Skip to content

Commit ed46a64

Browse files
committed
CLOUDSTACK-3852: fix upload volume
1 parent a2e2ef6 commit ed46a64

19 files changed

Lines changed: 161 additions & 234 deletions

File tree

core/src/com/cloud/agent/api/storage/CreateEntityDownloadURLCommand.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@
1717
package com.cloud.agent.api.storage;
1818

1919

20+
import com.cloud.agent.api.to.DataTO;
21+
2022
public class CreateEntityDownloadURLCommand extends AbstractDownloadCommand {
2123

22-
public CreateEntityDownloadURLCommand(String parent, String installPath, String uuid) { // this constructor is for creating template download url
24+
public CreateEntityDownloadURLCommand(String parent, String installPath, String uuid, DataTO data) { // this constructor is for creating template download url
2325
super();
2426
this.parent = parent; // parent is required as not the template can be child of one of many parents
2527
this.installPath = installPath;
2628
this.extractLinkUUID = uuid;
29+
this.data = data;
2730
}
2831

2932
public CreateEntityDownloadURLCommand(String installPath, String uuid) {
@@ -39,6 +42,16 @@ public CreateEntityDownloadURLCommand() {
3942
private String parent;
4043
private String extractLinkUUID;
4144

45+
public DataTO getData() {
46+
return data;
47+
}
48+
49+
public void setData(DataTO data) {
50+
this.data = data;
51+
}
52+
53+
private DataTO data;
54+
4255
@Override
4356
public boolean executeInSequence() {
4457
return false;

core/src/com/cloud/storage/resource/StoragePoolResource.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ public interface StoragePoolResource {
3535
Answer execute(DestroyCommand cmd);
3636

3737
CopyVolumeAnswer execute(CopyVolumeCommand cmd);
38-
39-
CreateVolumeOVAAnswer execute(CreateVolumeOVACommand cmd);
4038

4139
CreateAnswer execute(CreateCommand cmd);
4240
}

engine/api/src/org/apache/cloudstack/storage/image/datastore/ImageStoreEntity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,5 @@ public interface ImageStoreEntity extends DataStore, ImageStore {
4242

4343
String getMountPoint(); // get the mount point on ssvm.
4444

45-
String createEntityExtractUrl(String installPath, ImageFormat format); // get the entity download URL
45+
String createEntityExtractUrl(String installPath, ImageFormat format, DataObject dataObject); // get the entity download URL
4646
}

engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,8 @@ public String getMountPoint() {
190190
}
191191

192192
@Override
193-
public String createEntityExtractUrl(String installPath, ImageFormat format) {
194-
return driver.createEntityExtractUrl(this, installPath, format);
193+
public String createEntityExtractUrl(String installPath, ImageFormat format, DataObject dataObject) {
194+
return driver.createEntityExtractUrl(this, installPath, format, dataObject);
195195
}
196196

197197

engine/storage/src/org/apache/cloudstack/storage/image/ImageStoreDriver.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@
1818
*/
1919
package org.apache.cloudstack.storage.image;
2020

21+
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
2122
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
2223
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver;
2324

2425
import com.cloud.storage.Storage.ImageFormat;
2526

2627
public interface ImageStoreDriver extends DataStoreDriver {
27-
String createEntityExtractUrl(DataStore store, String installPath, ImageFormat format);
28+
String createEntityExtractUrl(DataStore store, String installPath, ImageFormat format, DataObject dataObject);
2829
}

plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@
2828
import javax.ejb.Local;
2929
import javax.inject.Inject;
3030

31+
import com.cloud.agent.api.storage.CreateEntityDownloadURLCommand;
3132
import com.cloud.host.Host;
33+
import com.cloud.storage.Storage;
34+
import org.apache.cloudstack.storage.to.VolumeObjectTO;
3235
import org.apache.log4j.Logger;
3336

3437
import org.apache.cloudstack.storage.command.CopyCommand;
@@ -316,6 +319,17 @@ public Pair<Boolean, Long> getCommandHostDelegation(long hostId, Command cmd) {
316319
} else {
317320
needDelegation = true;
318321
}
322+
} else if (cmd instanceof CreateEntityDownloadURLCommand) {
323+
DataTO srcData = ((CreateEntityDownloadURLCommand) cmd).getData();
324+
if ((HypervisorType.VMware == srcData.getHypervisorType())) {
325+
needDelegation = true;
326+
}
327+
if (srcData.getObjectType() == DataObjectType.VOLUME) {
328+
VolumeObjectTO volumeObjectTO = (VolumeObjectTO)srcData;
329+
if (Storage.ImageFormat.OVA == volumeObjectTO.getFormat()) {
330+
needDelegation = true;
331+
}
332+
}
319333
}
320334

321335
if(!needDelegation) {

plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManager.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,17 @@
2424
import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
2525
import com.cloud.agent.api.DeleteVMSnapshotCommand;
2626
import com.cloud.agent.api.RevertToVMSnapshotCommand;
27-
import com.cloud.agent.api.storage.CopyVolumeCommand;
28-
import com.cloud.agent.api.storage.PrepareOVAPackingCommand;
29-
import com.cloud.agent.api.storage.CreateVolumeOVACommand;
30-
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
27+
import com.cloud.agent.api.storage.*;
3128

3229
public interface VmwareStorageManager {
3330
Answer execute(VmwareHostService hostService, PrimaryStorageDownloadCommand cmd);
3431
Answer execute(VmwareHostService hostService, BackupSnapshotCommand cmd);
3532
Answer execute(VmwareHostService hostService, CreatePrivateTemplateFromVolumeCommand cmd);
3633
Answer execute(VmwareHostService hostService, CreatePrivateTemplateFromSnapshotCommand cmd);
3734
Answer execute(VmwareHostService hostService, CopyVolumeCommand cmd);
38-
Answer execute(VmwareHostService hostService, CreateVolumeOVACommand cmd);
39-
Answer execute(VmwareHostService hostService, PrepareOVAPackingCommand cmd);
4035
Answer execute(VmwareHostService hostService, CreateVolumeFromSnapshotCommand cmd);
4136
Answer execute(VmwareHostService hostService, CreateVMSnapshotCommand cmd);
4237
Answer execute(VmwareHostService hostService, DeleteVMSnapshotCommand cmd);
4338
Answer execute(VmwareHostService hostService, RevertToVMSnapshotCommand cmd);
39+
boolean execute(VmwareHostService hostService, CreateEntityDownloadURLCommand cmd);
4440
}

plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java

Lines changed: 99 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
import java.util.Map;
3030
import java.util.UUID;
3131

32+
import com.cloud.agent.api.storage.*;
33+
import com.cloud.agent.api.to.*;
34+
import org.apache.cloudstack.storage.to.TemplateObjectTO;
35+
import org.apache.cloudstack.storage.to.VolumeObjectTO;
3236
import org.apache.log4j.Logger;
3337

3438
import com.cloud.agent.api.Answer;
@@ -44,17 +48,6 @@
4448
import com.cloud.agent.api.DeleteVMSnapshotCommand;
4549
import com.cloud.agent.api.RevertToVMSnapshotAnswer;
4650
import com.cloud.agent.api.RevertToVMSnapshotCommand;
47-
import com.cloud.agent.api.storage.CopyVolumeAnswer;
48-
import com.cloud.agent.api.storage.CopyVolumeCommand;
49-
import com.cloud.agent.api.storage.PrepareOVAPackingAnswer;
50-
import com.cloud.agent.api.storage.PrepareOVAPackingCommand;
51-
import com.cloud.agent.api.storage.CreateVolumeOVAAnswer;
52-
import com.cloud.agent.api.storage.CreateVolumeOVACommand;
53-
import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
54-
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
55-
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
56-
import com.cloud.agent.api.to.StorageFilerTO;
57-
import com.cloud.agent.api.to.VolumeTO;
5851
import com.cloud.hypervisor.vmware.mo.CustomFieldConstants;
5952
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
6053
import com.cloud.hypervisor.vmware.mo.DatastoreMO;
@@ -89,6 +82,25 @@
8982
import com.vmware.vim25.VirtualSCSISharing;
9083

9184
public class VmwareStorageManagerImpl implements VmwareStorageManager {
85+
@Override
86+
public boolean execute(VmwareHostService hostService, CreateEntityDownloadURLCommand cmd) {
87+
DataTO data = cmd.getData();
88+
if (data == null) {
89+
return false;
90+
}
91+
92+
String newPath = null;
93+
if (data.getObjectType() == DataObjectType.VOLUME) {
94+
newPath = createOvaForVolume((VolumeObjectTO)data);
95+
} else if (data.getObjectType() == DataObjectType.TEMPLATE) {
96+
newPath = createOvaForTemplate((TemplateObjectTO)data);
97+
}
98+
if (newPath != null) {
99+
cmd.setInstallPath(newPath);
100+
}
101+
return true;
102+
}
103+
92104
private static final Logger s_logger = Logger.getLogger(VmwareStorageManagerImpl.class);
93105

94106
private final VmwareStorageMount _mountService;
@@ -108,108 +120,89 @@ public void configure(Map<String, Object> params) {
108120
_timeout = NumbersUtil.parseInt(value, 1440) * 1000;
109121
}
110122

111-
//Fang note: use Answer here instead of the PrepareOVAPackingAnswer
112-
@Override
113-
public Answer execute(VmwareHostService hostService, PrepareOVAPackingCommand cmd) {
114-
String secStorageUrl = ((PrepareOVAPackingCommand) cmd).getSecondaryStorageUrl();
115-
assert (secStorageUrl != null);
116-
String installPath = cmd.getTemplatePath();
117-
String details = null;
118-
boolean success = false;
119-
String ovafileName = "";
120-
s_logger.info("Fang: execute OVAPacking cmd at vmwareMngImpl. ");
121-
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
122-
// String installPath = getTemplateRelativeDirInSecStorage(accountId, templateId);
123-
String installFullPath = secondaryMountPoint + "/" + installPath;
124-
125-
String templateName = installFullPath; // should be a file ending .ova;
126-
s_logger.info("Fang: execute vmwareMgrImpl: templateNAme " + templateName);
127-
// Fang: Dir list, if there is ova file, done; Fang: add answer cmd;
128-
// if not, from ova.meta, create a new OVA file;
129-
// change the install path to *.ova , not ova.meta;
130-
// VmwareContext context = hostService.getServiceContext(cmd); //Fang: we may not have the CTX here
131-
try {
132-
if (templateName.endsWith(".ova")) {
133-
if(new File(templateName).exists()) {
134-
details = "OVA files exists. succeed. ";
135-
return new Answer(cmd, true, details);
136-
} else {
137-
if (new File(templateName + ".meta").exists()) { //Fang parse the meta file
138-
//execute the tar command;
139-
s_logger.info("Fang: execute vmwareMgrImpl: getfromMeta " + templateName);
140-
ovafileName = getOVAFromMetafile(templateName + ".meta");
141-
details = "OVA file in meta file is " + ovafileName;
142-
return new Answer(cmd, true, details);
143-
} else {
144-
String msg = "Unable to find ova meta or ova file to prepare template (vmware)";
145-
s_logger.error(msg);
146-
throw new Exception(msg);
147-
}
148-
}
149-
}
150-
} catch (Throwable e) {
151-
if (e instanceof RemoteException) {
152-
//hostService.invalidateServiceContext(context); do not need context
153-
s_logger.error("Unable to connect to remote service ");
154-
details = "Unable to connect to remote service ";
155-
return new Answer(cmd, false, details);
156-
}
157-
String msg = "Unable to execute PrepareOVAPackingCommand due to exception";
158-
s_logger.error(msg, e);
159-
return new Answer(cmd, false, details);
123+
public String createOvaForTemplate(TemplateObjectTO template) {
124+
DataStoreTO storeTO = template.getDataStore();
125+
if (!(storeTO instanceof NfsTO)) {
126+
s_logger.debug("can only handle nfs storage, when create ova from volume");
127+
return null;
128+
}
129+
NfsTO nfsStore = (NfsTO)storeTO;
130+
String secStorageUrl = nfsStore.getUrl();
131+
assert (secStorageUrl != null);
132+
String installPath = template.getPath();
133+
String ovafileName = "";
134+
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
135+
String installFullPath = secondaryMountPoint + "/" + installPath;
136+
137+
String templateName = installFullPath; // should be a file ending .ova;
138+
try {
139+
if (templateName.endsWith(".ova")) {
140+
if(new File(templateName).exists()) {
141+
s_logger.debug("OVA files exists. succeed. ");
142+
return templateName;
143+
} else {
144+
if (new File(templateName + ".meta").exists()) {
145+
ovafileName = getOVAFromMetafile(templateName + ".meta");
146+
s_logger.debug("OVA file in meta file is " + ovafileName);
147+
return installPath;
148+
} else {
149+
String msg = "Unable to find ova meta or ova file to prepare template (vmware)";
150+
s_logger.error(msg);
151+
throw new Exception(msg);
152+
}
153+
}
160154
}
161-
return new Answer(cmd, true, details);
155+
} catch (Throwable e) {
156+
s_logger.debug("Failed to create ova: " + e.toString());
157+
}
158+
return null;
162159
}
163160

164161
//Fang: new command added;
165162
// Important! we need to sync file system before we can safely use tar to work around a linux kernal bug(or feature)
166-
@Override
167-
public Answer execute(VmwareHostService hostService, CreateVolumeOVACommand cmd) {
168-
String secStorageUrl = ((CreateVolumeOVACommand) cmd).getSecondaryStorageUrl();
169-
assert (secStorageUrl != null);
170-
String installPath = cmd.getVolPath();
163+
public String createOvaForVolume(VolumeObjectTO volume) {
164+
DataStoreTO storeTO = volume.getDataStore();
165+
if (!(storeTO instanceof NfsTO)) {
166+
s_logger.debug("can only handle nfs storage, when create ova from volume");
167+
return null;
168+
}
169+
NfsTO nfsStore = (NfsTO)storeTO;
170+
String secStorageUrl = nfsStore.getUrl();
171+
assert (secStorageUrl != null);
172+
//Note the volume path is volumes/accountId/volumeId/uuid/, the actual volume is uuid/uuid.vmdk
173+
String installPath = volume.getPath();
174+
int index = installPath.lastIndexOf(File.separator);
175+
String volumeUuid = installPath.substring(index + 1);
171176
String details = null;
172-
boolean success = false;
177+
boolean success = false;
173178

174-
s_logger.info("volss: execute CreateVolumeOVA cmd at vmwareMngImpl. ");
175-
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
176-
// String installPath = getTemplateRelativeDirInSecStorage(accountId, templateId);
177-
s_logger.info("volss: mountPoint: " + secondaryMountPoint + "installPath:" + installPath);
178-
String installFullPath = secondaryMountPoint + "/" + installPath;
179-
180-
String volName = cmd.getVolName(); // should be a UUID, without ova ovf, etc;
181-
s_logger.info("volss: execute vmwareMgrImpl: VolName " + volName);
182-
// Fang: Dir list, if there is ova file, done; Note: add answer cmd;
183-
184-
try {
185-
if(new File(volName + ".ova").exists()) {
186-
details = "OVA files exists. succeed. ";
187-
return new CreateVolumeOVAAnswer(cmd, true, details);
188-
} else {
189-
File ovaFile = new File(installFullPath);
190-
String exportDir = ovaFile.getParent();
191-
192-
s_logger.info("Fang: exportDir is (for VolumeOVA): " + exportDir);
193-
s_logger.info("Sync file system before we package OVA...");
194-
195-
Script commandSync = new Script(true, "sync", 0, s_logger);
196-
commandSync.execute();
197-
198-
Script command = new Script(false, "tar", 0, s_logger);
199-
command.setWorkDir(exportDir);
200-
command.add("-cf", volName + ".ova");
201-
command.add(volName + ".ovf"); // OVF file should be the first file in OVA archive
202-
command.add(volName + "-disk0.vmdk");
203-
204-
s_logger.info("Package Volume OVA with commmand: " + command.toString());
205-
command.execute();
206-
return new CreateVolumeOVAAnswer(cmd, true, details);
207-
}
208-
} catch (Throwable e) {
209-
s_logger.info("Exception for createVolumeOVA");
210-
}
211-
return new CreateVolumeOVAAnswer(cmd, true, "fail to pack OVA for volume");
212-
}
179+
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
180+
//The real volume path
181+
String volumePath = installPath + File.separator + volumeUuid + ".ova";
182+
String installFullPath = secondaryMountPoint + "/" + installPath;
183+
184+
try {
185+
if(new File(secondaryMountPoint + File.separator + volumePath).exists()) {
186+
s_logger.debug("ova already exists:" + volumePath);
187+
return volumePath;
188+
} else {
189+
Script commandSync = new Script(true, "sync", 0, s_logger);
190+
commandSync.execute();
191+
192+
Script command = new Script(false, "tar", 0, s_logger);
193+
command.setWorkDir(installFullPath);
194+
command.add("-cf", volumeUuid + ".ova");
195+
command.add(volumeUuid + ".ovf"); // OVF file should be the first file in OVA archive
196+
command.add(volumeUuid + "-disk0.vmdk");
197+
198+
command.execute();
199+
return volumePath;
200+
}
201+
} catch (Throwable e) {
202+
s_logger.info("Exception for createVolumeOVA");
203+
}
204+
return null;
205+
}
213206

214207
@Override
215208
public Answer execute(VmwareHostService hostService, PrimaryStorageDownloadCommand cmd) {

0 commit comments

Comments
 (0)