Skip to content

Commit bbc0ae8

Browse files
authored
storage: post process locally uploaded multi-disk ova template (#3215)
Problem: When a multi-disk OVA template is uploaded, only the root disk is recognized and VMs deployed using such template only get the root disk provisioned. Root Cause: The template processor for multi-disk OVA was not used in the template upload processor. Solution: Added support for local multi-disk OVA template upload. After a multi-disk OVA template is uploaded, the mechanism that worked on multi-disk OVA templates registered using URL is now also used to discovers and creates data-disk templates in cloud.vm_template table and on the secondary storage. To enable SSL on SSVMs : • Upload the certificates like you usually do via the API or UI->Infrastructure tab • Set the global settings secstorage.encrypt.copy, secstorage.ssl.cert.domain to appropriate values along with the CPVM ones • Restart management server (no need to destroy/restart SSVM (or the ssvm agent)) Test cases: - Upload template and check it creates multi-disk folders on secondary storage and entries in cloud.vm_template table - Upload template and kill/shutdown management server. Then restart MS to check if template sync works - Copy template across zone of an uploaded template Signed-off-by: Rohit Yadav rohit.yadav@shapeblue.com
1 parent f7af27c commit bbc0ae8

4 files changed

Lines changed: 43 additions & 10 deletions

File tree

engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ public TemplateInfo getTemplate() {
4747

4848
AsyncCallFuture<TemplateApiResult> createTemplateFromVolumeAsync(VolumeInfo volume, TemplateInfo template, DataStore store);
4949

50+
boolean createOvaDataDiskTemplates(TemplateInfo parentTemplate);
51+
5052
AsyncCallFuture<TemplateApiResult> deleteTemplateAsync(TemplateInfo template);
5153

5254
AsyncCallFuture<TemplateApiResult> copyTemplate(TemplateInfo srcTemplate, DataStore destStore);

engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/TemplateServiceImpl.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -409,8 +409,15 @@ public void handleTemplateSync(DataStore store) {
409409
_templateDao.update(tmplt.getId(), tmlpt);
410410

411411
if (tmplt.getState() == VirtualMachineTemplate.State.NotUploaded || tmplt.getState() == VirtualMachineTemplate.State.UploadInProgress) {
412+
VirtualMachineTemplate.Event event = VirtualMachineTemplate.Event.OperationSucceeded;
413+
// For multi-disk OVA, check and create data disk templates
414+
if (tmplt.getFormat().equals(ImageFormat.OVA)) {
415+
if (!createOvaDataDiskTemplates(_templateFactory.getTemplate(tmlpt.getId(), store))) {
416+
event = VirtualMachineTemplate.Event.OperationFailed;
417+
}
418+
}
412419
try {
413-
stateMachine.transitTo(tmplt, VirtualMachineTemplate.Event.OperationSucceeded, null, _templateDao);
420+
stateMachine.transitTo(tmplt, event, null, _templateDao);
414421
} catch (NoTransitionException e) {
415422
s_logger.error("Unexpected state transition exception for template " + tmplt.getName() + ". Details: " + e.getMessage());
416423
}
@@ -701,7 +708,7 @@ protected Void createTemplateCallback(AsyncCallbackDispatcher<TemplateServiceImp
701708
return null;
702709
}
703710

704-
// Check if OVA contains additional data disks. If yes, create Datadisk templates for each of the additional datadisk present in the OVA
711+
// For multi-disk OVA, check and create data disk templates
705712
if (template.getFormat().equals(ImageFormat.OVA)) {
706713
if (!createOvaDataDiskTemplates(template)) {
707714
template.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed);
@@ -729,8 +736,8 @@ protected Void createTemplateCallback(AsyncCallbackDispatcher<TemplateServiceImp
729736
return null;
730737
}
731738

732-
733-
protected boolean createOvaDataDiskTemplates(TemplateInfo parentTemplate) {
739+
@Override
740+
public boolean createOvaDataDiskTemplates(TemplateInfo parentTemplate) {
734741
try {
735742
// Get Datadisk template (if any) for OVA
736743
List<DatadiskTO> dataDiskTemplates = new ArrayList<DatadiskTO>();

engine/storage/src/main/java/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ public ObjectInDataStoreManagerImpl() {
9090
stateMachines.addTransition(State.Allocated, Event.CreateOnlyRequested, State.Creating);
9191
stateMachines.addTransition(State.Allocated, Event.DestroyRequested, State.Destroying);
9292
stateMachines.addTransition(State.Allocated, Event.OperationFailed, State.Failed);
93+
stateMachines.addTransition(State.Allocated, Event.OperationSuccessed, State.Ready);
9394
stateMachines.addTransition(State.Creating, Event.OperationFailed, State.Allocated);
9495
stateMachines.addTransition(State.Creating, Event.OperationSuccessed, State.Ready);
9596
stateMachines.addTransition(State.Ready, Event.CopyingRequested, State.Copying);

server/src/main/java/com/cloud/storage/ImageStoreUploadMonitorImpl.java

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,14 @@
2525
import javax.inject.Inject;
2626
import javax.naming.ConfigurationException;
2727

28-
import com.cloud.configuration.Resource;
29-
import com.cloud.event.EventTypes;
30-
import com.cloud.event.UsageEventUtils;
31-
import com.cloud.user.ResourceLimitService;
32-
import org.apache.log4j.Logger;
33-
import org.springframework.stereotype.Component;
3428
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
3529
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
3630
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
3731
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
3832
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
33+
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
34+
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
35+
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
3936
import org.apache.cloudstack.framework.config.ConfigKey;
4037
import org.apache.cloudstack.framework.config.Configurable;
4138
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
@@ -48,6 +45,8 @@
4845
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
4946
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
5047
import org.apache.cloudstack.utils.identity.ManagementServerNode;
48+
import org.apache.log4j.Logger;
49+
import org.springframework.stereotype.Component;
5150

5251
import com.cloud.agent.Listener;
5352
import com.cloud.agent.api.AgentControlAnswer;
@@ -56,6 +55,9 @@
5655
import com.cloud.agent.api.Command;
5756
import com.cloud.agent.api.StartupCommand;
5857
import com.cloud.alert.AlertManager;
58+
import com.cloud.configuration.Resource;
59+
import com.cloud.event.EventTypes;
60+
import com.cloud.event.UsageEventUtils;
5961
import com.cloud.exception.ConnectionException;
6062
import com.cloud.host.Host;
6163
import com.cloud.host.Status;
@@ -65,6 +67,7 @@
6567
import com.cloud.storage.dao.VMTemplateZoneDao;
6668
import com.cloud.storage.dao.VolumeDao;
6769
import com.cloud.template.VirtualMachineTemplate;
70+
import com.cloud.user.ResourceLimitService;
6871
import com.cloud.utils.component.ManagerBase;
6972
import com.cloud.utils.concurrency.NamedThreadFactory;
7073
import com.cloud.utils.db.Transaction;
@@ -102,6 +105,12 @@ public class ImageStoreUploadMonitorImpl extends ManagerBase implements ImageSto
102105
private AlertManager _alertMgr;
103106
@Inject
104107
private VMTemplateZoneDao _vmTemplateZoneDao;
108+
@Inject
109+
private DataStoreManager dataStoreManager;
110+
@Inject
111+
private TemplateDataFactory templateFactory;
112+
@Inject
113+
private TemplateService templateService;
105114

106115
private long _nodeId;
107116
private ScheduledExecutorService _executor = null;
@@ -395,6 +404,20 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
395404
VMTemplateVO templateUpdate = _templateDao.createForUpdate();
396405
templateUpdate.setSize(answer.getVirtualSize());
397406
_templateDao.update(tmpTemplate.getId(), templateUpdate);
407+
// For multi-disk OVA, check and create data disk templates
408+
if (tmpTemplate.getFormat().equals(Storage.ImageFormat.OVA)) {
409+
final DataStore store = dataStoreManager.getDataStore(templateDataStore.getDataStoreId(), templateDataStore.getDataStoreRole());
410+
final TemplateInfo templateInfo = templateFactory.getTemplate(tmpTemplate.getId(), store);
411+
if (!templateService.createOvaDataDiskTemplates(templateInfo)) {
412+
tmpTemplateDataStore.setDownloadState(VMTemplateStorageResourceAssoc.Status.ABANDONED);
413+
tmpTemplateDataStore.setState(State.Failed);
414+
stateMachine.transitTo(tmpTemplate, VirtualMachineTemplate.Event.OperationFailed, null, _templateDao);
415+
msg = "Multi-disk OVA template " + tmpTemplate.getUuid() + " failed to process data disks";
416+
s_logger.error(msg);
417+
sendAlert = true;
418+
break;
419+
}
420+
}
398421
stateMachine.transitTo(tmpTemplate, VirtualMachineTemplate.Event.OperationSucceeded, null, _templateDao);
399422
_resourceLimitMgr.incrementResourceCount(template.getAccountId(), Resource.ResourceType.secondary_storage, answer.getVirtualSize());
400423
//publish usage event

0 commit comments

Comments
 (0)