CLOUDSTACK-4757. More updates to Datadisk template creation - update ROOT disk OVA once all the datadisks have been created

This commit is contained in:
Likitha Shetty 2014-05-16 11:32:10 +05:30
parent 3532ffe5af
commit fa0897f902
12 changed files with 203 additions and 173 deletions

View File

@ -18,38 +18,20 @@
*/
package com.cloud.agent.api.to;
public class DatadiskTemplateTO {
private long id;
private String uniqueName;
public class DatadiskTO {
private String path;
private Long virtualSize;
private Long fileSize;
private long virtualSize;
private long fileSize;
boolean bootable;
public DatadiskTemplateTO() {
public DatadiskTO() {
}
public DatadiskTemplateTO(long id, String uniqueName, String path, Long virtualSize, Long fileSize) {
this.id = id;
this.uniqueName = uniqueName;
public DatadiskTO(String path, long virtualSize, long fileSize, boolean bootable) {
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;
this.bootable = bootable;
}
public String getPath() {
@ -71,4 +53,8 @@ public class DatadiskTemplateTO {
public Long getFileSize() {
return fileSize;
}
public boolean isBootable() {
return bootable;
}
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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?";

View File

@ -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);
}

View File

@ -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;
// 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);
}
}
String ovfName = diskName.substring(0, diskName.lastIndexOf("-"));
String datastorePath = String.format("[%s] %s", datastoreMo.getName(), dataDiskTemplateFolderPath);
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);
}
}
// 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);
}
}
}
// 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);

View File

@ -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) {

View File

@ -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);
}
if (dataDiskOffering.isCustomized()) {
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);
if (dataDiskOffering.isCustomized()) {
throw new InvalidParameterValueException("Invalid disk offering id specified" + datadiskTemplateToDiskOffering.getValue() + ". Custom Disk offerings are not" +
" supported for Datadisk templates");
}
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.volume, 1);
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, dataDiskOffering.getDiskSize());
}