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/12 02:11:53 UTC
git commit: updated refs/heads/4.2-workplace to 94a5370
Updated Branches:
refs/heads/4.2-workplace 0423ba898 -> 94a537005
fix create template from snapshot
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/94a53700
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/94a53700
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/94a53700
Branch: refs/heads/4.2-workplace
Commit: 94a5370053d076bf49654eedf2ed63d56a6bb17f
Parents: 0423ba8
Author: Edison Su <su...@gmail.com>
Authored: Wed Dec 11 17:11:30 2013 -0800
Committer: Edison Su <su...@gmail.com>
Committed: Wed Dec 11 17:11:30 2013 -0800
----------------------------------------------------------------------
.../subsystem/api/storage/EndPointSelector.java | 2 +
.../endpoint/DefaultEndPointSelector.java | 66 +++++++++-
.../src/com/cloud/hypervisor/XenServerGuru.java | 44 ++++++-
.../resource/Xenserver620StorageProcessor.java | 126 +++++++++++++++++--
.../hypervisor/xenserver/cloud-plugin-snapshot | 16 ++-
5 files changed, 240 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/94a53700/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java
index 01de4f8..fd05f1b 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java
@@ -32,4 +32,6 @@ public interface EndPointSelector {
EndPoint select(DataObject object, StorageAction action);
List<EndPoint> selectAll(DataStore store);
+
+ EndPoint selectHypervisorHost(Scope scope);
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/94a53700/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java b/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
index 0c9c78b..12b56f8 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
@@ -27,11 +27,16 @@ import java.util.List;
import javax.inject.Inject;
-import com.cloud.hypervisor.Hypervisor;
-import com.cloud.vm.VirtualMachine;
-import org.apache.cloudstack.engine.subsystem.api.storage.*;
-import org.apache.cloudstack.storage.RemoteHostEndPoint;
+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.EndPoint;
+import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
+import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
+import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
+import org.apache.cloudstack.engine.subsystem.api.storage.StorageAction;
+import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.storage.LocalHostEndpoint;
+import org.apache.cloudstack.storage.RemoteHostEndPoint;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@@ -39,14 +44,16 @@ import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
+import com.cloud.hypervisor.Hypervisor;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.ScopeType;
import com.cloud.utils.db.DB;
+import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.SearchCriteria2;
import com.cloud.utils.db.SearchCriteriaService;
import com.cloud.utils.db.Transaction;
-import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.VirtualMachine;
@Component
public class DefaultEndPointSelector implements EndPointSelector {
@@ -55,6 +62,7 @@ public class DefaultEndPointSelector implements EndPointSelector {
HostDao hostDao;
private String findOneHostOnPrimaryStorage = "select h.id from host h, storage_pool_host_ref s where h.status = 'Up' and h.type = 'Routing' and h.resource_state = 'Enabled' and" +
" h.id = s.host_id and s.pool_id = ? ";
+ private String findOneHypervisorHostInScope = "select h.id from host h where h.status = 'Up' and h.hypervisor_type is not null ";
protected boolean moveBetweenPrimaryImage(DataStore srcStore, DataStore destStore) {
DataStoreRole srcRole = srcStore.getRole();
@@ -307,4 +315,52 @@ public class DefaultEndPointSelector implements EndPointSelector {
}
return endPoints;
}
+
+ @Override
+ public EndPoint selectHypervisorHost(Scope scope) {
+ StringBuilder sbuilder = new StringBuilder();
+ sbuilder.append(findOneHypervisorHostInScope);
+ if (scope.getScopeType() == ScopeType.ZONE) {
+ sbuilder.append(" and h.data_center_id = ");
+ sbuilder.append(scope.getScopeId());
+ } else if (scope.getScopeType() == ScopeType.CLUSTER) {
+ sbuilder.append(" and h.cluster_id = ");
+ sbuilder.append(scope.getScopeId());
+ }
+ sbuilder.append(" ORDER by rand() limit 1");
+
+ String sql = sbuilder.toString();
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ HostVO host = null;
+ Transaction txn = Transaction.currentTxn();
+
+ try {
+ pstmt = txn.prepareStatement(sql);
+ rs = pstmt.executeQuery();
+ while (rs.next()) {
+ long id = rs.getLong(1);
+ host = hostDao.findById(id);
+ }
+ } catch (SQLException e) {
+ s_logger.warn("can't find endpoint", e);
+ } finally {
+ try {
+ if (rs != null) {
+ rs.close();
+ }
+ if (pstmt != null) {
+ pstmt.close();
+ }
+ } catch (SQLException e) {
+ }
+ }
+
+ if (host == null) {
+ return null;
+ }
+
+ return RemoteHostEndPoint.getHypervisorHostEndPoint(host.getId(), host.getPrivateIpAddress(),
+ host.getPublicIpAddress());
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/94a53700/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java
index c52020e..6724c88 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java
@@ -19,18 +19,34 @@ package com.cloud.hypervisor;
import javax.ejb.Local;
import javax.inject.Inject;
+import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
+import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
+import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
+import org.apache.cloudstack.storage.command.CopyCommand;
+
+import com.cloud.agent.api.Command;
+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.VirtualMachineTO;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.GuestOSVO;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
+import com.cloud.utils.Pair;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
-import com.cloud.vm.VirtualMachineProfileImpl;
@Local(value=HypervisorGuru.class)
public class XenServerGuru extends HypervisorGuruBase implements HypervisorGuru {
@Inject GuestOSDao _guestOsDao;
+ @Inject
+ EndPointSelector endPointSelector;
+ @Inject
+ HostDao hostDao;
protected XenServerGuru() {
super();
@@ -61,4 +77,30 @@ public class XenServerGuru extends HypervisorGuruBase implements HypervisorGuru
public boolean trackVmHostChange() {
return true;
}
+
+ @Override
+ public Pair<Boolean, Long> getCommandHostDelegation(long hostId, Command cmd) {
+ if (cmd instanceof CopyCommand) {
+ CopyCommand cpyCommand = (CopyCommand)cmd;
+ DataTO srcData = cpyCommand.getSrcTO();
+ DataTO destData = cpyCommand.getDestTO();
+
+ if (srcData.getObjectType() == DataObjectType.SNAPSHOT && destData.getObjectType() == DataObjectType.TEMPLATE) {
+ DataStoreTO srcStore = srcData.getDataStore();
+ DataStoreTO destStore = destData.getDataStore();
+ if (srcStore instanceof NfsTO && destStore instanceof NfsTO) {
+ HostVO host = hostDao.findById(hostId);
+ EndPoint ep = endPointSelector.selectHypervisorHost(new ZoneScope(host.getDataCenterId()));
+ host = hostDao.findById(ep.getId());
+ hostDao.loadDetails(host);
+ String version = host.getDetail("product_version");
+ //can't mix both 6.2.0 with other version of xenserver
+ if ("6.2.0".equalsIgnoreCase(version)) {
+ return new Pair<Boolean, Long>(Boolean.TRUE, new Long(ep.getId()));
+ }
+ }
+ }
+ }
+ return new Pair<Boolean, Long>(Boolean.FALSE, new Long(hostId));
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/94a53700/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
index d9687e1..14a320b 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/Xenserver620StorageProcessor.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/Xenserver620StorageProcessor.java
@@ -70,6 +70,14 @@ public class Xenserver620StorageProcessor extends XenServerStorageProcessor {
}
return true;
}
+
+ protected boolean makeDirectory(Connection conn, String path) {
+ String result = hypervisorResource.callHostPlugin(conn, "cloud-plugin-snapshot", "makeDirectory", "path", path);
+ if (result == null || result.isEmpty()) {
+ return false;
+ }
+ return true;
+ }
protected SR createFileSr(Connection conn, String remotePath, String dir) {
String localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(remotePath.getBytes());
mountNfs(conn, remotePath, localDir);
@@ -281,16 +289,19 @@ public class Xenserver620StorageProcessor extends XenServerStorageProcessor {
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 {
+ String localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(secondaryStorageMountPath.getBytes());
+ mountNfs(conn, secondaryStorageMountPath, localDir);
+ boolean result = makeDirectory(conn, localDir + "/" + folder);
+ if (!result) {
+ details = " Filed to create folder " + folder + " in secondary storage";
+ s_logger.warn(details);
+ return new CopyCmdAnswer(details);
+ }
+
snapshotSr = createFileSr(conn, secondaryStorageMountPath, folder);
+
Task task = snapshotVdi.copyAsync(conn, snapshotSr, null, null);
// poll every 1 seconds ,
hypervisorResource.waitForTask(conn, task, 1000, wait * 1000);
@@ -665,4 +676,105 @@ public class Xenserver620StorageProcessor extends XenServerStorageProcessor {
return new CopyCmdAnswer("unsupported protocol");
}
+ @Override
+ public Answer createTemplateFromSnapshot(CopyCommand cmd) {
+ Connection conn = hypervisorResource.getConnection();
+ DataTO srcData = cmd.getSrcTO();
+ DataTO destData = cmd.getDestTO();
+ int wait = cmd.getWait();
+ SnapshotObjectTO srcObj = (SnapshotObjectTO)srcData;
+ TemplateObjectTO destObj = (TemplateObjectTO)destData;
+ NfsTO srcStore = (NfsTO)srcObj.getDataStore();
+ NfsTO destStore = (NfsTO)destObj.getDataStore();
+
+ URI srcUri = null;
+ URI destUri = null;
+ try {
+ srcUri = new URI(srcStore.getUrl());
+ destUri = new URI(destStore.getUrl());
+ } catch (Exception e) {
+ s_logger.debug("incorrect url", e);
+ return new CopyCmdAnswer("incorrect url" + e.toString());
+ }
+
+ String srcPath = srcObj.getPath();
+ int index = srcPath.lastIndexOf("/");
+ String srcDir = srcPath.substring(0, index);
+ String destDir = destObj.getPath();
+ SR srcSr = null;
+ SR destSr = null;
+ VDI destVdi = null;
+ boolean result = false;
+ try {
+ srcSr = createFileSr(conn, srcUri.getHost() + ":" + srcUri.getPath(), srcDir);
+
+ String destNfsPath = destUri.getHost() + ":" + destUri.getPath();
+ String localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(destNfsPath.getBytes());
+ mountNfs(conn, destUri.getHost() + ":" + destUri.getPath(), localDir);
+ makeDirectory(conn, localDir + "/" + destDir);
+ destSr = hypervisorResource.createFileSR(conn, localDir + "/" + destDir);
+
+ String nameLabel = "cloud-" + UUID.randomUUID().toString();
+
+ SnapshotObjectTO[] parents = srcObj.getParents();
+ List<VDI> snapshotChains = new ArrayList<VDI>();
+ if (parents != null) {
+ for(int i = 0; i < parents.length; i++) {
+ SnapshotObjectTO snChain = parents[i];
+ String uuid = getSnapshotUuid(snChain.getPath());
+ VDI chain = VDI.getByUuid(conn, uuid);
+ snapshotChains.add(chain);
+ }
+ }
+ String snapshotUuid = getSnapshotUuid(srcPath);
+ VDI snapshotVdi = VDI.getByUuid(conn, snapshotUuid);
+ snapshotChains.add(snapshotVdi);
+
+ long templateVirtualSize = snapshotChains.get(0).getVirtualSize(conn);
+ destVdi = createVdi(conn, nameLabel, destSr, templateVirtualSize);
+ String destVdiUuid = destVdi.getUuid(conn);
+
+ for(VDI snapChain : snapshotChains) {
+ Task task = snapChain.copyAsync(conn, null, null, destVdi);
+ // poll every 1 seconds ,
+ hypervisorResource.waitForTask(conn, task, 1000, wait * 1000);
+ hypervisorResource.checkForSuccess(conn, task);
+ }
+
+ destVdi = VDI.getByUuid(conn, destVdiUuid);
+ String templatePath = destDir + "/" + destVdiUuid + ".vhd";
+ templatePath = templatePath.replaceAll("//","/");
+ TemplateObjectTO newTemplate = new TemplateObjectTO();
+ newTemplate.setPath(templatePath);
+ newTemplate.setFormat(Storage.ImageFormat.VHD);
+ newTemplate.setSize(destVdi.getVirtualSize(conn));
+ newTemplate.setPhysicalSize(destVdi.getPhysicalUtilisation(conn));
+ newTemplate.setName(destVdiUuid);
+
+ result = true;
+ return new CopyCmdAnswer(newTemplate);
+ } catch (Exception e) {
+ s_logger.error("Failed create template from snapshot", e);
+ return new CopyCmdAnswer("Failed create template from snapshot " + e.toString());
+ } finally {
+ if (!result) {
+ if (destVdi != null) {
+ try {
+ destVdi.destroy(conn);
+ } catch (Exception e) {
+ s_logger.debug("Clean up left over on dest storage failed: ", e);
+ }
+ }
+ }
+
+ if (destSr != null) {
+ hypervisorResource.removeSR(conn, destSr);
+ }
+
+ if (srcSr != null) {
+ hypervisorResource.removeSR(conn, srcSr);
+ }
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/94a53700/scripts/vm/hypervisor/xenserver/cloud-plugin-snapshot
----------------------------------------------------------------------
diff --git a/scripts/vm/hypervisor/xenserver/cloud-plugin-snapshot b/scripts/vm/hypervisor/xenserver/cloud-plugin-snapshot
index 5150ae8..6aacc44 100644
--- a/scripts/vm/hypervisor/xenserver/cloud-plugin-snapshot
+++ b/scripts/vm/hypervisor/xenserver/cloud-plugin-snapshot
@@ -298,6 +298,20 @@ def makedirs(path):
raise xs_errors.XenError(errMsg)
return
+@echo
+def makeDirectory(session, args):
+ path = args['path']
+ if not os.path.isdir(path):
+ try:
+ os.makedirs(path)
+ except OSError, (errno, strerror):
+ if os.path.isdir(path):
+ return "true"
+ errMsg = "OSError while creating " + path + " with errno: " + str(errno) + " and strerr: " + strerror
+ logging.debug(errMsg)
+ raise xs_errors.XenError(errMsg)
+ return "true"
+
def mount(remoteDir, localDir):
makedirs(localDir)
options = "soft,tcp,timeo=133,retrans=1"
@@ -638,6 +652,6 @@ def revert_memory_snapshot(session, args):
return "0"
if __name__ == "__main__":
- XenAPIPlugin.dispatch({"getVhdParent":getVhdParent, "create_secondary_storage_folder":create_secondary_storage_folder, "delete_secondary_storage_folder":delete_secondary_storage_folder, "post_create_private_template":post_create_private_template, "backupSnapshot": backupSnapshot, "deleteSnapshotBackup": deleteSnapshotBackup, "unmountSnapshotsDir": unmountSnapshotsDir, "revert_memory_snapshot":revert_memory_snapshot, "mountNfsSecondaryStorage":mountNfsSecondaryStorage, "umountNfsSecondaryStorage":umountNfsSecondaryStorage})
+ XenAPIPlugin.dispatch({"getVhdParent":getVhdParent, "create_secondary_storage_folder":create_secondary_storage_folder, "delete_secondary_storage_folder":delete_secondary_storage_folder, "post_create_private_template":post_create_private_template, "backupSnapshot": backupSnapshot, "deleteSnapshotBackup": deleteSnapshotBackup, "unmountSnapshotsDir": unmountSnapshotsDir, "revert_memory_snapshot":revert_memory_snapshot, "mountNfsSecondaryStorage":mountNfsSecondaryStorage, "umountNfsSecondaryStorage":umountNfsSecondaryStorage, "makeDirectory":makeDirectory})