make create template from volume/snapshot work

This commit is contained in:
Edison Su 2013-05-07 17:46:10 -07:00
parent ac1b75dc9f
commit 5aeca646ae
10 changed files with 407 additions and 41 deletions

View File

@ -53,6 +53,7 @@ import org.apache.cloudstack.storage.command.CopyCommand;
import org.apache.cloudstack.storage.command.DownloadCommand; import org.apache.cloudstack.storage.command.DownloadCommand;
import org.apache.cloudstack.storage.command.DownloadProgressCommand; import org.apache.cloudstack.storage.command.DownloadProgressCommand;
import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType; import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType;
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
import org.apache.cloudstack.storage.to.TemplateObjectTO; import org.apache.cloudstack.storage.to.TemplateObjectTO;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -103,6 +104,7 @@ import com.cloud.agent.api.to.SwiftTO;
import com.cloud.exception.InternalErrorException; import com.cloud.exception.InternalErrorException;
import com.cloud.host.Host; import com.cloud.host.Host;
import com.cloud.host.Host.Type; import com.cloud.host.Host.Type;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.resource.ServerResourceBase; import com.cloud.resource.ServerResourceBase;
import com.cloud.storage.DataStoreRole; import com.cloud.storage.DataStoreRole;
import com.cloud.storage.StorageLayer; import com.cloud.storage.StorageLayer;
@ -110,10 +112,14 @@ import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.template.DownloadManager; import com.cloud.storage.template.DownloadManager;
import com.cloud.storage.template.DownloadManagerImpl; import com.cloud.storage.template.DownloadManagerImpl;
import com.cloud.storage.template.DownloadManagerImpl.ZfsPathParser; import com.cloud.storage.template.DownloadManagerImpl.ZfsPathParser;
import com.cloud.storage.template.Processor.FormatInfo;
import com.cloud.storage.template.Processor;
import com.cloud.storage.template.QCOW2Processor;
import com.cloud.storage.template.TemplateLocation; import com.cloud.storage.template.TemplateLocation;
import com.cloud.storage.template.TemplateProp; import com.cloud.storage.template.TemplateProp;
import com.cloud.storage.template.UploadManager; import com.cloud.storage.template.UploadManager;
import com.cloud.storage.template.UploadManagerImpl; import com.cloud.storage.template.UploadManagerImpl;
import com.cloud.storage.template.VhdProcessor;
import com.cloud.utils.NumbersUtil; import com.cloud.utils.NumbersUtil;
import com.cloud.utils.S3Utils; import com.cloud.utils.S3Utils;
import com.cloud.utils.S3Utils.FileNamingStrategy; import com.cloud.utils.S3Utils.FileNamingStrategy;
@ -161,6 +167,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
final private String _parent = "/mnt/SecStorage"; final private String _parent = "/mnt/SecStorage";
final private String _tmpltDir = "/var/cloudstack/template"; final private String _tmpltDir = "/var/cloudstack/template";
final private String _tmpltpp = "template.properties"; final private String _tmpltpp = "template.properties";
private String createTemplateFromSnapshotXenScript;
@Override @Override
public void disconnected() { public void disconnected() {
@ -280,11 +287,90 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
return new CopyCmdAnswer(errMsg); return new CopyCmdAnswer(errMsg);
} }
} }
protected Answer copySnapshotToTemplateFromNfsToNfsXenserver(CopyCommand cmd, SnapshotObjectTO srcData, NfsTO srcDataStore, TemplateObjectTO destData, NfsTO destDataStore) {
String srcMountPoint = this.getRootDir(srcDataStore.getUrl());
String snapshotPath = srcData.getPath();
int index = snapshotPath.lastIndexOf("/");
String snapshotName = snapshotPath.substring(index + 1);
if (!snapshotName.startsWith("VHD-") && !snapshotName.endsWith(".vhd")) {
snapshotName = snapshotName + ".vhd";
}
snapshotPath = snapshotPath.substring(0, index);
snapshotPath = srcMountPoint + snapshotPath;
String destMountPoint = this.getRootDir(destDataStore.getUrl());
String destPath = destMountPoint + destData.getPath();
protected Answer copyFromSwiftToNfs(CopyCommand cmd, DataTO srcData, SwiftTO srcImageStore, String errMsg = null;
try {
this._storage.mkdir(destPath);
DataTO destData, NfsTO destImageStore) { String templateUuid = UUID.randomUUID().toString();
return Answer.createUnsupportedCommandAnswer(cmd); String templateName = templateUuid + ".vhd";
Script command = new Script(this.createTemplateFromSnapshotXenScript, cmd.getWait(), s_logger);
command.add("-p", snapshotPath);
command.add("-s", snapshotName);
command.add("-n", templateName);
command.add("-t", destPath);
command.execute();
Map<String, Object> params = new HashMap<String, Object>();
params.put(StorageLayer.InstanceConfigKey, _storage);
Processor processor = new VhdProcessor();
processor.configure("Vhd Processor", params);
FormatInfo info = processor.process(destPath, null,
templateUuid);
TemplateLocation loc = new TemplateLocation(_storage, destPath);
loc.create(1, true, templateName);
loc.addFormat(info);
loc.save();
TemplateObjectTO newTemplate = new TemplateObjectTO();
newTemplate.setPath(destData.getPath() + File.separator + templateUuid);
return new CopyCmdAnswer(newTemplate);
} catch (ConfigurationException e) {
s_logger.debug("Failed to create template from snapshot: " + e.toString());
errMsg = e.toString();
} catch (InternalErrorException e) {
s_logger.debug("Failed to create template from snapshot: " + e.toString());
errMsg = e.toString();
} catch (IOException e) {
s_logger.debug("Failed to create template from snapshot: " + e.toString());
errMsg = e.toString();
}
return new CopyCmdAnswer(errMsg);
}
protected Answer copySnapshotToTemplateFromNfsToNfs(CopyCommand cmd, SnapshotObjectTO srcData, NfsTO srcDataStore, TemplateObjectTO destData, NfsTO destDataStore) {
if (srcData.getHypervisorType() == HypervisorType.XenServer) {
return copySnapshotToTemplateFromNfsToNfsXenserver(cmd, srcData, srcDataStore, destData, destDataStore);
}
return new CopyCmdAnswer("");
}
protected Answer createTemplateFromSnapshot(CopyCommand cmd) {
DataTO srcData = cmd.getSrcTO();
DataTO destData = cmd.getDestTO();
DataStoreTO srcDataStore = srcData.getDataStore();
DataStoreTO destDataStore = destData.getDataStore();
if (srcDataStore.getRole() == DataStoreRole.Image || srcDataStore.getRole() == DataStoreRole.ImageCache) {
if (!(srcDataStore instanceof NfsTO)) {
s_logger.debug("only support nfs storage as src, when create template from snapshot");
return Answer.createUnsupportedCommandAnswer(cmd);
}
if (destDataStore instanceof NfsTO){
return copySnapshotToTemplateFromNfsToNfs(cmd, (SnapshotObjectTO)srcData, (NfsTO)srcDataStore, (TemplateObjectTO)destData, (NfsTO)destDataStore);
}
}
return new CopyCmdAnswer("");
} }
protected Answer execute(CopyCommand cmd) { protected Answer execute(CopyCommand cmd) {
@ -292,23 +378,12 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
DataTO destData = cmd.getDestTO(); DataTO destData = cmd.getDestTO();
DataStoreTO srcDataStore = srcData.getDataStore(); DataStoreTO srcDataStore = srcData.getDataStore();
DataStoreTO destDataStore = destData.getDataStore(); DataStoreTO destDataStore = destData.getDataStore();
if (srcDataStore.getRole() == DataStoreRole.Image && destDataStore.getRole() == DataStoreRole.ImageCache) { if (srcData.getObjectType() == DataObjectType.SNAPSHOT && destData.getObjectType() == DataObjectType.TEMPLATE) {
return createTemplateFromSnapshot(cmd);
if (!(destDataStore instanceof NfsTO)) {
s_logger.debug("only support nfs as cache storage");
return Answer.createUnsupportedCommandAnswer(cmd);
}
if (srcDataStore instanceof S3TO) {
return copyFromS3ToNfs(cmd, srcData, (S3TO) srcDataStore, destData, (NfsTO) destDataStore);
} else if (srcDataStore instanceof SwiftTO) {
return copyFromSwiftToNfs(cmd, srcData, (SwiftTO) srcDataStore, destData, (NfsTO) destDataStore);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
} }
return Answer.createUnsupportedCommandAnswer(cmd); return Answer.createUnsupportedCommandAnswer(cmd);
} }
@ -1652,6 +1727,11 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
if (_configIpFirewallScr != null) { if (_configIpFirewallScr != null) {
s_logger.info("_configIpFirewallScr found in " + _configIpFirewallScr); s_logger.info("_configIpFirewallScr found in " + _configIpFirewallScr);
} }
createTemplateFromSnapshotXenScript = Script.findScript(getDefaultScriptsDir(), "create_privatetemplate_from_snapshot_xen.sh");
if (createTemplateFromSnapshotXenScript == null) {
throw new ConfigurationException("create_privatetemplate_from_snapshot_xen.sh not found in " + getDefaultScriptsDir());
}
_role = (String) params.get("role"); _role = (String) params.get("role");
if (_role == null) if (_role == null)

View File

@ -5,6 +5,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import com.cloud.agent.api.to.DataStoreTO; import com.cloud.agent.api.to.DataStoreTO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
public class SnapshotObjectTO implements DataTO { public class SnapshotObjectTO implements DataTO {
private String path; private String path;
@ -13,6 +14,7 @@ public class SnapshotObjectTO implements DataTO {
private DataStoreTO dataStore; private DataStoreTO dataStore;
private String vmName; private String vmName;
private String name; private String name;
private HypervisorType hypervisorType;
private long id; private long id;
public SnapshotObjectTO() { public SnapshotObjectTO() {
@ -29,6 +31,7 @@ public class SnapshotObjectTO implements DataTO {
} }
this.dataStore = snapshot.getDataStore().getTO(); this.dataStore = snapshot.getDataStore().getTO();
this.setName(snapshot.getName()); this.setName(snapshot.getName());
this.hypervisorType = snapshot.getHypervisorType();
} }
@Override @Override
@ -89,4 +92,12 @@ public class SnapshotObjectTO implements DataTO {
public void setName(String name) { public void setName(String name) {
this.name = name; this.name = name;
} }
public HypervisorType getHypervisorType() {
return hypervisorType;
}
public void setHypervisorType(HypervisorType hypervisorType) {
this.hypervisorType = hypervisorType;
}
} }

View File

@ -327,7 +327,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
.parseInt(Config.CreatePrivateTemplateFromSnapshotWait .parseInt(Config.CreatePrivateTemplateFromSnapshotWait
.getDefaultValue())); .getDefaultValue()));
if (srcData.getDataStore().getRole() != DataStoreRole.ImageCache && destData.getDataStore().getRole() != DataStoreRole.ImageCache) { if (needCacheStorage(srcData, destData)) {
SnapshotInfo snapshot = (SnapshotInfo)srcData; SnapshotInfo snapshot = (SnapshotInfo)srcData;
srcData = cacheSnapshotChain(snapshot); srcData = cacheSnapshotChain(snapshot);
} }

