From 1710c2f6848eaeb43ae8f0fe8ea4e524eabec871 Mon Sep 17 00:00:00 2001 From: frank Date: Tue, 11 Oct 2011 17:40:44 -0700 Subject: [PATCH] Bug 11648 - OVM - volume > create template FAIL status 11648: resolved fixed --- .../vm/hypervisor/ovm/OvmCommonModule.py | 13 +++ .../vm/hypervisor/ovm/OvmFaultConstants.py | 2 + .../vm/hypervisor/ovm/OvmStoragePoolModule.py | 70 +++++++++++++--- ovm/scripts/vm/hypervisor/ovm/OvmVmModule.py | 2 +- .../cloud/ovm/hypervisor/OvmResourceBase.java | 79 +++++++++++++------ .../com/cloud/ovm/object/OvmStoragePool.java | 7 ++ 6 files changed, 137 insertions(+), 36 deletions(-) mode change 100644 => 100755 ovm/scripts/vm/hypervisor/ovm/OvmVmModule.py diff --git a/ovm/scripts/vm/hypervisor/ovm/OvmCommonModule.py b/ovm/scripts/vm/hypervisor/ovm/OvmCommonModule.py index da51e184283..26086db20b6 100755 --- a/ovm/scripts/vm/hypervisor/ovm/OvmCommonModule.py +++ b/ovm/scripts/vm/hypervisor/ovm/OvmCommonModule.py @@ -112,4 +112,17 @@ def raiseExceptionIfFail(res): def ipToHeartBeatFileName(ip): return ip.replace('.', '_') + "_HEARTBEAT" + +def parseVmConfigureFile(cfgPath): + if not isfile(cfgPath): return {} + + res = {} + fd = open(cfgPath) + for i in fd.readlines(): + (key, value) = i.split("=", 1) + key = key.strip().strip("'") + value = value.strip().strip("'") + res[key] = value + fd.close() + return res diff --git a/ovm/scripts/vm/hypervisor/ovm/OvmFaultConstants.py b/ovm/scripts/vm/hypervisor/ovm/OvmFaultConstants.py index 8efeda3ed7a..4ed10984623 100755 --- a/ovm/scripts/vm/hypervisor/ovm/OvmFaultConstants.py +++ b/ovm/scripts/vm/hypervisor/ovm/OvmFaultConstants.py @@ -38,6 +38,8 @@ errCode = { "OvmStoragePool.getDetailsByUuid":OvmStoragePoolErrCodeStub+2, "OvmStoragePool.downloadTemplate":OvmStoragePoolErrCodeStub+3, "OvmStoragePool.prepareOCFS2Nodes":OvmStoragePoolErrCodeStub+4, + "OvmStoragePool.createTemplateFromVolume":OvmStoragePoolErrCodeStub+5, + "OvmStoragePool._umount":OvmStoragePoolErrCodeStub+6, "OvmNetwork.createBridge":OvmNetworkErrCodeStub+1, "OvmNetwork.deleteBridge":OvmNetworkErrCodeStub+2, diff --git a/ovm/scripts/vm/hypervisor/ovm/OvmStoragePoolModule.py b/ovm/scripts/vm/hypervisor/ovm/OvmStoragePoolModule.py index 6684e5b22ec..5b6dd29fcf7 100755 --- a/ovm/scripts/vm/hypervisor/ovm/OvmStoragePoolModule.py +++ b/ovm/scripts/vm/hypervisor/ovm/OvmStoragePoolModule.py @@ -74,12 +74,25 @@ class OvmStoragePool(OvmObject): res = doCmd(['mount']) return (path in res) - def _mount(self, target, mountpoint): + def _mount(self, target, mountpoint, readonly=False): if not exists(mountpoint): os.makedirs(mountpoint) if not OvmStoragePool()._isMounted(mountpoint): - doCmd(['mount', target, mountpoint, '-r']) + if readonly: + doCmd(['mount', target, mountpoint, '-r']) + else: + doCmd(['mount', target, mountpoint]) + + def _umount(self, mountpoint): + umountCmd = ['umount', '-f', mountpoint] + doCmd(umountCmd) + ls = os.listdir(mountpoint) + if len(ls) == 0: + rmDirCmd = ['rm', '-r', mountpoint] + doCmd(rmDirCmd) + else: + logger.warning(OvmStoragePool._umount, "Something wrong when umount %s, there are still files in directory:%s", mountpoint, " ".join(ls)) @staticmethod def create(jStr): @@ -174,14 +187,7 @@ class OvmStoragePool(OvmObject): finally: if exists(secMountPoint): try: - umountCmd = ['umount', '-f', secMountPoint] - doCmd(umountCmd) - ls = os.listdir(secMountPoint) - if len(ls) == 0: - rmDirCmd = ['rm', '-r', secMountPoint] - doCmd(rmDirCmd) - else: - logger.warning(OvmStoragePool.downloadTemplate, "Something wrong when umount %s, there are still files in directory:%s", secMountPoint, " ".join(ls)) + OvmStoragePool()._umount(secMountPoint) except Exception, e: errmsg = fmt_err_msg(e) logger.error(OvmStoragePool.downloadTemplate, 'unmount secondary storage at %s failed, %s'%(secMountPoint, errmsg)) @@ -314,6 +320,48 @@ class OvmStoragePool(OvmObject): errmsg = fmt_err_msg(e) logger.error(OvmStoragePool.prepareOCFS2Nodes, errmsg) raise XmlRpcFault(toErrCode(OvmStoragePool, OvmStoragePool.prepareOCFS2Nodes), errmsg) + + @staticmethod + def createTemplateFromVolume(secStorageMountPath, installPath, volumePath): + try: + secMountPoint = "" + if not isfile(volumePath): raise Exception("Cannot find %s"%volumePath) + vmCfg = join(dirname(volumePath), 'vm.cfg') + cfgs = parseVmConfigureFile(vmCfg) + if len(cfgs) == 0: raise Exception("Cannot find vm.cfg, this volume(%s) seems not the ROOT volume. We don't support create template from non-ROOT volume"%volumePath) + vmName = cfgs['name'] + if vmName in doCmd(['xm', 'list']): + raise Exception("%s is still running, please stop it first then create template again"%vmName) - + tmpUuid = get_uuid() + secMountPoint = join("/var/cloud/", tmpUuid) + OvmStoragePool()._mount(secStorageMountPath, secMountPoint) + installPath = installPath.lstrip('/') + destPath = join(secMountPoint, installPath) + if exists(destPath): + logger.warning("%s is already here, delete it since it is most likely stale"%destPath) + doCmd(['rm', '-rf', destPath]) + OvmStoragePool()._checkDirSizeForImage(secMountPoint, volumePath) + + os.makedirs(destPath) + newName = get_uuid() + ".raw" + destName = join(destPath, newName) + doCmd(['cp', volumePath, destName]) + size = os.path.getsize(destName) + resInstallPath = join(installPath, newName) + OvmStoragePool()._umount(secMountPoint) + rs = toGson({"installPath":resInstallPath, "templateFileName":newName, "virtualSize":size, "physicalSize":size}) + return rs + + except Exception, e: + try: + if exists(secMountPoint): + OvmStoragePool()._umount(secMountPoint) + except Exception, e: + logger.warning(OvmStoragePool.createTemplateFromVolume, "umount %s failed"%secMountPoint) + + errmsg = fmt_err_msg(e) + logger.error(OvmStoragePool.createTemplateFromVolume, errmsg) + raise XmlRpcFault(toErrCode(OvmStoragePool, OvmStoragePool.createTemplateFromVolume), errmsg) + \ No newline at end of file diff --git a/ovm/scripts/vm/hypervisor/ovm/OvmVmModule.py b/ovm/scripts/vm/hypervisor/ovm/OvmVmModule.py old mode 100644 new mode 100755 index 38ac5b56dbd..a804d9ccb48 --- a/ovm/scripts/vm/hypervisor/ovm/OvmVmModule.py +++ b/ovm/scripts/vm/hypervisor/ovm/OvmVmModule.py @@ -73,7 +73,7 @@ class OvmVm(OvmObject): name = '' bootDev = '' type = '' - + def _getVifs(self, vmName): vmPath = OvmHost()._vmNameToPath(vmName) domId = OvmHost()._getDomainIdByName(vmName) diff --git a/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java b/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java index 6105edec51b..adb0c193ab5 100755 --- a/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java +++ b/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java @@ -25,7 +25,9 @@ import com.cloud.agent.api.CheckVirtualMachineAnswer; import com.cloud.agent.api.CheckVirtualMachineCommand; import com.cloud.agent.api.CleanupNetworkRulesCmd; import com.cloud.agent.api.Command; +import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand; import com.cloud.agent.api.CreateStoragePoolCommand; +import com.cloud.agent.api.CreateVolumeFromSnapshotCommand; import com.cloud.agent.api.FenceAnswer; import com.cloud.agent.api.FenceCommand; import com.cloud.agent.api.GetHostStatsAnswer; @@ -64,6 +66,7 @@ import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.VmStatsEntry; import com.cloud.agent.api.storage.CreateAnswer; import com.cloud.agent.api.storage.CreateCommand; +import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer; import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; @@ -87,6 +90,7 @@ import com.cloud.ovm.object.OvmVm; import com.cloud.ovm.object.OvmVolume; import com.cloud.resource.ServerResource; import com.cloud.resource.hypervisor.HypervisorResource; +import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Volume; import com.cloud.storage.template.TemplateInfo; @@ -1163,56 +1167,83 @@ public class OvmResourceBase implements ServerResource, HypervisorResource { } } + protected CreatePrivateTemplateAnswer execute(final CreatePrivateTemplateFromVolumeCommand cmd) { + String secondaryStoragePoolURL = cmd.getSecondaryStorageURL(); + String volumePath = cmd.getVolumePath(); + Long accountId = cmd.getAccountId(); + Long templateId = cmd.getTemplateId(); + int wait = cmd.getWait(); + if (wait == 0) { + /* Defaut timeout 2 hours */ + wait = 7200; + } + + try { + URI uri; + uri = new URI(secondaryStoragePoolURL); + String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); + String installPath = "template/tmpl/" + accountId + "/" + templateId; + Map res = OvmStoragePool.createTemplateFromVolume(_conn, secondaryStorageMountPath, installPath, volumePath, wait); + return new CreatePrivateTemplateAnswer(cmd, true, null, res.get("installPath"), Long.valueOf(res.get("virtualSize")), Long.valueOf(res.get("physicalSize")), res.get("templateFileName"), ImageFormat.RAW); + } catch (Exception e) { + s_logger.debug("Create template failed", e); + return new CreatePrivateTemplateAnswer(cmd, false, e.getMessage()); + } + } + @Override public Answer executeRequest(Command cmd) { - if (cmd instanceof ReadyCommand) { + Class clazz = cmd.getClass(); + if (clazz == ReadyCommand.class) { return execute((ReadyCommand)cmd); - } else if (cmd instanceof CreateStoragePoolCommand) { + } else if (clazz == CreateStoragePoolCommand.class) { return execute((CreateStoragePoolCommand)cmd); - } else if (cmd instanceof ModifyStoragePoolCommand) { + } else if (clazz == ModifyStoragePoolCommand.class) { return execute((ModifyStoragePoolCommand)cmd); - } else if (cmd instanceof PrimaryStorageDownloadCommand) { + } else if (clazz == PrimaryStorageDownloadCommand.class) { return execute((PrimaryStorageDownloadCommand)cmd); - } else if (cmd instanceof CreateCommand) { + } else if (clazz == CreateCommand.class) { return execute((CreateCommand)cmd); - } else if (cmd instanceof GetHostStatsCommand) { + } else if (clazz == GetHostStatsCommand.class) { return execute((GetHostStatsCommand)cmd); - } else if (cmd instanceof StopCommand) { + } else if (clazz == StopCommand.class) { return execute((StopCommand)cmd); - } else if (cmd instanceof RebootCommand) { + } else if (clazz == RebootCommand.class) { return execute((RebootCommand)cmd); - } else if (cmd instanceof GetStorageStatsCommand) { + } else if (clazz == GetStorageStatsCommand.class) { return execute((GetStorageStatsCommand)cmd); - } else if (cmd instanceof GetVmStatsCommand) { + } else if (clazz == GetVmStatsCommand.class) { return execute((GetVmStatsCommand)cmd); - } else if (cmd instanceof AttachVolumeCommand) { + } else if (clazz == AttachVolumeCommand.class) { return execute((AttachVolumeCommand)cmd); - } else if (cmd instanceof DestroyCommand) { + } else if (clazz == DestroyCommand.class) { return execute((DestroyCommand)cmd); - } else if (cmd instanceof PrepareForMigrationCommand) { + } else if (clazz == PrepareForMigrationCommand.class) { return execute((PrepareForMigrationCommand)cmd); - } else if (cmd instanceof MigrateCommand) { + } else if (clazz == MigrateCommand.class) { return execute((MigrateCommand)cmd); - } else if (cmd instanceof CheckVirtualMachineCommand) { + } else if (clazz == CheckVirtualMachineCommand.class) { return execute((CheckVirtualMachineCommand)cmd); - } else if (cmd instanceof MaintainCommand) { + } else if (clazz == MaintainCommand.class) { return execute((MaintainCommand)cmd); - } else if (cmd instanceof StartCommand) { + } else if (clazz == StartCommand.class) { return execute((StartCommand)cmd); - } else if (cmd instanceof GetVncPortCommand) { + } else if (clazz == GetVncPortCommand.class) { return execute((GetVncPortCommand)cmd); - } else if (cmd instanceof PingTestCommand) { + } else if (clazz == PingTestCommand.class) { return execute((PingTestCommand)cmd); - } else if (cmd instanceof FenceCommand) { + } else if (clazz == FenceCommand.class) { return execute((FenceCommand)cmd); - } else if (cmd instanceof AttachIsoCommand) { + } else if (clazz == AttachIsoCommand.class) { return execute((AttachIsoCommand)cmd); - } else if (cmd instanceof SecurityIngressRulesCmd) { + } else if (clazz == SecurityIngressRulesCmd.class) { return execute((SecurityIngressRulesCmd) cmd); - } else if (cmd instanceof CleanupNetworkRulesCmd) { + } else if (clazz == CleanupNetworkRulesCmd.class) { return execute((CleanupNetworkRulesCmd) cmd); - } else if (cmd instanceof PrepareOCFS2NodesCommand) { + } else if (clazz == PrepareOCFS2NodesCommand.class) { return execute((PrepareOCFS2NodesCommand)cmd); + } else if (clazz == CreatePrivateTemplateFromVolumeCommand.class) { + return execute((CreatePrivateTemplateFromVolumeCommand)cmd); }else { return Answer.createUnsupportedCommandAnswer(cmd); } diff --git a/ovm/src/com/cloud/ovm/object/OvmStoragePool.java b/ovm/src/com/cloud/ovm/object/OvmStoragePool.java index 3f5ea4d03e1..fc196929c80 100755 --- a/ovm/src/com/cloud/ovm/object/OvmStoragePool.java +++ b/ovm/src/com/cloud/ovm/object/OvmStoragePool.java @@ -67,4 +67,11 @@ public class OvmStoragePool extends OvmObject { Object[] params = {clusterName, nodes}; c.call("OvmStoragePool.prepareOCFS2Nodes", params); } + + public static Map createTemplateFromVolume(Connection c, String secStorageMountPath, String installPath, String volumePath, int timeout) throws XmlRpcException { + Object[] params = {secStorageMountPath, installPath, volumePath}; + String res = (String) c.callTimeoutInSec("OvmStoragePool.createTemplateFromVolume", params, timeout); + Map info = Coder.mapFromJson(res); + return info; + } }