From 88180fc139ad905bb51db6aa0287bd9471194aea Mon Sep 17 00:00:00 2001 From: Marcus Sorensen Date: Sat, 17 Nov 2012 23:47:39 -0700 Subject: [PATCH] Summary: Direct template imaging for CLVM, bypass copy template to primary Detail: Because of the way most other primary storage types work with cloudstack (i.e. backing stores) CLVM actually copies the template to a local logical volume on primary storage, then uses that. This causes all of your primary storage to be littered with a copy of every template used. Since we're not using these, dump the template direct to the newly created logical volume. This is faster as well since the template is sparse; we're not creating a fat template on primary storage and then copying that to a logical volume when we deploy from template. BUG-ID: CLOUDSTACK-508 Bugfix-for: 4.1 Signed-off-by: Marcus Sorensen 1353221260 -0700 --- .../resource/LibvirtComputingResource.java | 59 +++++++++++++++++-- .../com/cloud/storage/StorageManagerImpl.java | 43 +++++++++++--- 2 files changed, 89 insertions(+), 13 deletions(-) diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index c783daa5947..41ee1dd4139 100755 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -1190,11 +1190,13 @@ public class LibvirtComputingResource extends ServerResourceBase implements disksize = dskch.getSize(); if (cmd.getTemplateUrl() != null) { - - BaseVol = primaryPool.getPhysicalDisk(cmd.getTemplateUrl()); - vol = _storagePoolMgr.createDiskFromTemplate(BaseVol, UUID + if(primaryPool.getType() == StoragePoolType.CLVM) { + vol = templateToPrimaryDownload(cmd.getTemplateUrl(),primaryPool); + } else { + BaseVol = primaryPool.getPhysicalDisk(cmd.getTemplateUrl()); + vol = _storagePoolMgr.createDiskFromTemplate(BaseVol, UUID .randomUUID().toString(), primaryPool); - + } if (vol == null) { return new Answer(cmd, false, " Can't create storage volume on storage pool"); @@ -1213,6 +1215,55 @@ public class LibvirtComputingResource extends ServerResourceBase implements } } + // this is much like PrimaryStorageDownloadCommand, but keeping it separate + protected KVMPhysicalDisk templateToPrimaryDownload(String templateUrl, KVMStoragePool primaryPool) { + int index = templateUrl.lastIndexOf("/"); + String mountpoint = templateUrl.substring(0, index); + String templateName = null; + if (index < templateUrl.length() - 1) { + templateName = templateUrl.substring(index + 1); + } + + KVMPhysicalDisk templateVol = null; + KVMStoragePool secondaryPool = null; + try { + secondaryPool = _storagePoolMgr.getStoragePoolByURI(mountpoint); + /* Get template vol */ + if (templateName == null) { + secondaryPool.refresh(); + List disks = secondaryPool.listPhysicalDisks(); + if (disks == null || disks.isEmpty()) { + s_logger.error("Failed to get volumes from pool: " + secondaryPool.getUuid()); + return null; + } + for (KVMPhysicalDisk disk : disks) { + if (disk.getName().endsWith("qcow2")) { + templateVol = disk; + break; + } + } + if (templateVol == null) { + s_logger.error("Failed to get template from pool: " + secondaryPool.getUuid()); + return null; + } + } else { + templateVol = secondaryPool.getPhysicalDisk(templateName); + } + + /* Copy volume to primary storage */ + + KVMPhysicalDisk primaryVol = _storagePoolMgr.copyPhysicalDisk(templateVol, UUID.randomUUID().toString(), primaryPool); + return primaryVol; + } catch (CloudRuntimeException e) { + s_logger.error("Failed to download template to primary storage",e); + return null; + } finally { + if (secondaryPool != null) { + secondaryPool.delete(); + } + } + } + public Answer execute(DestroyCommand cmd) { VolumeTO vol = cmd.getVolume(); diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index f5d0796530b..e252633f8e3 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -835,11 +835,23 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag for (int i = 0; i < 2; i++) { if (volume.getVolumeType() == Type.ROOT && Storage.ImageFormat.ISO != template.getFormat()) { - tmpltStoredOn = _tmpltMgr.prepareTemplateForCreate(template, pool); - if (tmpltStoredOn == null) { - continue; + if (pool.getPoolType() == StoragePoolType.CLVM) { + //prepareISOForCreate does what we need, which is to tell us where the template is + VMTemplateHostVO tmpltHostOn = _tmpltMgr.prepareISOForCreate(template, pool); + if (tmpltHostOn == null) { + continue; + } + HostVO secondaryStorageHost = _hostDao.findById(tmpltHostOn.getHostId()); + String tmpltHostUrl = secondaryStorageHost.getStorageUrl(); + String fullTmpltUrl = tmpltHostUrl + "/" + tmpltHostOn.getInstallPath(); + cmd = new CreateCommand(dskCh, fullTmpltUrl, new StorageFilerTO(pool)); + } else { + tmpltStoredOn = _tmpltMgr.prepareTemplateForCreate(template, pool); + if (tmpltStoredOn == null) { + continue; + } + cmd = new CreateCommand(dskCh, tmpltStoredOn.getLocalDownloadPath(), new StorageFilerTO(pool)); } - cmd = new CreateCommand(dskCh, tmpltStoredOn.getLocalDownloadPath(), new StorageFilerTO(pool)); } else { if (volume.getVolumeType() == Type.ROOT && Storage.ImageFormat.ISO == template.getFormat()) { VMTemplateHostVO tmpltHostOn = _tmpltMgr.prepareISOForCreate(template, pool); @@ -3434,12 +3446,25 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag for (int i = 0; i < 2; i++) { if (template != null && template.getFormat() != Storage.ImageFormat.ISO) { - tmpltStoredOn = _tmpltMgr.prepareTemplateForCreate(template, pool); - if (tmpltStoredOn == null) { - s_logger.debug("Cannot use this pool " + pool + " because we can't propagate template " + template); - return null; + if (pool.getPoolType() == StoragePoolType.CLVM) { + //prepareISOForCreate does what we need, which is to tell us where the template is + VMTemplateHostVO tmpltHostOn = _tmpltMgr.prepareISOForCreate(template, pool); + if (tmpltHostOn == null) { + s_logger.debug("cannot find template " + template.getId() + " " + template.getName()); + return null; + } + HostVO secondaryStorageHost = _hostDao.findById(tmpltHostOn.getHostId()); + String tmpltHostUrl = secondaryStorageHost.getStorageUrl(); + String fullTmpltUrl = tmpltHostUrl + "/" + tmpltHostOn.getInstallPath(); + cmd = new CreateCommand(diskProfile, fullTmpltUrl, new StorageFilerTO(pool)); + } else { + tmpltStoredOn = _tmpltMgr.prepareTemplateForCreate(template, pool); + if (tmpltStoredOn == null) { + s_logger.debug("Cannot use this pool " + pool + " because we can't propagate template " + template); + return null; + } + cmd = new CreateCommand(diskProfile, tmpltStoredOn.getLocalDownloadPath(), new StorageFilerTO(pool)); } - cmd = new CreateCommand(diskProfile, tmpltStoredOn.getLocalDownloadPath(), new StorageFilerTO(pool)); } else { if (template != null && Storage.ImageFormat.ISO == template.getFormat()) { VMTemplateHostVO tmpltHostOn = _tmpltMgr.prepareISOForCreate(template, pool);