View File

@ -94,6 +94,9 @@ public class CloudStackTestNGBase extends AbstractTestNGSpringContextTests {
this.s3TemplateBucket = s3_template_bucket; this.s3TemplateBucket = s3_template_bucket;
this.s3UseHttps = Boolean.parseBoolean(s3_usehttps); this.s3UseHttps = Boolean.parseBoolean(s3_usehttps);
this.scriptPath = scriptPath; this.scriptPath = scriptPath;
if (this.scriptPath != null) {
System.setProperty("paths.script", this.getScriptPath());
}
} }
protected String getHostGuid() { protected String getHostGuid() {

View File

@ -29,6 +29,7 @@ import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
@ -45,6 +46,8 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreState
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult;
import org.apache.cloudstack.engine.subsystem.api.storage.type.RootDisk; import org.apache.cloudstack.engine.subsystem.api.storage.type.RootDisk;
import org.apache.cloudstack.framework.async.AsyncCallFuture; import org.apache.cloudstack.framework.async.AsyncCallFuture;
import org.apache.cloudstack.storage.LocalHostEndpoint;
import org.apache.cloudstack.storage.MockLocalNfsSecondaryStorageResource;
import org.apache.cloudstack.storage.RemoteHostEndPoint; import org.apache.cloudstack.storage.RemoteHostEndPoint;
import org.apache.cloudstack.storage.command.CopyCmdAnswer; import org.apache.cloudstack.storage.command.CopyCmdAnswer;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
@ -144,6 +147,7 @@ public class SnapshotTest extends CloudStackTestNGBase {
SnapshotDao snapshotDao; SnapshotDao snapshotDao;
@Inject @Inject
EndPointSelector epSelector; EndPointSelector epSelector;
long primaryStoreId; long primaryStoreId;
VMTemplateVO image; VMTemplateVO image;
String imageStoreName = "testImageStore"; String imageStoreName = "testImageStore";
@ -196,7 +200,7 @@ public class SnapshotTest extends CloudStackTestNGBase {
imageStore = new ImageStoreVO(); imageStore = new ImageStoreVO();
imageStore.setName(imageStoreName); imageStore.setName(imageStoreName);
imageStore.setDataCenterId(dcId); imageStore.setDataCenterId(dcId);
imageStore.setProviderName("CloudStack ImageStore Provider"); imageStore.setProviderName(DataStoreProvider.NFS_IMAGE);
imageStore.setRole(DataStoreRole.Image); imageStore.setRole(DataStoreRole.Image);
imageStore.setUrl(this.getSecondaryStorage()); imageStore.setUrl(this.getSecondaryStorage());
imageStore.setUuid(UUID.randomUUID().toString()); imageStore.setUuid(UUID.randomUUID().toString());
@ -301,7 +305,7 @@ public class SnapshotTest extends CloudStackTestNGBase {
pool.setPoolType(StoragePoolType.NetworkFilesystem); pool.setPoolType(StoragePoolType.NetworkFilesystem);
pool.setPodId(podId); pool.setPodId(podId);
pool.setScope(ScopeType.CLUSTER); pool.setScope(ScopeType.CLUSTER);
pool.setStorageProviderName("cloudstack primary data store provider"); pool.setStorageProviderName(DataStoreProvider.DEFAULT_PRIMARY);
pool = this.primaryStoreDao.persist(pool); pool = this.primaryStoreDao.persist(pool);
DataStore store = this.dataStoreMgr.getPrimaryDataStore(pool.getId()); DataStore store = this.dataStoreMgr.getPrimaryDataStore(pool.getId());
return store; return store;
@ -359,15 +363,49 @@ public class SnapshotTest extends CloudStackTestNGBase {
} }
} }
} }
//@Test private VMTemplateVO createTemplateInDb() {
public void testCreateDataDisk() { image = new VMTemplateVO();
DataStore primaryStore = createPrimaryDataStore(); image.setTemplateType(TemplateType.USER);
primaryStoreId = primaryStore.getId();
primaryStore = this.dataStoreMgr.getPrimaryDataStore(primaryStoreId); image.setUniqueName(UUID.randomUUID().toString());
VolumeVO volume = createVolume(null, primaryStore.getId()); image.setName(UUID.randomUUID().toString());
VolumeInfo volInfo = this.volFactory.getVolume(volume.getId()); image.setPublicTemplate(true);
this.volumeService.createVolumeAsync(volInfo, primaryStore); image.setFeatured(true);
image.setRequiresHvm(true);
image.setBits(64);
image.setFormat(Storage.ImageFormat.VHD);
image.setEnablePassword(true);
image.setEnableSshKey(true);
image.setGuestOSId(1);
image.setBootable(true);
image.setPrepopulate(true);
image.setCrossZones(true);
image.setExtractable(true);
image = imageDataDao.persist(image);
return image;
}
@Test
public void createTemplateFromSnapshot() {
VolumeInfo vol = createCopyBaseImage();
SnapshotVO snapshotVO = createSnapshotInDb(vol);
SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore());
boolean result = false;
for (SnapshotStrategy strategy : this.snapshotStrategies) {
if (strategy.canHandle(snapshot)) {
snapshot = strategy.takeSnapshot(snapshot);
result = true;
}
}
AssertJUnit.assertTrue(result);
LocalHostEndpoint ep = new LocalHostEndpoint();
ep.setResource(new MockLocalNfsSecondaryStorageResource());
Mockito.when(epSelector.select(Mockito.any(DataObject.class), Mockito.any(DataObject.class))).thenReturn(ep);
VMTemplateVO templateVO = createTemplateInDb();
TemplateInfo tmpl = this.templateFactory.getTemplate(templateVO.getId());
DataStore imageStore = this.dataStoreMgr.getImageStore(this.dcId);
this.imageService.createTemplateFromSnapshotAsync(snapshot, tmpl, imageStore);
} }
} }

