mirror of https://github.com/apache/cloudstack.git
CLOUDSTACK-4757. More updates to Datadisk template creation - update ROOT disk OVA once all the datadisks have been created
This commit is contained in:
parent
3532ffe5af
commit
fa0897f902
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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?";
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue