Repository: cloudstack Updated Branches: refs/heads/multiple-disk-ova 3532ffe5a -> fa0897f90
CLOUDSTACK-4757. More updates to Datadisk template creation - update ROOT disk OVA once all the datadisks have been created Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/fa0897f9 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/fa0897f9 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/fa0897f9 Branch: refs/heads/multiple-disk-ova Commit: fa0897f902dbb941bb18a0bf63fe1b182f535c86 Parents: 3532ffe Author: Likitha Shetty <likitha.she...@citrix.com> Authored: Fri May 16 11:32:10 2014 +0530 Committer: Likitha Shetty <likitha.she...@citrix.com> Committed: Mon May 19 15:06:45 2014 +0530 ---------------------------------------------------------------------- api/src/com/cloud/agent/api/to/DatadiskTO.java | 60 +++++++++ .../cloud/agent/api/to/DatadiskTemplateTO.java | 74 ----------- .../storage/CreateDatadiskTemplateCommand.java | 8 +- .../agent/api/storage/GetDatadisksAnswer.java | 8 +- .../subsystem/api/storage/TemplateService.java | 7 +- .../image/datastore/ImageStoreEntity.java | 6 +- .../storage/image/TemplateServiceImpl.java | 123 ++++++++++++++++--- .../storage/image/store/ImageStoreImpl.java | 9 +- .../storage/image/BaseImageStoreDriverImpl.java | 12 +- .../storage/image/ImageStoreDriver.java | 6 +- .../manager/VmwareStorageManagerImpl.java | 76 +++++++----- .../template/HypervisorTemplateAdapter.java | 63 ---------- server/src/com/cloud/vm/UserVmManagerImpl.java | 16 ++- 13 files changed, 249 insertions(+), 219 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fa0897f9/api/src/com/cloud/agent/api/to/DatadiskTO.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/agent/api/to/DatadiskTO.java b/api/src/com/cloud/agent/api/to/DatadiskTO.java new file mode 100644 index 0000000..514ca98 --- /dev/null +++ b/api/src/com/cloud/agent/api/to/DatadiskTO.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.cloud.agent.api.to; + +public class DatadiskTO { + private String path; + private long virtualSize; + private long fileSize; + boolean bootable; + + public DatadiskTO() { + } + + public DatadiskTO(String path, long virtualSize, long fileSize, boolean bootable) { + this.path = path; + this.virtualSize = virtualSize; + this.fileSize = fileSize; + this.bootable = bootable; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public Long getVirtualSize() { + return virtualSize; + } + + public void setVirtualSize(Long virtualSize) { + this.virtualSize = virtualSize; + } + + public Long getFileSize() { + return fileSize; + } + + public boolean isBootable() { + return bootable; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fa0897f9/api/src/com/cloud/agent/api/to/DatadiskTemplateTO.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/agent/api/to/DatadiskTemplateTO.java b/api/src/com/cloud/agent/api/to/DatadiskTemplateTO.java deleted file mode 100644 index 34d7237..0000000 --- a/api/src/com/cloud/agent/api/to/DatadiskTemplateTO.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package com.cloud.agent.api.to; - -public class DatadiskTemplateTO { - private long id; - private String uniqueName; - private String path; - private Long virtualSize; - private Long fileSize; - - public DatadiskTemplateTO() { - } - - public DatadiskTemplateTO(long id, String uniqueName, String path, Long virtualSize, Long fileSize) { - this.id = id; - this.uniqueName = uniqueName; - this.path = path; - this.virtualSize = virtualSize; - this.fileSize = fileSize; - } - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public String getUniqueName() { - return uniqueName; - } - - public void setUniqueName(String uniqueName) { - this.uniqueName = uniqueName; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public Long getVirtualSize() { - return virtualSize; - } - - public void setVirtualSize(Long virtualSize) { - this.virtualSize = virtualSize; - } - - public Long getFileSize() { - return fileSize; - } -} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fa0897f9/core/src/com/cloud/agent/api/storage/CreateDatadiskTemplateCommand.java ---------------------------------------------------------------------- diff --git a/core/src/com/cloud/agent/api/storage/CreateDatadiskTemplateCommand.java b/core/src/com/cloud/agent/api/storage/CreateDatadiskTemplateCommand.java index bd3843b..548cc45 100644 --- a/core/src/com/cloud/agent/api/storage/CreateDatadiskTemplateCommand.java +++ b/core/src/com/cloud/agent/api/storage/CreateDatadiskTemplateCommand.java @@ -23,12 +23,14 @@ public final class CreateDatadiskTemplateCommand extends Command { private DataTO dataDiskTemplate; private String path; private long fileSize; + private boolean bootable; - public CreateDatadiskTemplateCommand(DataTO dataDiskTemplate, String path, long fileSize) { + public CreateDatadiskTemplateCommand(DataTO dataDiskTemplate, String path, long fileSize, boolean bootable) { super(); this.dataDiskTemplate = dataDiskTemplate; this.path = path; this.fileSize = fileSize; + this.bootable = bootable; } protected CreateDatadiskTemplateCommand() { @@ -51,4 +53,8 @@ public final class CreateDatadiskTemplateCommand extends Command { public long getFileSize() { return fileSize; } + + public boolean getBootable() { + return bootable; + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fa0897f9/core/src/com/cloud/agent/api/storage/GetDatadisksAnswer.java ---------------------------------------------------------------------- diff --git a/core/src/com/cloud/agent/api/storage/GetDatadisksAnswer.java b/core/src/com/cloud/agent/api/storage/GetDatadisksAnswer.java index ffcf26f..5892217 100644 --- a/core/src/com/cloud/agent/api/storage/GetDatadisksAnswer.java +++ b/core/src/com/cloud/agent/api/storage/GetDatadisksAnswer.java @@ -20,17 +20,17 @@ import java.util.ArrayList; import java.util.List; import com.cloud.agent.api.Answer; -import com.cloud.utils.Ternary; +import com.cloud.agent.api.to.DatadiskTO; public class GetDatadisksAnswer extends Answer { - List<Ternary<String, Long, Long>> dataDiskDetails = new ArrayList<Ternary<String, Long, Long>>(); + List<DatadiskTO> dataDiskDetails = new ArrayList<DatadiskTO>(); - public GetDatadisksAnswer(List<Ternary<String, Long, Long>> dataDiskDetails) { + public GetDatadisksAnswer(List<DatadiskTO> dataDiskDetails) { super(null); this.dataDiskDetails = dataDiskDetails; } - public List<Ternary<String, Long, Long>> getDataDiskDetails() { + public List<DatadiskTO> getDataDiskDetails() { return dataDiskDetails; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fa0897f9/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java ---------------------------------------------------------------------- diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java index ff045bc..b416e9d 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java @@ -18,15 +18,12 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; -import java.util.List; - import org.apache.cloudstack.framework.async.AsyncCallFuture; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.storage.command.CommandResult; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.StoragePool; -import com.cloud.utils.Ternary; public interface TemplateService { @@ -69,7 +66,5 @@ public interface TemplateService { void associateCrosszoneTemplatesToZone(long dcId); - List<Ternary<String, Long, Long>> getDatadiskTemplates(TemplateInfo template); - - AsyncCallFuture<TemplateApiResult> createDatadiskTemplateAsync(TemplateInfo parentTemplate, TemplateInfo dataDiskTemplate, String path, long fileSize); + AsyncCallFuture<TemplateApiResult> createDatadiskTemplateAsync(TemplateInfo parentTemplate, TemplateInfo dataDiskTemplate, String path, long fileSize, boolean bootable); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fa0897f9/engine/api/src/org/apache/cloudstack/storage/image/datastore/ImageStoreEntity.java ---------------------------------------------------------------------- diff --git a/engine/api/src/org/apache/cloudstack/storage/image/datastore/ImageStoreEntity.java b/engine/api/src/org/apache/cloudstack/storage/image/datastore/ImageStoreEntity.java index be419b4..223fc4d 100644 --- a/engine/api/src/org/apache/cloudstack/storage/image/datastore/ImageStoreEntity.java +++ b/engine/api/src/org/apache/cloudstack/storage/image/datastore/ImageStoreEntity.java @@ -29,9 +29,9 @@ import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import com.cloud.agent.api.to.DatadiskTO; import com.cloud.storage.ImageStore; import com.cloud.storage.Storage.ImageFormat; -import com.cloud.utils.Ternary; public interface ImageStoreEntity extends DataStore, ImageStore { TemplateInfo getTemplate(long templateId); @@ -48,7 +48,7 @@ public interface ImageStoreEntity extends DataStore, ImageStore { String createEntityExtractUrl(String installPath, ImageFormat format, DataObject dataObject); // get the entity download URL - List<Ternary<String, Long, Long>> getDatadiskTemplates(DataObject obj); + List<DatadiskTO> getDatadiskTemplates(DataObject obj); - Void createDataDiskTemplateAsync(TemplateInfo dataDiskTemplate, String path, long fileSize, AsyncCompletionCallback<CreateCmdResult> callback); + Void createDataDiskTemplateAsync(TemplateInfo dataDiskTemplate, String path, long fileSize, boolean bootable, AsyncCompletionCallback<CreateCmdResult> callback); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fa0897f9/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java ---------------------------------------------------------------------- diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java index ffdfcba..c539dab 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java @@ -67,14 +67,17 @@ import org.apache.cloudstack.storage.to.TemplateObjectTO; import com.cloud.agent.api.Answer; import com.cloud.agent.api.storage.ListTemplateAnswer; import com.cloud.agent.api.storage.ListTemplateCommand; +import com.cloud.agent.api.to.DatadiskTO; import com.cloud.alert.AlertManager; import com.cloud.configuration.Config; +import com.cloud.configuration.Resource.ResourceType; import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.DataCenterDao; import com.cloud.exception.ResourceAllocationException; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ScopeType; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; import com.cloud.storage.StoragePool; @@ -91,9 +94,11 @@ import com.cloud.template.TemplateManager; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.ResourceLimitService; -import com.cloud.utils.Ternary; import com.cloud.utils.UriUtils; import com.cloud.utils.db.GlobalLock; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.db.TransactionCallbackNoReturn; +import com.cloud.utils.db.TransactionStatus; import com.cloud.utils.exception.CloudRuntimeException; @Component @@ -581,6 +586,18 @@ public class TemplateServiceImpl implements TemplateService { return null; } + // Check if OVA contains additional data disks. If yes, create Datadisk templates for each of the additional datadisk present in the OVA + if (template.getFormat().equals(ImageFormat.OVA)) { + if(!createDataDiskTemplates(template)) { + template.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed); + result.setResult(callbackResult.getResult()); + if (parentCallback != null) { + parentCallback.complete(result); + } + return null; + } + } + try { template.processEvent(ObjectInDataStoreStateMachine.Event.OperationSuccessed); } catch (Exception e) { @@ -597,6 +614,81 @@ public class TemplateServiceImpl implements TemplateService { return null; } + protected boolean createDataDiskTemplates(TemplateInfo parentTemplate) { + TemplateApiResult result = null; + // Get Datadisk template (if any) for OVA + List<DatadiskTO> dataDiskTemplates = new ArrayList<DatadiskTO>(); + ImageStoreEntity tmpltStore = (ImageStoreEntity)parentTemplate.getDataStore(); + dataDiskTemplates = tmpltStore.getDatadiskTemplates(parentTemplate); + s_logger.error("Found " + dataDiskTemplates.size() + " Datadisk template(s) for template: " + parentTemplate.getId()); + int diskCount = 1; + VMTemplateVO template = _templateDao.findById(parentTemplate.getId()); + DataStore imageStore = parentTemplate.getDataStore(); + for (DatadiskTO dataDiskTemplate : dataDiskTemplates) { + if (dataDiskTemplate.isBootable()) + continue; + // Make an entry in vm_template table + final long templateId = _templateDao.getNextInSequence(Long.class, "id"); + VMTemplateVO templateVO = new VMTemplateVO(templateId, template.getName() + "-DataDiskTemplate-" + diskCount, template.getFormat(), false, false, false, + TemplateType.DATADISK, template.getUrl(), template.requiresHvm(), template.getBits(), template.getAccountId(), null, + template.getDisplayText() + "-DataDiskTemplate", false, 0, false, template.getHypervisorType(), null, null, false, false); + templateVO.setParentTemplateId(template.getId()); + templateVO.setSize(dataDiskTemplate.getVirtualSize()); + templateVO = _templateDao.persist(templateVO); + // Make sync call to create Datadisk templates in image store + TemplateInfo dataDiskTemplateInfo = imageFactory.getTemplate(templateVO.getId(), imageStore); + AsyncCallFuture<TemplateApiResult> future = createDatadiskTemplateAsync(parentTemplate, dataDiskTemplateInfo, dataDiskTemplate.getPath(), + dataDiskTemplate.getFileSize(), dataDiskTemplate.isBootable()); + try { + result = future.get(); + if (result.isSuccess()) { + // Make an entry in template_zone_ref table + if (imageStore.getScope().getScopeType() == ScopeType.REGION) { + associateTemplateToZone(templateId, null); + } else if (imageStore.getScope().getScopeType() == ScopeType.ZONE) { + Long zoneId = ((ImageStoreEntity)imageStore).getDataCenterId(); + VMTemplateZoneVO templateZone = new VMTemplateZoneVO(zoneId, templateId, new Date()); + _vmTemplateZoneDao.persist(templateZone); + } + _resourceLimitMgr.incrementResourceCount(template.getAccountId(), ResourceType.secondary_storage, templateVO.getSize()); + } else { + // Cleanup Datadisk template enries in case of failure + Transaction.execute(new TransactionCallbackNoReturn() { + @Override + public void doInTransactionWithoutResult(TransactionStatus status) { + _vmTemplateStoreDao.deletePrimaryRecordsForTemplate(templateId); + _vmTemplateZoneDao.deletePrimaryRecordsForTemplate(templateId); + _templateDao.expunge(templateId); + } + }); + // Don't create the remaining Datadisk templates if creation of any of the Datadisk template failed + s_logger.error("Creation of Datadisk: " + templateVO.getId() + " failed: " + result.getResult()); + return false; + } + } catch (Exception e) { + s_logger.error("Creation of Datadisk: " + templateVO.getId() + " failed: " + result.getResult()); + return false; + } + diskCount++; + } + // Create disk template for the bootable parent template + for (DatadiskTO dataDiskTemplate : dataDiskTemplates) { + if (dataDiskTemplate.isBootable()) { + TemplateInfo templateInfo = imageFactory.getTemplate(template.getId(), imageStore); + AsyncCallFuture<TemplateApiResult> templateFuture = createDatadiskTemplateAsync(parentTemplate, templateInfo, dataDiskTemplate.getPath(), + dataDiskTemplate.getFileSize(), dataDiskTemplate.isBootable()); + try { + result = templateFuture.get(); + return result.isSuccess(); + } catch (Exception e) { + s_logger.error("Creation of template: " + template.getId() + " failed: " + result.getResult()); + return false; + } + } + } + return true; + } + @Override public AsyncCallFuture<TemplateApiResult> deleteTemplateAsync(TemplateInfo template) { TemplateObject to = (TemplateObject)template; @@ -891,14 +983,6 @@ public class TemplateServiceImpl implements TemplateService { } } - @Override - public List<Ternary<String, Long, Long>> getDatadiskTemplates(TemplateInfo template) { - List<Ternary<String, Long, Long>> dataDiskDetails = new ArrayList<Ternary<String, Long, Long>>(); - ImageStoreEntity tmpltStore = (ImageStoreEntity)template.getDataStore(); - dataDiskDetails = tmpltStore.getDatadiskTemplates(template); - return dataDiskDetails; - } - private class CreateDataDiskTemplateContext<T> extends AsyncRpcContext<T> { private final DataObject dataDiskTemplate; private final AsyncCallFuture<TemplateApiResult> future; @@ -915,18 +999,23 @@ public class TemplateServiceImpl implements TemplateService { } @Override - public AsyncCallFuture<TemplateApiResult> createDatadiskTemplateAsync(TemplateInfo parentTemplate, TemplateInfo dataDiskTemplate, String path, long fileSize) { + public AsyncCallFuture<TemplateApiResult> createDatadiskTemplateAsync(TemplateInfo parentTemplate, TemplateInfo dataDiskTemplate, String path, long fileSize, boolean bootable) { AsyncCallFuture<TemplateApiResult> future = new AsyncCallFuture<TemplateApiResult>(); // Make an entry for Datadisk template in template_store_ref table DataStore store = parentTemplate.getDataStore(); - TemplateObject dataDiskTemplateOnStore = (TemplateObject)store.create(dataDiskTemplate); - dataDiskTemplateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.CreateOnlyRequested); + TemplateObject dataDiskTemplateOnStore; + if (!bootable) { + dataDiskTemplateOnStore = (TemplateObject)store.create(dataDiskTemplate); + dataDiskTemplateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.CreateOnlyRequested); + } else { + dataDiskTemplateOnStore = (TemplateObject) imageFactory.getTemplate(parentTemplate, store); + } try { CreateDataDiskTemplateContext<TemplateApiResult> context = new CreateDataDiskTemplateContext<TemplateApiResult>(null, dataDiskTemplateOnStore, future); AsyncCallbackDispatcher<TemplateServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this); - caller.setCallback(caller.getTarget().createDataDiskTemplateCallback(null, null)).setContext(context); + caller.setCallback(caller.getTarget().createDatadiskTemplateCallback(null, null)).setContext(context); ImageStoreEntity tmpltStore = (ImageStoreEntity)parentTemplate.getDataStore(); - tmpltStore.createDataDiskTemplateAsync(dataDiskTemplate, path, fileSize, caller); + tmpltStore.createDataDiskTemplateAsync(dataDiskTemplate, path, fileSize, bootable, caller); } catch (CloudRuntimeException ex) { dataDiskTemplateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed); TemplateApiResult result = new TemplateApiResult(dataDiskTemplate); @@ -938,7 +1027,7 @@ public class TemplateServiceImpl implements TemplateService { return future; } - protected Void createDataDiskTemplateCallback(AsyncCallbackDispatcher<TemplateServiceImpl, CreateCmdResult> callback, CreateDataDiskTemplateContext<TemplateApiResult> context) { + protected Void createDatadiskTemplateCallback(AsyncCallbackDispatcher<TemplateServiceImpl, CreateCmdResult> callback, CreateDataDiskTemplateContext<TemplateApiResult> context) { if (s_logger.isDebugEnabled()) { s_logger.debug("Performing create datadisk template cross callback after completion"); } @@ -954,10 +1043,10 @@ public class TemplateServiceImpl implements TemplateService { dataDiskTemplateResult.setResult(result.getResult()); } } catch (Exception e) { - s_logger.debug("Failed to process copy template cross zones callback", e); + s_logger.debug("Failed to process create datadisk template callback", e); dataDiskTemplateResult.setResult(e.toString()); } future.complete(dataDiskTemplateResult); return null; } -} +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fa0897f9/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java ---------------------------------------------------------------------- diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java index 0a3b7e8..97f09d0 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java @@ -45,12 +45,12 @@ import org.apache.cloudstack.storage.image.ImageStoreDriver; import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity; import org.apache.cloudstack.storage.to.ImageStoreTO; +import com.cloud.agent.api.to.DatadiskTO; import com.cloud.agent.api.to.DataStoreTO; import com.cloud.capacity.dao.CapacityDao; import com.cloud.storage.DataStoreRole; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.utils.Ternary; import com.cloud.utils.component.ComponentContext; public class ImageStoreImpl implements ImageStoreEntity { @@ -208,13 +208,12 @@ public class ImageStoreImpl implements ImageStoreEntity { } @Override - public List<Ternary<String, Long, Long>> getDatadiskTemplates(DataObject obj) { + public List<DatadiskTO> getDatadiskTemplates(DataObject obj) { return driver.getDatadiskTemplates(obj); } @Override - public Void createDataDiskTemplateAsync(TemplateInfo dataDiskTemplate, String path, long fileSize, AsyncCompletionCallback<CreateCmdResult> callback) { - return driver.createDataDiskTemplateAsync(dataDiskTemplate, path, fileSize, callback); - + public Void createDataDiskTemplateAsync(TemplateInfo dataDiskTemplate, String path, long fileSize, boolean bootable, AsyncCompletionCallback<CreateCmdResult> callback) { + return driver.createDataDiskTemplateAsync(dataDiskTemplate, path, bootable, fileSize, callback); } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fa0897f9/engine/storage/src/org/apache/cloudstack/storage/image/BaseImageStoreDriverImpl.java ---------------------------------------------------------------------- diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/BaseImageStoreDriverImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/BaseImageStoreDriverImpl.java index 94366ef..b170c75 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/BaseImageStoreDriverImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/BaseImageStoreDriverImpl.java @@ -54,6 +54,7 @@ import com.cloud.agent.api.storage.DownloadAnswer; import com.cloud.agent.api.storage.GetDatadisksAnswer; import com.cloud.agent.api.storage.GetDatadisksCommand; import com.cloud.agent.api.storage.Proxy; +import com.cloud.agent.api.to.DatadiskTO; import com.cloud.agent.api.to.DataObjectType; import com.cloud.agent.api.to.DataTO; import com.cloud.hypervisor.Hypervisor.HypervisorType; @@ -66,7 +67,6 @@ import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.download.DownloadMonitor; import com.cloud.user.ResourceLimitService; import com.cloud.user.dao.AccountDao; -import com.cloud.utils.Ternary; public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver { private static final Logger s_logger = Logger.getLogger(BaseImageStoreDriverImpl.class); @@ -293,8 +293,8 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver { } @Override - public List<Ternary<String, Long, Long>> getDatadiskTemplates(DataObject obj) { - List<Ternary<String, Long, Long>> dataDiskDetails = new ArrayList<Ternary<String, Long, Long>>(); + public List<DatadiskTO> getDatadiskTemplates(DataObject obj) { + List<DatadiskTO> dataDiskDetails = new ArrayList<DatadiskTO>(); if (s_logger.isDebugEnabled()) { s_logger.debug("Get the data disks present in the OVA template"); } @@ -311,20 +311,20 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver { } if (answer != null && answer.getResult()) { GetDatadisksAnswer getDatadisksAnswer = (GetDatadisksAnswer)answer; - dataDiskDetails = getDatadisksAnswer.getDataDiskDetails(); // Details - Disk path, virtual size + dataDiskDetails = getDatadisksAnswer.getDataDiskDetails(); // Details - Disk path, virtual size, bootable } return dataDiskDetails; } @Override - public Void createDataDiskTemplateAsync(TemplateInfo dataDiskTemplate, String path, long fileSize, + public Void createDataDiskTemplateAsync(TemplateInfo dataDiskTemplate, String path, boolean bootable, long fileSize, AsyncCompletionCallback<CreateCmdResult> callback) { Answer answer = null; String errMsg = null; if (s_logger.isDebugEnabled()) { s_logger.debug("Create Datadisk template: " + dataDiskTemplate.getId()); } - CreateDatadiskTemplateCommand cmd = new CreateDatadiskTemplateCommand(dataDiskTemplate.getTO(), path, fileSize); + CreateDatadiskTemplateCommand cmd = new CreateDatadiskTemplateCommand(dataDiskTemplate.getTO(), path, fileSize, bootable); EndPoint ep = _defaultEpSelector.selectHypervisorHostByType(dataDiskTemplate.getDataStore().getScope(), HypervisorType.VMware); if (ep == null) { errMsg = "No remote endpoint to send command, check if host or ssvm is down?"; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fa0897f9/engine/storage/src/org/apache/cloudstack/storage/image/ImageStoreDriver.java ---------------------------------------------------------------------- diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/ImageStoreDriver.java b/engine/storage/src/org/apache/cloudstack/storage/image/ImageStoreDriver.java index e4e9451..a262c9b 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/ImageStoreDriver.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/ImageStoreDriver.java @@ -27,13 +27,13 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import com.cloud.agent.api.to.DatadiskTO; import com.cloud.storage.Storage.ImageFormat; -import com.cloud.utils.Ternary; public interface ImageStoreDriver extends DataStoreDriver { String createEntityExtractUrl(DataStore store, String installPath, ImageFormat format, DataObject dataObject); - List<Ternary<String, Long, Long>> getDatadiskTemplates(DataObject obj); + List<DatadiskTO> getDatadiskTemplates(DataObject obj); - Void createDataDiskTemplateAsync(TemplateInfo dataDiskTemplate, String path, long fileSize, AsyncCompletionCallback<CreateCmdResult> callback); + Void createDataDiskTemplateAsync(TemplateInfo dataDiskTemplate, String path, boolean bootable, long fileSize, AsyncCompletionCallback<CreateCmdResult> callback); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fa0897f9/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java index 9a3ce40..b1001f8 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java @@ -68,6 +68,7 @@ import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; 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.DatadiskTO; import com.cloud.agent.api.to.NfsTO; import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.hypervisor.vmware.mo.CustomFieldConstants; @@ -550,7 +551,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { @Override public Answer execute(VmwareHostService hostService, GetDatadisksCommand cmd) { - List<Ternary<String, Long, Long>> datDiskDetails = new ArrayList<Ternary<String, Long, Long>>(); + List<DatadiskTO> disks = new ArrayList<DatadiskTO>(); DataTO srcData = cmd.getData(); TemplateObjectTO template = (TemplateObjectTO)srcData; DataStoreTO srcStore = srcData.getDataStore(); @@ -603,22 +604,19 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { s_logger.debug("Reading OVF " + ovfFilePath + " to retrive the number of disks present in OVA"); List<Pair<String, Boolean>> ovfVolumeDetails = HypervisorHostHelper.readOVF(hyperHost, ovfFilePath, datastoreMo); - // Get the virtual size of data disk + // Get OVA disk details for (Pair<String, Boolean> ovfVolumeDetail : ovfVolumeDetails) { - if (ovfVolumeDetail.second()) { // ROOT disk - continue; - } String dataDiskPath = ovfVolumeDetail.first(); String diskName = dataDiskPath.substring((dataDiskPath.lastIndexOf(File.separator)) + 1); Pair<Long, Long> diskDetails = new OVAProcessor().getDiskDetails(ovfFilePath, diskName); - datDiskDetails.add(new Ternary<String, Long, Long>(dataDiskPath, diskDetails.first(), diskDetails.second())); + disks.add(new DatadiskTO(dataDiskPath, diskDetails.first(), diskDetails.second(), ovfVolumeDetail.second())); } } catch (Exception e) { String msg = "Get Datadisk Template Count failed due to " + e.getMessage(); s_logger.error(msg); return new GetDatadisksAnswer(msg); } - return new GetDatadisksAnswer(datDiskDetails); + return new GetDatadisksAnswer(disks); } @Override @@ -653,36 +651,50 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { long physicalSize = new File(dataDiskPath).length(); String dataDiskTemplateFolderPath = getTemplateRelativeDirInSecStorage(dataDiskTemplate.getAccountId(), dataDiskTemplate.getId()); String dataDiskTemplateFolderFullPath = secondaryMountPoint + "/" + dataDiskTemplateFolderPath; + String ovfName = diskName.substring(0, diskName.lastIndexOf("-")); + String datastorePath = String.format("[%s] %s", datastoreMo.getName(), dataDiskTemplateFolderPath); - // Create folder to hold datadisk template - synchronized (dataDiskTemplateFolderPath.intern()) { - Script command = new Script(false, "mkdir", _timeout, s_logger); - command.add("-p"); - command.add(dataDiskTemplateFolderFullPath); - String result = command.execute(); - if (result != null) { - String msg = "Unable to prepare template directory: " + dataDiskTemplateFolderPath + ", storage: " + secondaryStorageUrl + ", error msg: " + result; - s_logger.error(msg); - throw new Exception(msg); + if (!cmd.getBootable()) { + // Create folder to hold datadisk template + synchronized (dataDiskTemplateFolderPath.intern()) { + Script command = new Script(false, "mkdir", _timeout, s_logger); + command.add("-p"); + command.add(dataDiskTemplateFolderFullPath); + String result = command.execute(); + if (result != null) { + String msg = "Unable to prepare template directory: " + dataDiskTemplateFolderPath + ", storage: " + secondaryStorageUrl + ", error msg: " + result; + s_logger.error(msg); + throw new Exception(msg); + } } - } - - // Copy Datadisk VMDK from parent template folder to Datadisk template folder - synchronized (dataDiskPath.intern()) { - Script command = new Script(false, "cp", _timeout, s_logger); - command.add(dataDiskPath); - command.add(dataDiskTemplateFolderFullPath); - String result = command.execute(); - if (result != null) { - String msg = "Unable to copy VMDK from parent template folder to datadisk template folder" + ", error msg: " + result; - s_logger.error(msg); - throw new Exception(msg); + // Move Datadisk VMDK from parent template folder to Datadisk template folder + synchronized (dataDiskPath.intern()) { + Script command = new Script(false, "mv", _timeout, s_logger); + command.add(dataDiskPath); + command.add(dataDiskTemplateFolderFullPath); + String result = command.execute(); + if (result != null) { + String msg = "Unable to copy VMDK from parent template folder to datadisk template folder" + ", error msg: " + result; + s_logger.error(msg); + throw new Exception(msg); + } + } + } else { + // Delete original OVA as a new OVA will be created for the root disk template + String rootDiskTemplatePath = dataDiskTemplate.getPath(); + String rootDiskTemplateFullPath = secondaryMountPoint + "/" + rootDiskTemplatePath; + synchronized (rootDiskTemplateFullPath.intern()) { + Script command = new Script(false, "rm", _timeout, s_logger); + command.add(rootDiskTemplateFullPath); + String result = command.execute(); + if (result != null) { + String msg = "Unable to delete original OVA" + ", error msg: " + result; + s_logger.error(msg); + throw new Exception(msg); + } } } - String ovfName = diskName.substring(0, diskName.lastIndexOf("-")); - String datastorePath = String.format("[%s] %s", datastoreMo.getName(), dataDiskTemplateFolderPath); - // Create OVF for Datadisk s_logger.debug("Creating OVF file for datadisk " + diskName + " in " + dataDiskTemplateFolderFullPath); HypervisorHostHelper.createOvfFile(hyperHost, diskName, ovfName, datastorePath, dataDiskTemplateFolderFullPath, virtualSize, fileSize, morDs); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fa0897f9/server/src/com/cloud/template/HypervisorTemplateAdapter.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/template/HypervisorTemplateAdapter.java b/server/src/com/cloud/template/HypervisorTemplateAdapter.java index f984872..8bef4a5 100755 --- a/server/src/com/cloud/template/HypervisorTemplateAdapter.java +++ b/server/src/com/cloud/template/HypervisorTemplateAdapter.java @@ -19,7 +19,6 @@ package com.cloud.template; import java.net.MalformedURLException; import java.net.URL; import java.util.Collections; -import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -75,13 +74,9 @@ import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.storage.download.DownloadMonitor; import com.cloud.user.Account; import com.cloud.utils.Pair; -import com.cloud.utils.Ternary; import com.cloud.utils.UriUtils; import com.cloud.utils.db.DB; import com.cloud.utils.db.EntityManager; -import com.cloud.utils.db.Transaction; -import com.cloud.utils.db.TransactionCallbackNoReturn; -import com.cloud.utils.db.TransactionStatus; import com.cloud.utils.exception.CloudRuntimeException; @Local(value = TemplateAdapter.class) @@ -301,10 +296,6 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase { TemplateInfo template = context.template; if (result.isSuccess()) { VMTemplateVO tmplt = _tmpltDao.findById(template.getId()); - // Check if OVA contains additional data disks. If yes, create Datadisk templates for each of the additional datadisk present in the OVA - if (template.getFormat().equals(ImageFormat.OVA)) { - createDataDiskTemplates(template); - } // need to grant permission for public templates if (tmplt.isPublicTemplate()) { _messageBus.publish(_name, TemplateManager.MESSAGE_REGISTER_PUBLIC_TEMPLATE_EVENT, PublishScope.LOCAL, tmplt.getId()); @@ -346,60 +337,6 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase { return null; } - private void createDataDiskTemplates(TemplateInfo parentTemplate) { - TemplateApiResult result = null; - VMTemplateVO template = _tmpltDao.findById(parentTemplate.getId()); - DataStore imageStore = parentTemplate.getDataStore(); - List<Ternary<String, Long, Long>> dataDiskTemplates = imageService.getDatadiskTemplates(parentTemplate); - s_logger.error("Found " + dataDiskTemplates.size() + " Datadisk templates for template: " + parentTemplate.getId()); - int diskCount = 1; - for (Ternary<String, Long, Long> dataDiskTemplate : dataDiskTemplates) { - // Make an entry in vm_template table - final long templateId = _templateDao.getNextInSequence(Long.class, "id"); - VMTemplateVO templateVO = new VMTemplateVO(templateId, template.getName() + "-DataDiskTemplate-" + diskCount, template.getFormat(), false, false, false, - TemplateType.DATADISK, template.getUrl(), template.requiresHvm(), template.getBits(), template.getAccountId(), null, - template.getDisplayText() + "-DataDiskTemplate", false, 0, false, template.getHypervisorType(), null, null, false, false); - templateVO.setParentTemplateId(template.getId()); - templateVO.setSize(dataDiskTemplate.second()); - templateVO = _templateDao.persist(templateVO); - // Make sync call to create Datadisk templates in image store - TemplateInfo dataDiskTemplateInfo = imageFactory.getTemplate(templateVO.getId(), imageStore); - AsyncCallFuture<TemplateApiResult> future = imageService.createDatadiskTemplateAsync(parentTemplate, dataDiskTemplateInfo, dataDiskTemplate.first(), - dataDiskTemplate.third()); - try { - result = future.get(); - if (result.isSuccess()) { - // Make an entry in template_zone_ref table - if (imageStore.getScope().getScopeType() == ScopeType.REGION) { - imageService.associateTemplateToZone(templateId, null); - } else if (imageStore.getScope().getScopeType() == ScopeType.ZONE) { - Long zoneId = ((ImageStoreEntity)imageStore).getDataCenterId(); - VMTemplateZoneVO templateZone = new VMTemplateZoneVO(zoneId, templateId, new Date()); - _tmpltZoneDao.persist(templateZone); - } - _resourceLimitMgr.incrementResourceCount(template.getAccountId(), ResourceType.secondary_storage, templateVO.getSize()); - } else { - // Cleanup Datadisk template enries in case of failure - Transaction.execute(new TransactionCallbackNoReturn() { - @Override - public void doInTransactionWithoutResult(TransactionStatus status) { - _tmplStoreDao.deletePrimaryRecordsForTemplate(templateId); - _tmpltZoneDao.deletePrimaryRecordsForTemplate(templateId); - _tmpltDao.expunge(templateId); - } - }); - // Continue to create the remaining Datadisk templates even if creation of 1 Datadisk template failes - s_logger.error("Creation of Datadisk: " + templateVO.getId() + " failed: " + result.getResult()); - continue; - } - } catch (Exception e) { - s_logger.error("Creation of Datadisk: " + templateVO.getId() + " failed: " + result.getResult()); - continue; - } - diskCount++; - } - } - @Override @DB public boolean delete(TemplateProfile profile) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fa0897f9/server/src/com/cloud/vm/UserVmManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 9a0d2a1..8a719de 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -2612,18 +2612,24 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir (dataDiskTemplate.getState().equals(VirtualMachineTemplate.State.Active))) { throw new InvalidParameterValueException("Invalid template id specified for Datadisk template" + datadiskTemplateToDiskOffering.getKey()); } + long dataDiskTemplateId = datadiskTemplateToDiskOffering.getKey(); if (!dataDiskTemplate.getParentTemplateId().equals(template.getId())) { - throw new InvalidParameterValueException("Invalid Datadisk template. Specified Datadisk template " + datadiskTemplateToDiskOffering.getKey() + throw new InvalidParameterValueException("Invalid Datadisk template. Specified Datadisk template " + dataDiskTemplateId + " doesn't belong to template " + template.getId()); } if (dataDiskOffering == null) { - throw new InvalidParameterValueException("Invalid disk offering id specified" + datadiskTemplateToDiskOffering.getValue()); + throw new InvalidParameterValueException("Invalid disk offering id " + datadiskTemplateToDiskOffering.getValue().getId() + + " specified for datadisk template " + dataDiskTemplateId); } - _templateDao.loadDetails(dataDiskTemplate); if (dataDiskOffering.isCustomized()) { - throw new InvalidParameterValueException("Invalid disk offering id specified" + datadiskTemplateToDiskOffering.getValue() + ". Custom Disk offerings are not" + - " supported for Datadisk templates"); + throw new InvalidParameterValueException("Invalid disk offering id " + dataDiskOffering.getId() + " specified for datadisk template " + + dataDiskTemplateId + ". Custom Disk offerings are not supported for Datadisk templates"); + } + if (dataDiskOffering.getDiskSize() < dataDiskTemplate.getSize()) { + throw new InvalidParameterValueException("Invalid disk offering id " + dataDiskOffering.getId() + " specified for datadisk template " + + dataDiskTemplateId + ". Disk offering size should be greater than or equal to the template size"); } + _templateDao.loadDetails(dataDiskTemplate); _resourceLimitMgr.checkResourceLimit(owner, ResourceType.volume, 1); _resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, dataDiskOffering.getDiskSize()); }