View File

@ -68,7 +68,7 @@ public class TemplateTest extends CloudStackTestNGBase {
@Test(priority = -1) @Test(priority = -1)
public void setUp() { public void setUp() {
ComponentContext.initComponentsLifeCycle(); ComponentContext.initComponentsLifeCycle();
System.setProperty("paths.script", this.getScriptPath());
//create data center //create data center
DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24", DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24",
null, null, NetworkType.Basic, null, null, true, true, null, null); null, null, NetworkType.Basic, null, null, true, true, null, null);

View File

@ -379,4 +379,55 @@ public class VolumeTest extends CloudStackTestNGBase {
} }
} }
private VMTemplateVO createTemplateInDb() {
image = new VMTemplateVO();
image.setTemplateType(TemplateType.USER);
image.setUniqueName(UUID.randomUUID().toString());
image.setName(UUID.randomUUID().toString());
image.setPublicTemplate(true);
image.setFeatured(true);
image.setRequiresHvm(true);
image.setBits(64);
image.setFormat(Storage.ImageFormat.VHD);
image.setEnablePassword(true);
image.setEnableSshKey(true);
image.setGuestOSId(1);
image.setBootable(true);
image.setPrepopulate(true);
image.setCrossZones(true);
image.setExtractable(true);
image = imageDataDao.persist(image);
return image;
}
@Test
public void testCreateTemplateFromVolume() {
DataStore primaryStore = createPrimaryDataStore();
primaryStoreId = primaryStore.getId();
primaryStore = this.dataStoreMgr.getPrimaryDataStore(primaryStoreId);
VolumeVO volume = createVolume(null, primaryStore.getId());
VolumeInfo volInfo = this.volFactory.getVolume(volume.getId());
AsyncCallFuture<VolumeApiResult> future = this.volumeService.createVolumeAsync(volInfo, primaryStore);
try {
VolumeApiResult result = future.get();
AssertJUnit.assertTrue(result.isSuccess());
volInfo = result.getVolume();
VMTemplateVO templateVO = createTemplateInDb();
TemplateInfo tmpl = this.templateFactory.getTemplate(templateVO.getId());
DataStore imageStore = this.dataStoreMgr.getImageStore(this.dcId);
this.imageService.createTemplateFromVolumeAsync(volInfo, tmpl, imageStore);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} }

