mirror of https://github.com/apache/cloudstack.git
Bug 11648 - OVM - volume > create template FAIL
status 11648: resolved fixed
This commit is contained in:
parent
dce4e74b58
commit
1710c2f684
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ class OvmVm(OvmObject):
|
|||
name = ''
|
||||
bootDev = ''
|
||||
type = ''
|
||||
|
||||
|
||||
def _getVifs(self, vmName):
|
||||
vmPath = OvmHost()._vmNameToPath(vmName)
|
||||
domId = OvmHost()._getDomainIdByName(vmName)
|
||||
|
|
|
|||
|
|
@ -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<String, String> 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<? extends Command> 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,4 +67,11 @@ public class OvmStoragePool extends OvmObject {
|
|||
Object[] params = {clusterName, nodes};
|
||||
c.call("OvmStoragePool.prepareOCFS2Nodes", params);
|
||||
}
|
||||
|
||||
public static Map<String, String> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue