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})