You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ed...@apache.org on 2013/12/11 02:23:42 UTC
[2/3] git commit: updated refs/heads/4.2-workplace to 514c3da
basical stuff works
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/e8a87bbf
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/e8a87bbf
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/e8a87bbf
Branch: refs/heads/4.2-workplace
Commit: e8a87bbf05a7d863e9406e3472eb9768ef187fa1
Parents: 4cd6f31
Author: Edison Su <su...@gmail.com>
Authored: Tue Dec 10 17:16:51 2013 -0800
Committer: Edison Su <su...@gmail.com>
Committed: Tue Dec 10 17:16:51 2013 -0800
----------------------------------------------------------------------
.../xen/resource/XenServer620Resource.java | 8 +
.../xen/resource/XenServerStorageProcessor.java | 9 +-
.../resource/Xenserver620StorageProcessor.java | 636 +++++++++++++++++++
3 files changed, 649 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e8a87bbf/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer620Resource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer620Resource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer620Resource.java
index 0d6e159..e623aca 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer620Resource.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer620Resource.java
@@ -27,6 +27,8 @@ import org.apache.log4j.Logger;
import org.apache.cloudstack.hypervisor.xenserver.XenServerResourceNewBase;
import com.cloud.resource.ServerResource;
+import com.cloud.storage.resource.StorageSubsystemCommandHandler;
+import com.cloud.storage.resource.StorageSubsystemCommandHandlerBase;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;
@@ -86,4 +88,10 @@ public class XenServer620Resource extends XenServerResourceNewBase {
return dynamicMinRam;
}
+ @Override
+ protected StorageSubsystemCommandHandler getStorageHandler() {
+ XenServerStorageProcessor processor = new Xenserver620StorageProcessor(this);
+ return new StorageSubsystemCommandHandlerBase(processor);
+ }
+
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e8a87bbf/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
index a90c829..c89e58a 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
@@ -88,7 +88,7 @@ import com.xensource.xenapi.VMGuestMetrics;
public class XenServerStorageProcessor implements StorageProcessor {
private static final Logger s_logger = Logger.getLogger(XenServerStorageProcessor.class);
protected CitrixResourceBase hypervisorResource;
- private String BaseMountPointOnHost = "/var/run/cloud_mount";
+ protected String BaseMountPointOnHost = "/var/run/cloud_mount";
public XenServerStorageProcessor(CitrixResourceBase resource) {
hypervisorResource = resource;
@@ -446,6 +446,7 @@ public class XenServerStorageProcessor implements StorageProcessor {
return new CreateObjectAnswer(details);
}
+
@Override
public Answer deleteVolume(DeleteCommand cmd) {
DataTO volume = cmd.getData();
@@ -767,7 +768,7 @@ public class XenServerStorageProcessor implements StorageProcessor {
}
}
- private boolean IsISCSI(String type) {
+ protected boolean IsISCSI(String type) {
return SRType.LVMOHBA.equals(type) || SRType.LVMOISCSI.equals(type) || SRType.LVM.equals(type) ;
}
@@ -1069,7 +1070,7 @@ public class XenServerStorageProcessor implements StorageProcessor {
return lfilename;
}
- private String backupSnapshotToS3(final Connection connection, final S3TO s3, final String srUuid, final String folder, final String snapshotUuid,
+ protected String backupSnapshotToS3(final Connection connection, final S3TO s3, final String srUuid, final String folder, final String snapshotUuid,
final Boolean iSCSIFlag, final int wait) {
final String filename = iSCSIFlag ? "VHD-" + snapshotUuid
@@ -1182,7 +1183,7 @@ public class XenServerStorageProcessor implements StorageProcessor {
}
}
- private boolean destroySnapshotOnPrimaryStorageExceptThis(Connection conn, String volumeUuid, String avoidSnapshotUuid){
+ protected boolean destroySnapshotOnPrimaryStorageExceptThis(Connection conn, String volumeUuid, String avoidSnapshotUuid){
try {
VDI volume = getVDIbyUuid(conn, volumeUuid);
if (volume == null) {
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e8a87bbf/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/Xenserver620StorageProcessor.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/Xenserver620StorageProcessor.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/Xenserver620StorageProcessor.java
new file mode 100644
index 0000000..2d80747
--- /dev/null
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/Xenserver620StorageProcessor.java
@@ -0,0 +1,636 @@
+/*
+ * 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.
+ */
+package com.cloud.hypervisor.xen.resource;
+
+import java.io.File;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.cloudstack.storage.command.CopyCmdAnswer;
+import org.apache.cloudstack.storage.command.CopyCommand;
+import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
+import org.apache.cloudstack.storage.to.SnapshotObjectTO;
+import org.apache.cloudstack.storage.to.TemplateObjectTO;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.to.DataObjectType;
+import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
+import com.cloud.agent.api.to.NfsTO;
+import com.cloud.agent.api.to.S3TO;
+import com.cloud.agent.api.to.SwiftTO;
+import com.cloud.exception.InternalErrorException;
+import com.cloud.storage.Storage;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.xensource.xenapi.Connection;
+import com.xensource.xenapi.SR;
+import com.xensource.xenapi.Task;
+import com.xensource.xenapi.Types;
+import com.xensource.xenapi.VDI;
+
+public class Xenserver620StorageProcessor extends XenServerStorageProcessor {
+ private static final Logger s_logger = Logger.getLogger(XenServerStorageProcessor.class);
+
+ public Xenserver620StorageProcessor(CitrixResourceBase resource) {
+ super(resource);
+ }
+ protected boolean mountNfs(Connection conn, String remoteDir, String localDir) {
+ if (localDir == null) {
+ localDir = "/var/cloud_mount/" + UUID.randomUUID().toString();
+ }
+ String results = hypervisorResource.callHostPluginAsync(conn, "cloud-plugin-snapshot", "mountNfsSecondaryStorage", 100 * 1000,
+ "localDir", localDir, "remoteDir", remoteDir);
+ if (results == null || results.isEmpty()) {
+ String errMsg = "Could not mount secondary storage " + remoteDir + " on host ";
+ s_logger.warn(errMsg);
+ throw new CloudRuntimeException(errMsg);
+ }
+ return true;
+ }
+ protected SR createFileSr(Connection conn, String remotePath, String dir) {
+ String localDir = "/var/cloud_mount/" + UUID.randomUUID().toString();
+ mountNfs(conn, remotePath, localDir);
+ SR sr = hypervisorResource.createFileSR(conn, localDir + "/" + dir);
+ return sr;
+ }
+
+ @Override
+ public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) {
+ DataTO srcData = cmd.getSrcTO();
+ DataTO destData = cmd.getDestTO();
+ int wait = cmd.getWait();
+ DataStoreTO srcStore = srcData.getDataStore();
+ Connection conn = hypervisorResource.getConnection();
+ SR srcSr = null;
+ try {
+ if ((srcStore instanceof NfsTO) && (srcData.getObjectType() == DataObjectType.TEMPLATE)) {
+ NfsTO srcImageStore = (NfsTO)srcStore;
+ TemplateObjectTO srcTemplate = (TemplateObjectTO)srcData;
+ String storeUrl = srcImageStore.getUrl();
+ URI uri = new URI(storeUrl);
+ String volumePath = srcData.getPath();
+
+ int index = volumePath.lastIndexOf("/");
+ String volumeDirectory = volumePath.substring(0, index);
+ srcSr = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), volumeDirectory);
+ Set<VDI> vdis = srcSr.getVDIs(conn);
+ if (vdis.size() != 1) {
+ return new CopyCmdAnswer("Can't find template VDI under: " + uri.getHost() + ":" + uri.getPath() + "/" + volumeDirectory);
+ }
+
+ VDI srcVdi = vdis.iterator().next();
+
+ PrimaryDataStoreTO destStore = (PrimaryDataStoreTO)destData.getDataStore();
+ String poolName = destStore.getUuid();
+
+
+ SR poolsr = null;
+ Set<SR> srs = SR.getByNameLabel(conn, poolName);
+ if (srs.size() != 1) {
+ String msg = "There are " + srs.size() + " SRs with same name: " + poolName;
+ s_logger.warn(msg);
+ return new CopyCmdAnswer(msg);
+ } else {
+ poolsr = srs.iterator().next();
+ }
+ String pUuid = poolsr.getUuid(conn);
+ boolean isISCSI = IsISCSI(poolsr.getType(conn));
+ Task task = srcVdi.copyAsync(conn, poolsr, null, null);
+ // poll every 1 seconds ,
+ hypervisorResource.waitForTask(conn, task, 1000, wait * 1000);
+ hypervisorResource.checkForSuccess(conn, task);
+ VDI tmpl = Types.toVDI(task, conn);
+ VDI snapshotvdi = tmpl.snapshot(conn, new HashMap<String, String>());
+ String snapshotUuid = snapshotvdi.getUuid(conn);
+ snapshotvdi.setNameLabel(conn, "Template " + srcTemplate.getName());
+ String parentuuid = getVhdParent(conn, pUuid, snapshotUuid, isISCSI);
+ VDI parent = getVDIbyUuid(conn, parentuuid);
+ Long phySize = parent.getPhysicalUtilisation(conn);
+ tmpl.destroy(conn);
+ poolsr.scan(conn);
+ try{
+ Thread.sleep(5000);
+ } catch (Exception e) {
+ }
+
+ TemplateObjectTO newVol = new TemplateObjectTO();
+ newVol.setUuid(snapshotvdi.getUuid(conn));
+ newVol.setPath(newVol.getUuid());
+ newVol.setFormat(Storage.ImageFormat.VHD);
+ return new CopyCmdAnswer(newVol);
+ }
+ }catch (Exception e) {
+ String msg = "Catch Exception " + e.getClass().getName() + " for template + " + " due to " + e.toString();
+ s_logger.warn(msg, e);
+ return new CopyCmdAnswer(msg);
+ } finally {
+ if (srcSr != null) {
+ hypervisorResource.removeSR(conn, srcSr);
+ }
+ }
+ return new CopyCmdAnswer("not implemented yet");
+ }
+
+ protected String backupSnapshot(Connection conn, String primaryStorageSRUuid, String localMountPoint, String path, String secondaryStorageMountPath, String snapshotUuid, String prevBackupUuid, String prevSnapshotUuid, Boolean isISCSI, int wait) {
+ String errMsg = null;
+ boolean mounted = false;
+ boolean filesrcreated = false;
+ boolean copied = false;
+ if (prevBackupUuid == null) {
+ prevBackupUuid = "";
+ }
+ SR ssSR = null;
+
+ String remoteDir = secondaryStorageMountPath;
+
+ try {
+ ssSR = createFileSr(conn, remoteDir, path);
+ filesrcreated = true;
+
+ VDI snapshotvdi = VDI.getByUuid(conn, snapshotUuid);
+ Task task = null;
+ if (wait == 0) {
+ wait = 2 * 60 * 60;
+ }
+ VDI dvdi = null;
+ try {
+ VDI previousSnapshotVdi = null;
+ if (prevSnapshotUuid != null) {
+ previousSnapshotVdi = VDI.getByUuid(conn,prevSnapshotUuid);
+ }
+ task = snapshotvdi.copyAsync(conn, ssSR, previousSnapshotVdi, null);
+ // poll every 1 seconds ,
+ hypervisorResource.waitForTask(conn, task, 1000, wait * 1000);
+ hypervisorResource.checkForSuccess(conn, task);
+ dvdi = Types.toVDI(task, conn);
+ copied = true;
+ } catch (TimeoutException e) {
+ throw new CloudRuntimeException(e.toString());
+ } finally {
+ if (task != null) {
+ try {
+ task.destroy(conn);
+ } catch (Exception e1) {
+ s_logger.warn("unable to destroy task(" + task.toString() + ") on host("
+ + ") due to ", e1);
+ }
+ }
+ }
+ String backupUuid = dvdi.getUuid(conn);
+ return backupUuid;
+ } catch (Exception e) {
+ String msg = "Exception in backupsnapshot stage due to " + e.toString();
+ s_logger.debug(msg);
+ throw new CloudRuntimeException(msg, e);
+ } finally {
+ try {
+ if (filesrcreated && ssSR != null) {
+ hypervisorResource.removeSR(conn, ssSR);
+ }
+ } catch (Exception e) {
+ s_logger.debug("Exception in backupsnapshot cleanup stage due to " + e.toString());
+ }
+ }
+ }
+
+ @Override
+ public Answer backupSnapshot(CopyCommand cmd) {
+ Connection conn = hypervisorResource.getConnection();
+ DataTO srcData = cmd.getSrcTO();
+ DataTO cacheData = cmd.getCacheTO();
+ DataTO destData = cmd.getDestTO();
+ int wait = cmd.getWait();
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)srcData.getDataStore();
+ String primaryStorageNameLabel = primaryStore.getUuid();
+ String secondaryStorageUrl = null;
+ NfsTO cacheStore = null;
+ String destPath = null;
+ if (cacheData != null) {
+ cacheStore = (NfsTO)cacheData.getDataStore();
+ secondaryStorageUrl = cacheStore.getUrl();
+ destPath = cacheData.getPath();
+ } else {
+ cacheStore = (NfsTO)destData.getDataStore();
+ secondaryStorageUrl = cacheStore.getUrl();
+ destPath = destData.getPath();
+ }
+
+ SnapshotObjectTO snapshotTO = (SnapshotObjectTO)srcData;
+ SnapshotObjectTO snapshotOnImage = (SnapshotObjectTO)destData;
+ String snapshotUuid = snapshotTO.getPath();
+
+ String prevBackupUuid = snapshotOnImage.getParentSnapshotPath();
+ String prevSnapshotUuid = snapshotTO.getParentSnapshotPath();
+
+ // By default assume failure
+ String details = null;
+ String snapshotBackupUuid = null;
+ boolean fullbackup = true;
+ try {
+ SR primaryStorageSR = hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel);
+ if (primaryStorageSR == null) {
+ throw new InternalErrorException("Could not backup snapshot because the primary Storage SR could not be created from the name label: " + primaryStorageNameLabel);
+ }
+ String psUuid = primaryStorageSR.getUuid(conn);
+ Boolean isISCSI = IsISCSI(primaryStorageSR.getType(conn));
+
+ VDI snapshotVdi = getVDIbyUuid(conn, snapshotUuid);
+ String snapshotPaUuid = null;
+ if ( prevBackupUuid != null ) {
+ try {
+ snapshotPaUuid = getVhdParent(conn, psUuid, snapshotUuid, isISCSI);
+ if( snapshotPaUuid != null ) {
+ String snashotPaPaPaUuid = getVhdParent(conn, psUuid, snapshotPaUuid, isISCSI);
+ String prevSnashotPaUuid = getVhdParent(conn, psUuid, prevSnapshotUuid, isISCSI);
+ if (snashotPaPaPaUuid != null && prevSnashotPaUuid!= null && prevSnashotPaUuid.equals(snashotPaPaPaUuid)) {
+ fullbackup = false;
+ }
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ URI uri = new URI(secondaryStorageUrl);
+ String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath();
+ DataStoreTO destStore = destData.getDataStore();
+ String folder = destPath;
+ String finalPath = null;
+
+ String localMountPoint = BaseMountPointOnHost + File.separator + UUID.nameUUIDFromBytes(secondaryStorageUrl.getBytes()).toString();
+ if (fullbackup) {
+ // the first snapshot is always a full snapshot
+
+ if( !hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, folder)) {
+ details = " Filed to create folder " + folder + " in secondary storage";
+ s_logger.warn(details);
+ return new CopyCmdAnswer(details);
+ }
+ SR snapshotSr = null;
+ try {
+ snapshotSr = createFileSr(conn, secondaryStorageMountPath, folder);
+ Task task = snapshotVdi.copyAsync(conn, snapshotSr, null, null);
+ // poll every 1 seconds ,
+ hypervisorResource.waitForTask(conn, task, 1000, wait * 1000);
+ hypervisorResource.checkForSuccess(conn, task);
+ VDI backedVdi = Types.toVDI(task, conn);
+ snapshotBackupUuid = backedVdi.getUuid(conn);
+
+ if( destStore instanceof SwiftTO) {
+ try {
+ String container = "S-" + snapshotTO.getVolume().getVolumeId().toString();
+ String destSnapshotName = swiftBackupSnapshot(conn, (SwiftTO)destStore, snapshotSr.getUuid(conn), snapshotBackupUuid, container, false, wait);
+ String swiftPath = container + File.separator + destSnapshotName;
+ finalPath = swiftPath;
+ } finally {
+ try {
+ deleteSnapshotBackup(conn, localMountPoint, folder, secondaryStorageMountPath, snapshotBackupUuid);
+ } catch (Exception e) {
+ s_logger.debug("Failed to delete snapshot on cache storages" ,e);
+ }
+ }
+
+ } else if (destStore instanceof S3TO) {
+ try {
+ finalPath = backupSnapshotToS3(conn, (S3TO) destStore, snapshotSr.getUuid(conn), folder, snapshotBackupUuid, isISCSI, wait);
+ if (finalPath == null) {
+ throw new CloudRuntimeException("S3 upload of snapshots " + snapshotBackupUuid + " failed");
+ }
+ } finally {
+ try {
+ deleteSnapshotBackup(conn, localMountPoint, folder, secondaryStorageMountPath, snapshotBackupUuid);
+ } catch (Exception e) {
+ s_logger.debug("Failed to delete snapshot on cache storages" ,e);
+ }
+ }
+ // finalPath = folder + File.separator + snapshotBackupUuid;
+ } else {
+ finalPath = folder + File.separator + snapshotBackupUuid;
+ }
+
+ } finally {
+ if( snapshotSr != null) {
+ hypervisorResource.removeSR(conn, snapshotSr);
+ }
+ }
+ } else {
+ String primaryStorageSRUuid = primaryStorageSR.getUuid(conn);
+ if( destStore instanceof SwiftTO ) {
+ String container = "S-" + snapshotTO.getVolume().getVolumeId().toString();
+ snapshotBackupUuid = swiftBackupSnapshot(conn, (SwiftTO)destStore, primaryStorageSRUuid, snapshotPaUuid, "S-" + snapshotTO.getVolume().getVolumeId().toString(), isISCSI, wait);
+ finalPath = container + File.separator + snapshotBackupUuid;
+ } else if (destStore instanceof S3TO ) {
+ finalPath = backupSnapshotToS3(conn, (S3TO) destStore, primaryStorageSRUuid, folder, snapshotPaUuid, isISCSI, wait);
+ if (finalPath == null) {
+ throw new CloudRuntimeException("S3 upload of snapshots " + snapshotPaUuid + " failed");
+ }
+ } else {
+ snapshotBackupUuid = backupSnapshot(conn, primaryStorageSRUuid, localMountPoint, folder,
+ secondaryStorageMountPath, snapshotUuid, prevBackupUuid, prevSnapshotUuid, isISCSI, wait);
+
+ finalPath = folder + File.separator + snapshotBackupUuid;
+ }
+ }
+ String volumeUuid = snapshotTO.getVolume().getPath();
+ destroySnapshotOnPrimaryStorageExceptThis(conn, volumeUuid, snapshotUuid);
+
+ SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
+ newSnapshot.setPath(finalPath);
+ if (fullbackup) {
+ newSnapshot.setParentSnapshotPath(null);
+ } else {
+ newSnapshot.setParentSnapshotPath(prevBackupUuid);
+ }
+ return new CopyCmdAnswer(newSnapshot);
+ } catch (Types.XenAPIException e) {
+ details = "BackupSnapshot Failed due to " + e.toString();
+ s_logger.warn(details, e);
+ } catch (Exception e) {
+ details = "BackupSnapshot Failed due to " + e.getMessage();
+ s_logger.warn(details, e);
+ }
+
+ return new CopyCmdAnswer(details);
+ }
+
+ @Override
+ public Answer createTemplateFromVolume(CopyCommand cmd) {
+ Connection conn = hypervisorResource.getConnection();
+ VolumeObjectTO volume = (VolumeObjectTO)cmd.getSrcTO();
+ TemplateObjectTO template = (TemplateObjectTO)cmd.getDestTO();
+ NfsTO destStore = (NfsTO)cmd.getDestTO().getDataStore();
+ int wait = cmd.getWait();
+
+ 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( !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
+ tmpltSR = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), installPath);
+
+ // copy volume to template SR
+ Task task = vol.copyAsync(conn, tmpltSR, null, null);
+ // poll every 1 seconds ,
+ hypervisorResource.waitForTask(conn, task, 1000, wait * 1000);
+ hypervisorResource.checkForSuccess(conn, task);
+ VDI tmpltVDI = Types.toVDI(task, conn);
+ // 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 = 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");
+ }
+ installPath = installPath + "/" + tmpltFilename;
+ hypervisorResource.removeSR(conn, tmpltSR);
+ tmpltSR = null;
+ TemplateObjectTO newTemplate = new TemplateObjectTO();
+ newTemplate.setPath(installPath);
+ newTemplate.setFormat(Storage.ImageFormat.VHD);
+ newTemplate.setSize(virtualSize);
+ newTemplate.setPhysicalSize(physicalSize);
+ newTemplate.setName(tmpltUUID);
+ CopyCmdAnswer answer = new CopyCmdAnswer(newTemplate);
+ return answer;
+ } catch (Exception e) {
+ if (tmpltSR != null) {
+ hypervisorResource.removeSR(conn, tmpltSR);
+ }
+ if ( secondaryStorageMountPath != null) {
+ 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);
+ }
+
+ @Override
+ public Answer createVolumeFromSnapshot(CopyCommand cmd) {
+ Connection conn = hypervisorResource.getConnection();
+ DataTO srcData = cmd.getSrcTO();
+ SnapshotObjectTO snapshot = (SnapshotObjectTO)srcData;
+ DataTO destData = cmd.getDestTO();
+ PrimaryDataStoreTO pool = (PrimaryDataStoreTO)destData.getDataStore();
+ DataStoreTO imageStore = srcData.getDataStore();
+
+ if (!(imageStore instanceof NfsTO)) {
+ return new CopyCmdAnswer("unsupported protocol");
+ }
+
+ NfsTO nfsImageStore = (NfsTO)imageStore;
+ String primaryStorageNameLabel = pool.getUuid();
+ String secondaryStorageUrl = nfsImageStore.getUrl();
+ int wait = cmd.getWait();
+ boolean result = false;
+ // Generic error message.
+ String details = null;
+ String volumeUUID = null;
+
+ if (secondaryStorageUrl == null) {
+ details += " because the URL passed: " + secondaryStorageUrl + " is invalid.";
+ return new CopyCmdAnswer(details);
+ }
+ SR srcSr = null;
+ try {
+ SR primaryStorageSR = hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel);
+ if (primaryStorageSR == null) {
+ throw new InternalErrorException("Could not create volume from snapshot because the primary Storage SR could not be created from the name label: "
+ + primaryStorageNameLabel);
+ }
+ // Get the absolute path of the snapshot on the secondary storage.
+ String snapshotInstallPath = snapshot.getPath();
+ int index = snapshotInstallPath.lastIndexOf(File.separator);
+ String snapshotUuid = snapshotInstallPath.substring(index + 1);
+ String snapshotDirectory = snapshotInstallPath.substring(0, index);
+ index = snapshotUuid.lastIndexOf(".");
+ if (index != -1) {
+ snapshotUuid = snapshotUuid.substring(0, index);
+ }
+
+ URI uri = new URI(secondaryStorageUrl);
+
+ srcSr = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), snapshotDirectory);
+
+ VDI snapshotVdi = VDI.getByUuid(conn, snapshotUuid);
+ Task task = snapshotVdi.copyAsync(conn, primaryStorageSR, null, null);
+ // poll every 1 seconds ,
+ hypervisorResource.waitForTask(conn, task, 1000, wait * 1000);
+ hypervisorResource.checkForSuccess(conn, task);
+ VDI volumeVdi = Types.toVDI(task, conn);
+ volumeUUID = volumeVdi.getUuid(conn);
+ result = true;
+ VDI volume = VDI.getByUuid(conn, volumeUUID);
+ VDI.Record vdir = volume.getRecord(conn);
+ VolumeObjectTO newVol = new VolumeObjectTO();
+ newVol.setPath(volumeUUID);
+ newVol.setSize(vdir.virtualSize);
+ return new CopyCmdAnswer(newVol);
+ } catch (Types.XenAPIException e) {
+ details += " due to " + e.toString();
+ s_logger.warn(details, e);
+ } catch (Exception e) {
+ details += " due to " + e.getMessage();
+ s_logger.warn(details, e);
+ } finally {
+ if (srcSr != null) {
+ hypervisorResource.removeSR(conn, srcSr);
+ }
+ }
+ if (!result) {
+ // Is this logged at a higher level?
+ s_logger.error(details);
+ }
+
+ // In all cases return something.
+ return new CopyCmdAnswer(details);
+ }
+
+ @Override
+ public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd) {
+ Connection conn = hypervisorResource.getConnection();
+ VolumeObjectTO srcVolume = (VolumeObjectTO)cmd.getSrcTO();
+ VolumeObjectTO destVolume = (VolumeObjectTO)cmd.getDestTO();
+ int wait = cmd.getWait();
+ DataStoreTO destStore = destVolume.getDataStore();
+
+ if (destStore instanceof NfsTO) {
+ SR secondaryStorage = null;
+ try {
+ NfsTO nfsStore = (NfsTO)destStore;
+ URI uri = new URI(nfsStore.getUrl());
+ // Create the volume folder
+ if (!hypervisorResource.createSecondaryStorageFolder(conn, uri.getHost() + ":" + uri.getPath(), destVolume.getPath())) {
+ throw new InternalErrorException("Failed to create the volume folder.");
+ }
+
+ // Create a SR for the volume UUID folder
+ secondaryStorage = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), destVolume.getPath());
+ // Look up the volume on the source primary storage pool
+ VDI srcVdi = getVDIbyUuid(conn, srcVolume.getPath());
+ // Copy the volume to secondary storage
+ Task task = srcVdi.copyAsync(conn, secondaryStorage, null, null);
+ // poll every 1 seconds ,
+ hypervisorResource.waitForTask(conn, task, 1000, wait * 1000);
+ hypervisorResource.checkForSuccess(conn, task);
+ VDI destVdi = Types.toVDI(task, conn);
+ String destVolumeUUID = destVdi.getUuid(conn);
+
+ VolumeObjectTO newVol = new VolumeObjectTO();
+ newVol.setPath(destVolume.getPath() + File.separator + destVolumeUUID + ".vhd");
+ newVol.setSize(srcVolume.getSize());
+ return new CopyCmdAnswer(newVol);
+ } catch (Exception e) {
+ s_logger.debug("Failed to copy volume to secondary: " + e.toString());
+ return new CopyCmdAnswer("Failed to copy volume to secondary: " + e.toString());
+ } finally {
+ hypervisorResource.removeSR(conn, secondaryStorage);
+ }
+ }
+ return new CopyCmdAnswer("unsupported protocol");
+ }
+
+ @Override
+ public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd) {
+ Connection conn = hypervisorResource.getConnection();
+ DataTO srcData = cmd.getSrcTO();
+ DataTO destData = cmd.getDestTO();
+ int wait = cmd.getWait();
+ VolumeObjectTO srcVolume = (VolumeObjectTO)srcData;
+ VolumeObjectTO destVolume = (VolumeObjectTO)destData;
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)destVolume.getDataStore();
+ DataStoreTO srcStore = srcVolume.getDataStore();
+
+ if (srcStore instanceof NfsTO) {
+ NfsTO nfsStore = (NfsTO)srcStore;
+ String volumePath = srcVolume.getPath();
+ int index = volumePath.lastIndexOf("/");
+ String volumeDirectory = volumePath.substring(0, index);
+ String volumeUuid = volumePath.substring(index + 1);
+ index = volumeUuid.indexOf(".");
+ if (index != -1) {
+ volumeUuid = volumeUuid.substring(0, index);
+ }
+ URI uri = null;
+ try {
+ uri = new URI(nfsStore.getUrl());
+ } catch (Exception e) {
+ return new CopyCmdAnswer(e.toString());
+ }
+ SR srcSr = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), volumeDirectory);
+ try {
+ SR primaryStoragePool = hypervisorResource.getStorageRepository(conn, primaryStore.getUuid());
+ VDI srcVdi = VDI.getByUuid(conn, volumeUuid);
+ Task task = srcVdi.copyAsync(conn, primaryStoragePool, null, null);
+ // poll every 1 seconds ,
+ hypervisorResource.waitForTask(conn, task, 1000, wait * 1000);
+ hypervisorResource.checkForSuccess(conn, task);
+ VDI destVdi = Types.toVDI(task, conn);
+ VolumeObjectTO newVol = new VolumeObjectTO();
+ newVol.setPath(destVdi.getUuid(conn));
+ newVol.setSize(srcVolume.getSize());
+
+ return new CopyCmdAnswer(newVol);
+ } catch (Exception e) {
+ String msg = "Catch Exception " + e.getClass().getName() + " due to " + e.toString();
+ s_logger.warn(msg, e);
+ return new CopyCmdAnswer(e.toString());
+ } finally {
+ if (srcSr != null) {
+ hypervisorResource.removeSR(conn, srcSr);
+ }
+ }
+ }
+
+ s_logger.debug("unsupported protocol");
+ return new CopyCmdAnswer("unsupported protocol");
+ }
+
+}