View File

@ -83,6 +83,16 @@ public class DefaultEndPointSelector implements EndPointSelector {
return false; return false;
} }
} }
protected boolean moveBetweenImages(DataStore srcStore, DataStore destStore) {
DataStoreRole srcRole = srcStore.getRole();
DataStoreRole destRole = destStore.getRole();
if (srcRole == DataStoreRole.Image && destRole == DataStoreRole.Image) {
return true;
} else {
return false;
}
}
@DB @DB
protected EndPoint findEndPointInScope(Scope scope, String sqlBase) { protected EndPoint findEndPointInScope(Scope scope, String sqlBase) {
@ -162,12 +172,11 @@ public class DefaultEndPointSelector implements EndPointSelector {
if (moveBetweenPrimaryImage(srcStore, destStore)) { if (moveBetweenPrimaryImage(srcStore, destStore)) {
return findEndPointForImageMove(srcStore, destStore); return findEndPointForImageMove(srcStore, destStore);
} else if (moveBetweenCacheAndImage(srcStore, destStore)) { } else if (moveBetweenCacheAndImage(srcStore, destStore)) {
EndPoint ep = findEndPointForImageMove(srcStore, destStore); EndPoint ep = findEndpointForImageStorage(destStore);
if (ep == null) {
//if there is no ssvm agent running, use mgt server
ep = new LocalHostEndpoint();
}
return ep; return ep;
} else if (moveBetweenImages(srcStore, destStore)) {
EndPoint ep = findEndpointForImageStorage(destStore);
return ep;
} }
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return null;

View File

@ -70,6 +70,7 @@ import com.cloud.agent.api.ManageSnapshotAnswer;
import com.cloud.agent.api.ManageSnapshotCommand; import com.cloud.agent.api.ManageSnapshotCommand;
import com.cloud.agent.api.storage.CopyVolumeAnswer; import com.cloud.agent.api.storage.CopyVolumeAnswer;
import com.cloud.agent.api.storage.CreateAnswer; import com.cloud.agent.api.storage.CreateAnswer;
import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
import com.cloud.agent.api.storage.DeleteVolumeCommand; import com.cloud.agent.api.storage.DeleteVolumeCommand;
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
import com.cloud.agent.api.to.DataStoreTO; import com.cloud.agent.api.to.DataStoreTO;
@ -81,6 +82,7 @@ import com.cloud.agent.api.to.VolumeTO;
import com.cloud.exception.InternalErrorException; import com.cloud.exception.InternalErrorException;
import com.cloud.hypervisor.xen.resource.CitrixResourceBase.SRType; import com.cloud.hypervisor.xen.resource.CitrixResourceBase.SRType;
import com.cloud.storage.DataStoreRole; import com.cloud.storage.DataStoreRole;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.utils.S3Utils; import com.cloud.utils.S3Utils;
import com.cloud.utils.StringUtils; import com.cloud.utils.StringUtils;
import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.CloudRuntimeException;
@ -1200,7 +1202,7 @@ public class XenServerStorageResource {
destroySnapshotOnPrimaryStorageExceptThis(conn, volumeUuid, snapshotUuid); destroySnapshotOnPrimaryStorageExceptThis(conn, volumeUuid, snapshotUuid);
SnapshotObjectTO newSnapshot = new SnapshotObjectTO(); SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
newSnapshot.setPath(snapshotBackupUuid); newSnapshot.setPath(folder + File.separator + snapshotBackupUuid);
if (fullbackup) { if (fullbackup) {
newSnapshot.setParentSnapshotPath(null); newSnapshot.setParentSnapshotPath(null);
} else { } else {
@ -1217,6 +1219,76 @@ public class XenServerStorageResource {
return new CopyCmdAnswer(details); return new CopyCmdAnswer(details);
} }
protected CopyCmdAnswer createTemplateFromVolume(DataTO srcData, DataTO destData, int wait) {
Connection conn = this.hypervisorResource.getConnection();
VolumeObjectTO volume = (VolumeObjectTO)srcData;
TemplateObjectTO template = (TemplateObjectTO)destData;
NfsTO destStore = (NfsTO)destData.getDataStore();
String secondaryStoragePoolURL = destStore.getUrl();
String volumeUUID = volume.getPath();
String userSpecifiedName = template.getName();
String details = null;
SR tmpltSR = null;
boolean result = false;
String secondaryStorageMountPath = null;
String installPath = null;
try {
URI uri = new URI(secondaryStoragePoolURL);
secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath();
installPath = template.getPath();
if( !this.hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath)) {
details = " Filed to create folder " + installPath + " in secondary storage";
s_logger.warn(details);
return new CopyCmdAnswer(details);
}
VDI vol = getVDIbyUuid(conn, volumeUUID);
// create template SR
URI tmpltURI = new URI(secondaryStoragePoolURL + "/" + installPath);
tmpltSR = this.hypervisorResource.createNfsSRbyURI(conn, tmpltURI, false);
// copy volume to template SR
VDI tmpltVDI = this.hypervisorResource.cloudVDIcopy(conn, vol, tmpltSR, wait);
// scan makes XenServer pick up VDI physicalSize
tmpltSR.scan(conn);
if (userSpecifiedName != null) {
tmpltVDI.setNameLabel(conn, userSpecifiedName);
}
String tmpltUUID = tmpltVDI.getUuid(conn);
String tmpltFilename = tmpltUUID + ".vhd";
long virtualSize = tmpltVDI.getVirtualSize(conn);
long physicalSize = tmpltVDI.getPhysicalUtilisation(conn);
// create the template.properties file
String templatePath = secondaryStorageMountPath + "/" + installPath;
result = this.hypervisorResource.postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUUID, userSpecifiedName, null, physicalSize, virtualSize, template.getId());
if (!result) {
throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir: " + tmpltURI);
}
installPath = installPath + "/" + tmpltFilename;
this.hypervisorResource.removeSR(conn, tmpltSR);
tmpltSR = null;
TemplateObjectTO newTemplate = new TemplateObjectTO();
newTemplate.setPath(installPath);
CopyCmdAnswer answer = new CopyCmdAnswer(newTemplate);
return answer;
} catch (Exception e) {
if (tmpltSR != null) {
this.hypervisorResource.removeSR(conn, tmpltSR);
}
if ( secondaryStorageMountPath != null) {
this.hypervisorResource.deleteSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath);
}
details = "Creating template from volume " + volumeUUID + " failed due to " + e.toString();
s_logger.error(details, e);
}
return new CopyCmdAnswer(details);
}
protected Answer execute(CopyCommand cmd) { protected Answer execute(CopyCommand cmd) {
DataTO srcData = cmd.getSrcTO(); DataTO srcData = cmd.getSrcTO();
@ -1235,11 +1307,15 @@ public class XenServerStorageResource {
} else if (srcData.getObjectType() == DataObjectType.TEMPLATE && srcDataStore.getRole() == DataStoreRole.Primary && destDataStore.getRole() == DataStoreRole.Primary) { } else if (srcData.getObjectType() == DataObjectType.TEMPLATE && srcDataStore.getRole() == DataStoreRole.Primary && destDataStore.getRole() == DataStoreRole.Primary) {
//clone template to a volume //clone template to a volume
return cloneVolumeFromBaseTemplate(srcData, destData); return cloneVolumeFromBaseTemplate(srcData, destData);
} else if (srcData.getObjectType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.ImageCache) { } else if (srcData.getObjectType() == DataObjectType.VOLUME && (srcData.getDataStore().getRole() == DataStoreRole.ImageCache || srcDataStore.getRole() == DataStoreRole.Image)) {
//copy volume from image cache to primary //copy volume from image cache to primary
return copyVolumeFromImageCacheToPrimary(srcData, destData, cmd.getWait()); return copyVolumeFromImageCacheToPrimary(srcData, destData, cmd.getWait());
} else if (srcData.getObjectType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.Primary) { } else if (srcData.getObjectType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.Primary) {
return copyVolumeFromPrimaryToSecondary(srcData, destData, cmd.getWait()); if (destData.getObjectType() == DataObjectType.VOLUME) {
return copyVolumeFromPrimaryToSecondary(srcData, destData, cmd.getWait());
} else if (destData.getObjectType() == DataObjectType.TEMPLATE) {
return createTemplateFromVolume(srcData, destData, cmd.getWait());
}
} else if (srcData.getObjectType() == DataObjectType.SNAPSHOT && srcData.getDataStore().getRole() == DataStoreRole.Primary) { } else if (srcData.getObjectType() == DataObjectType.SNAPSHOT && srcData.getDataStore().getRole() == DataStoreRole.Primary) {
DataTO cacheData = cmd.getCacheTO(); DataTO cacheData = cmd.getCacheTO();
return backupSnasphot(srcData, destData, cacheData, cmd.getWait()); return backupSnasphot(srcData, destData, cacheData, cmd.getWait());

View File

@ -0,0 +1,98 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#set -x
usage() {
printf "Usage: %s -t [template path] -n [template name] -s [snapshot name] -p [snapshot path] \n" $(basename $0)
}
snapshotPath=
snapshotName=
templatePath=
templateName=
while getopts ':s:n:t:p:' OPTION
do
case $OPTION in
t) tflag=1
templatePath="$OPTARG"
;;
n) nflag=1
templateName="$OPTARG"
;;
s) sflag=1
snapshotName="$OPTARG"
;;
p) pflag=1
snapshotPath="$OPTARG"
;;
?) usage
exit 2
;;
esac
done
if [ "$sflag$nflag$tflag$pflag" != "1111" ]
then
usage
exit 1
fi
VHDUTIL="/bin/vhd-util"
desvhd=$templatePath/$templateName
srcvhd=$snapshotPath/$snapshotName
copyvhd()
{
local desvhd=$1
local srcvhd=$2
local parent=
parent=`$VHDUTIL query -p -n $srcvhd`
if [ $? -ne 0 ]; then
echo "30#failed to query $srcvhd"
exit 2
fi
if [[ "${parent}" =~ " no parent" ]]; then
dd if=$srcvhd of=$desvhd bs=2M
if [ $? -ne 0 ]; then
echo "31#failed to dd $srcvhd to $desvhd"
rm -rf $desvhd > /dev/null
exit 0
fi
else
copyvhd $desvhd $parent
$VHDUTIL coalesce -p $desvhd -n $srcvhd
if [ $? -ne 0 ]; then
echo "32#failed to coalesce $desvhd to $srcvhd"
rm -rf $desvhd > /dev/null
exit 0
fi
fi
}
copyvhd $desvhd $srcvhd
imgsize=$(ls -l $desvhd| awk -F" " '{print $5}')
propertyFile=/$templatePath/template.properties
touch $propertyFile
echo -n "" > $propertyFile
echo "filename=$templateName" > $propertyFile
echo "hvm=$hvm" >> $propertyFile
echo "size=$imgsize" >> $propertyFile
exit 0