You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by li...@apache.org on 2014/05/19 11:47:41 UTC

git commit: updated refs/heads/multiple-disk-ova to fa0897f

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 <li...@citrix.com>
Authored: Fri May 16 11:32:10 2014 +0530
Committer: Likitha Shetty <li...@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());
             }