mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-02 11:52:28 +01:00
CLOUDSTACK-3869: Move VMware datastore folder structure policy management to central place
This commit is contained in:
parent
458de9321d
commit
40869a5a2b
@ -1530,35 +1530,6 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private VirtualMachineMO createWorkingVM(DatastoreMO dsMo, VmwareHypervisorHost hyperHost) throws Exception {
|
||||
String uniqueName = UUID.randomUUID().toString();
|
||||
VirtualMachineMO workingVM = null;
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
vmConfig.setName(uniqueName);
|
||||
vmConfig.setMemoryMB((long) 4);
|
||||
vmConfig.setNumCPUs(1);
|
||||
vmConfig.setGuestId(VirtualMachineGuestOsIdentifier.OTHER_GUEST.toString());
|
||||
VirtualMachineFileInfo fileInfo = new VirtualMachineFileInfo();
|
||||
fileInfo.setVmPathName(String.format("[%s]", dsMo.getName()));
|
||||
vmConfig.setFiles(fileInfo);
|
||||
|
||||
VirtualLsiLogicController scsiController = new VirtualLsiLogicController();
|
||||
scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
scsiController.setBusNumber(0);
|
||||
scsiController.setKey(1);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
|
||||
vmConfig.getDeviceChange().add(scsiControllerSpec);
|
||||
hyperHost.createVm(vmConfig);
|
||||
workingVM = hyperHost.findVmOnHyperHost(uniqueName);
|
||||
return workingVM;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String deleteVolumeDirOnSecondaryStorage(long volumeId, String secStorageUrl) throws Exception {
|
||||
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
|
||||
String volumeMountRoot = secondaryMountPoint + "/" + getVolumeRelativeDirInSecStroage(volumeId);
|
||||
|
||||
@ -310,6 +310,7 @@ import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.resource.StoragePoolResource;
|
||||
import com.cloud.storage.resource.StorageSubsystemCommandHandler;
|
||||
import com.cloud.storage.resource.VmwareStorageLayoutHelper;
|
||||
import com.cloud.storage.resource.VmwareStorageProcessor;
|
||||
import com.cloud.storage.resource.VmwareStorageSubsystemCommandHandler;
|
||||
import com.cloud.storage.template.TemplateProp;
|
||||
@ -5364,7 +5365,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName);
|
||||
synchronized (this) {
|
||||
s_logger.info("Delete file if exists in datastore to clear the way for creating the volume. file: " + volumeDatastorePath);
|
||||
VmwareHelper.deleteVolumeVmdkFiles(dsMo, vmdkName, dcMo);
|
||||
VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, vmdkName, dcMo);
|
||||
vmMo.createDisk(volumeDatastorePath, getMBsFromBytes(dskch.getSize()), morDatastore, -1);
|
||||
vmMo.detachDisk(volumeDatastorePath, false);
|
||||
}
|
||||
@ -5422,7 +5423,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
|
||||
synchronized (this) {
|
||||
// s_logger.info("Delete file if exists in datastore to clear the way for creating the volume. file: " + volumeDatastorePath);
|
||||
VmwareHelper.deleteVolumeVmdkFiles(dsMo, volumeUuid.toString(), dcMo);
|
||||
VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, volumeUuid.toString(), dcMo);
|
||||
|
||||
vmMo.createDisk(volumeDatastorePath, getMBsFromBytes(dskch.getSize()), morDatastore, vmMo.getScsiDeviceControllerKey());
|
||||
vmMo.detachDisk(volumeDatastorePath, false);
|
||||
|
||||
@ -0,0 +1,126 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package com.cloud.storage.resource;
|
||||
|
||||
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
|
||||
import com.cloud.hypervisor.vmware.mo.DatastoreMO;
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
/**
|
||||
*
|
||||
* To provide helper methods to handle storage layout in one place
|
||||
*
|
||||
*/
|
||||
public class VmwareStorageLayoutHelper {
|
||||
|
||||
public static String[] getVmdkFilePairDatastorePath(DatastoreMO dsMo, String vmName, String vmdkName,
|
||||
VmwareStorageLayoutType layoutType, boolean linkedVmdk) throws Exception {
|
||||
|
||||
String[] filePair = new String[2];
|
||||
switch(layoutType) {
|
||||
case VMWARE :
|
||||
assert(vmName != null && !vmName.isEmpty());
|
||||
filePair[0] = String.format("[%s] %s/%s.vmdk", dsMo.getName(), vmName, vmdkName);
|
||||
|
||||
if(linkedVmdk)
|
||||
filePair[1] = String.format("[%s] %s/%s-delta.vmdk", dsMo.getName(), vmName, vmdkName);
|
||||
else
|
||||
filePair[1] = String.format("[%s] %s/%s-flat.vmdk", dsMo.getName(), vmName, vmdkName);
|
||||
return filePair;
|
||||
|
||||
case CLOUDSTACK_LEGACY :
|
||||
filePair[0] = String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName);
|
||||
|
||||
if(linkedVmdk)
|
||||
filePair[1] = String.format("[%s] %s-delta.vmdk", dsMo.getName(), vmdkName);
|
||||
else
|
||||
filePair[1] = String.format("[%s] %s-flat.vmdk", dsMo.getName(), vmdkName);
|
||||
return filePair;
|
||||
|
||||
default :
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getTemplateOnSecStorageFilePath(String secStorageMountPoint, String templateRelativeFolderPath,
|
||||
String templateName, String fileExtension) {
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(secStorageMountPoint);
|
||||
if(!secStorageMountPoint.endsWith("/"))
|
||||
sb.append("/");
|
||||
|
||||
sb.append(templateRelativeFolderPath);
|
||||
if(!secStorageMountPoint.endsWith("/"))
|
||||
sb.append("/");
|
||||
|
||||
sb.append(templateName);
|
||||
if(!fileExtension.startsWith("."))
|
||||
sb.append(".");
|
||||
sb.append(fileExtension);
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* return Pair of <Template relative path, Template name>
|
||||
* Template url may or may not end with .ova extension
|
||||
*/
|
||||
public static Pair<String, String> decodeTemplateRelativePathAndNameFromUrl(String storeUrl, String templateUrl,
|
||||
String defaultName) {
|
||||
|
||||
String templateName = null;
|
||||
String mountPoint = null;
|
||||
if (templateUrl.endsWith(".ova")) {
|
||||
int index = templateUrl.lastIndexOf("/");
|
||||
mountPoint = templateUrl.substring(0, index);
|
||||
mountPoint = mountPoint.substring(storeUrl.length() + 1);
|
||||
if (!mountPoint.endsWith("/")) {
|
||||
mountPoint = mountPoint + "/";
|
||||
}
|
||||
|
||||
templateName = templateUrl.substring(index + 1).replace(".ova", "");
|
||||
|
||||
if (templateName == null || templateName.isEmpty()) {
|
||||
templateName = defaultName;
|
||||
}
|
||||
} else {
|
||||
mountPoint = templateUrl.substring(storeUrl.length() + 1);
|
||||
if (!mountPoint.endsWith("/")) {
|
||||
mountPoint = mountPoint + "/";
|
||||
}
|
||||
templateName = defaultName;
|
||||
}
|
||||
|
||||
return new Pair<String, String>(mountPoint, templateName);
|
||||
}
|
||||
|
||||
public static void deleteVolumeVmdkFiles(DatastoreMO dsMo, String volumeName, DatacenterMO dcMo) throws Exception {
|
||||
String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeName);
|
||||
dsMo.deleteFile(volumeDatastorePath, dcMo.getMor(), true);
|
||||
|
||||
volumeDatastorePath = String.format("[%s] %s-flat.vmdk", dsMo.getName(), volumeName);
|
||||
dsMo.deleteFile(volumeDatastorePath, dcMo.getMor(), true);
|
||||
|
||||
volumeDatastorePath = String.format("[%s] %s-delta.vmdk", dsMo.getName(), volumeName);
|
||||
dsMo.deleteFile(volumeDatastorePath, dcMo.getMor(), true);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package com.cloud.storage.resource;
|
||||
|
||||
public enum VmwareStorageLayoutType {
|
||||
VMWARE,
|
||||
CLOUDSTACK_LEGACY
|
||||
}
|
||||
@ -89,6 +89,7 @@ import com.cloud.vm.VirtualMachine.State;
|
||||
|
||||
public class VmwareStorageProcessor implements StorageProcessor {
|
||||
private static final Logger s_logger = Logger.getLogger(VmwareStorageProcessor.class);
|
||||
|
||||
private VmwareHostService hostService;
|
||||
private boolean _fullCloneFlag;
|
||||
private VmwareStorageMount mountService;
|
||||
@ -97,8 +98,6 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
protected Integer _shutdown_waitMs;
|
||||
private final Gson _gson;
|
||||
private final StorageLayer _storage = new JavaStorageLayer();
|
||||
private final PremiumSecondaryStorageResource storageResource;
|
||||
|
||||
public VmwareStorageProcessor(VmwareHostService hostService, boolean fullCloneFlag, VmwareStorageMount mountService,
|
||||
Integer timeout,
|
||||
VmwareResource resource,
|
||||
@ -111,7 +110,6 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
this.resource = resource;
|
||||
this._shutdown_waitMs = shutdownWaitMs;
|
||||
_gson = GsonHelper.getGsonLogger();
|
||||
this.storageResource = storageResource;
|
||||
}
|
||||
|
||||
private String getOVFFilePath(String srcOVAFileName) {
|
||||
@ -128,8 +126,9 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void copyTemplateFromSecondaryToPrimary(VmwareHypervisorHost hyperHost, DatastoreMO datastoreMo, String secondaryStorageUrl,
|
||||
String templatePathAtSecondaryStorage, String templateName, String templateUuid) throws Exception {
|
||||
String templatePathAtSecondaryStorage, String templateName, String templateUuid) throws Exception {
|
||||
|
||||
s_logger.info("Executing copyTemplateFromSecondaryToPrimary. secondaryStorage: "
|
||||
+ secondaryStorageUrl + ", templatePathAtSecondaryStorage: " + templatePathAtSecondaryStorage
|
||||
@ -138,9 +137,10 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
String secondaryMountPoint = mountService.getMountPoint(secondaryStorageUrl);
|
||||
s_logger.info("Secondary storage mount point: " + secondaryMountPoint);
|
||||
|
||||
String srcOVAFileName = secondaryMountPoint + "/" + templatePathAtSecondaryStorage +
|
||||
templateName + "." + ImageFormat.OVA.getFileExtension();
|
||||
|
||||
String srcOVAFileName = VmwareStorageLayoutHelper.getTemplateOnSecStorageFilePath(
|
||||
secondaryMountPoint, templatePathAtSecondaryStorage,
|
||||
templateName, ImageFormat.OVA.getFileExtension());
|
||||
|
||||
String srcFileName = getOVFFilePath(srcOVAFileName);
|
||||
if(srcFileName == null) {
|
||||
Script command = new Script("tar", 0, s_logger);
|
||||
@ -193,7 +193,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
DataStoreTO srcStore = srcData.getDataStore();
|
||||
if (!(srcStore instanceof NfsTO)) {
|
||||
return new CopyCmdAnswer("unsupported protocol");
|
||||
}
|
||||
}
|
||||
NfsTO nfsImageStore = (NfsTO)srcStore;
|
||||
DataTO destData = cmd.getDestTO();
|
||||
DataStoreTO destStore = destData.getDataStore();
|
||||
@ -201,55 +201,32 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
String secondaryStorageUrl = nfsImageStore.getUrl();
|
||||
assert (secondaryStorageUrl != null);
|
||||
|
||||
String templateUrl = secondaryStorageUrl + File.separator + srcData.getPath();
|
||||
|
||||
String templateName = null;
|
||||
String mountPoint = null;
|
||||
if (templateUrl.endsWith(".ova")) {
|
||||
int index = templateUrl.lastIndexOf("/");
|
||||
mountPoint = templateUrl.substring(0, index);
|
||||
mountPoint = mountPoint.substring(secondaryStorageUrl.length() + 1);
|
||||
if (!mountPoint.endsWith("/")) {
|
||||
mountPoint = mountPoint + "/";
|
||||
}
|
||||
|
||||
templateName = templateUrl.substring(index + 1).replace("." + ImageFormat.OVA.getFileExtension(), "");
|
||||
|
||||
if (templateName == null || templateName.isEmpty()) {
|
||||
templateName = template.getName();
|
||||
}
|
||||
} else {
|
||||
mountPoint = templateUrl.substring(secondaryStorageUrl.length() + 1);
|
||||
if (!mountPoint.endsWith("/")) {
|
||||
mountPoint = mountPoint + "/";
|
||||
}
|
||||
templateName = template.getName();
|
||||
}
|
||||
String templateUrl = secondaryStorageUrl + "/" + srcData.getPath();
|
||||
|
||||
Pair<String, String> templateInfo = VmwareStorageLayoutHelper.decodeTemplateRelativePathAndNameFromUrl(
|
||||
secondaryStorageUrl, templateUrl, template.getName());
|
||||
|
||||
VmwareContext context = hostService.getServiceContext(cmd);
|
||||
try {
|
||||
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
|
||||
|
||||
String templateUuidName = UUID.nameUUIDFromBytes((templateName + "@" + primaryStore.getUuid() + "-" + hyperHost.getMor().getValue()).getBytes()).toString();
|
||||
// truncate template name to 32 chars to ensure they work well with vSphere API's.
|
||||
templateUuidName = templateUuidName.replace("-", "");
|
||||
String templateUuidName = deriveTemplateUuidOnHost(hyperHost, primaryStore.getUuid(), templateInfo.second());
|
||||
|
||||
DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
|
||||
VirtualMachineMO templateMo = VmwareHelper.pickOneVmOnRunningHost(dcMo.findVmByNameAndLabel(templateUuidName), true);
|
||||
|
||||
if (templateMo == null) {
|
||||
if(s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Template " + templateName + " is not setup yet, setup template from secondary storage with uuid name: " + templateUuidName);
|
||||
}
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("Template " + templateInfo.second() + " is not setup yet, setup template from secondary storage with uuid name: " + templateUuidName);
|
||||
ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid());
|
||||
assert (morDs != null);
|
||||
DatastoreMO primaryStorageDatastoreMo = new DatastoreMO(context, morDs);
|
||||
|
||||
copyTemplateFromSecondaryToPrimary(hyperHost,
|
||||
primaryStorageDatastoreMo, secondaryStorageUrl,
|
||||
mountPoint, templateName, templateUuidName);
|
||||
templateInfo.first(), templateInfo.second(), templateUuidName);
|
||||
} else {
|
||||
s_logger.info("Template " + templateName + " has already been setup, skip the template setup process in primary storage");
|
||||
s_logger.info("Template " + templateInfo.second() + " has already been setup, skip the template setup process in primary storage");
|
||||
}
|
||||
|
||||
TemplateObjectTO newTemplate = new TemplateObjectTO();
|
||||
@ -265,6 +242,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
return new CopyCmdAnswer(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean createVMLinkedClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo,
|
||||
String vmdkName, ManagedObjectReference morDatastore, ManagedObjectReference morPool) throws Exception {
|
||||
|
||||
@ -275,10 +253,6 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
if(dsMo.folderExists(String.format("[%s]", dsMo.getName()), vmdkName)) {
|
||||
dsMo.deleteFile(String.format("[%s] %s/", dsMo.getName(), vmdkName), dcMo.getMor(), false);
|
||||
}
|
||||
|
||||
s_logger.info("creating linked clone from template");
|
||||
if (!vmTemplate.createLinkedClone(vmdkName, morBaseSnapshot, dcMo.getVmFolder(), morPool, morDatastore)) {
|
||||
String msg = "Unable to clone from the template";
|
||||
@ -286,16 +260,21 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
// we can't rely on un-offical API (VirtualMachineMO.moveAllVmDiskFiles() any more, use hard-coded disk names that we know
|
||||
// to move files
|
||||
s_logger.info("Move volume out of volume-wrapper VM ");
|
||||
dsMo.moveDatastoreFile(String.format("[%s] %s/%s.vmdk", dsMo.getName(), vmdkName, vmdkName),
|
||||
String[] vmwareLayoutFilePair = VmwareStorageLayoutHelper.getVmdkFilePairDatastorePath(dsMo,
|
||||
vmdkName, vmdkName, VmwareStorageLayoutType.VMWARE, true);
|
||||
String[] legacyCloudStackLayoutFilePair = VmwareStorageLayoutHelper.getVmdkFilePairDatastorePath(dsMo,
|
||||
vmdkName, vmdkName, VmwareStorageLayoutType.CLOUDSTACK_LEGACY, true);
|
||||
|
||||
dsMo.moveDatastoreFile(vmwareLayoutFilePair[0],
|
||||
dcMo.getMor(), dsMo.getMor(),
|
||||
String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
|
||||
|
||||
dsMo.moveDatastoreFile(String.format("[%s] %s/%s-delta.vmdk", dsMo.getName(), vmdkName, vmdkName),
|
||||
legacyCloudStackLayoutFilePair[0],
|
||||
dcMo.getMor(), true);
|
||||
|
||||
dsMo.moveDatastoreFile(vmwareLayoutFilePair[1],
|
||||
dcMo.getMor(), dsMo.getMor(),
|
||||
String.format("[%s] %s-delta.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
|
||||
legacyCloudStackLayoutFilePair[1],
|
||||
dcMo.getMor(), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -303,28 +282,28 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
private boolean createVMFullClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo,
|
||||
String vmdkName, ManagedObjectReference morDatastore, ManagedObjectReference morPool) throws Exception {
|
||||
|
||||
if(dsMo.folderExists(String.format("[%s]", dsMo.getName()), vmdkName)) {
|
||||
dsMo.deleteFile(String.format("[%s] %s/", dsMo.getName(), vmdkName), dcMo.getMor(), false);
|
||||
}
|
||||
|
||||
s_logger.info("creating full clone from template");
|
||||
if (!vmTemplate.createFullClone(vmdkName, dcMo.getVmFolder(), morPool, morDatastore)) {
|
||||
String msg = "Unable to create full clone from the template";
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
// we can't rely on un-offical API (VirtualMachineMO.moveAllVmDiskFiles() any more, use hard-coded disk names that we know
|
||||
// to move files
|
||||
|
||||
s_logger.info("Move volume out of volume-wrapper VM ");
|
||||
dsMo.moveDatastoreFile(String.format("[%s] %s/%s.vmdk", dsMo.getName(), vmdkName, vmdkName),
|
||||
String[] vmwareLayoutFilePair = VmwareStorageLayoutHelper.getVmdkFilePairDatastorePath(dsMo,
|
||||
vmdkName, vmdkName, VmwareStorageLayoutType.VMWARE, false);
|
||||
String[] legacyCloudStackLayoutFilePair = VmwareStorageLayoutHelper.getVmdkFilePairDatastorePath(dsMo,
|
||||
vmdkName, vmdkName, VmwareStorageLayoutType.CLOUDSTACK_LEGACY, false);
|
||||
|
||||
dsMo.moveDatastoreFile(vmwareLayoutFilePair[0],
|
||||
dcMo.getMor(), dsMo.getMor(),
|
||||
String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
|
||||
|
||||
dsMo.moveDatastoreFile(String.format("[%s] %s/%s-flat.vmdk", dsMo.getName(), vmdkName, vmdkName),
|
||||
legacyCloudStackLayoutFilePair[0],
|
||||
dcMo.getMor(), true);
|
||||
|
||||
dsMo.moveDatastoreFile(vmwareLayoutFilePair[1],
|
||||
dcMo.getMor(), dsMo.getMor(),
|
||||
String.format("[%s] %s-flat.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
|
||||
|
||||
legacyCloudStackLayoutFilePair[1],
|
||||
dcMo.getMor(), true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -337,7 +316,6 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
|
||||
PrimaryDataStoreTO srcStore = (PrimaryDataStoreTO)template.getDataStore();
|
||||
|
||||
|
||||
try {
|
||||
VmwareContext context = this.hostService.getServiceContext(null);
|
||||
VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(context, null);
|
||||
@ -350,26 +328,28 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
|
||||
DatastoreMO dsMo = new DatastoreMO(context, morDatastore);
|
||||
|
||||
|
||||
// attach volume id to make the name unique
|
||||
String vmdkName = volume.getName() + "-" + volume.getId();
|
||||
String vmdkName = volume.getName();
|
||||
if (srcStore == null) {
|
||||
// create a root volume for blank VM
|
||||
// create a root volume for blank VM (created from ISO)
|
||||
String dummyVmName = this.hostService.getWorkerName(context, cmd, 0);
|
||||
|
||||
try {
|
||||
vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName);
|
||||
vmMo = HypervisorHostHelper.createWorkerVM(hyperHost, dsMo, dummyVmName);
|
||||
if (vmMo == null) {
|
||||
throw new Exception("Unable to create a dummy VM for volume creation");
|
||||
}
|
||||
|
||||
String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName);
|
||||
String vmdkFilePair[] = VmwareStorageLayoutHelper.getVmdkFilePairDatastorePath(dsMo, null, vmdkName,
|
||||
VmwareStorageLayoutType.CLOUDSTACK_LEGACY,
|
||||
true // we only use the first file in the pair, linked or not will not matter
|
||||
);
|
||||
String volumeDatastorePath = vmdkFilePair[0];
|
||||
synchronized (this) {
|
||||
s_logger.info("Delete file if exists in datastore to clear the way for creating the volume. file: " + volumeDatastorePath);
|
||||
VmwareHelper.deleteVolumeVmdkFiles(dsMo, vmdkName, dcMo);
|
||||
VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, vmdkName, dcMo);
|
||||
vmMo.createDisk(volumeDatastorePath, (int) (volume.getSize() / (1024L * 1024L)), morDatastore, -1);
|
||||
vmMo.detachDisk(volumeDatastorePath, false);
|
||||
}
|
||||
}
|
||||
|
||||
VolumeObjectTO newVol = new VolumeObjectTO();
|
||||
newVol.setPath(vmdkName);
|
||||
@ -391,7 +371,6 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
|
||||
ManagedObjectReference morPool = hyperHost.getHyperHostOwnerResourcePool();
|
||||
ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
|
||||
//createVMLinkedClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
|
||||
if (!_fullCloneFlag) {
|
||||
createVMLinkedClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
|
||||
} else {
|
||||
@ -407,7 +386,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
s_logger.info("destroy volume-wrapper VM " + vmdkName);
|
||||
vmMo.destroy();
|
||||
|
||||
String srcFile = String.format("[%s] %s/", dsMo.getName(), vmdkName);
|
||||
String srcFile = dsMo.getDatastorePath(vmdkName, true);
|
||||
dsMo.deleteFile(srcFile, dcMo.getMor(), true);
|
||||
VolumeObjectTO newVol = new VolumeObjectTO();
|
||||
newVol.setPath(vmdkName);
|
||||
@ -441,7 +420,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
volumeName = srcVolumePath.substring(index + 1);
|
||||
}
|
||||
|
||||
String newVolume = UUID.randomUUID().toString().replaceAll("-", "");
|
||||
String newVolume = VmwareHelper.getVCenterSafeUuid();
|
||||
restoreVolumeFromSecStorage(hyperHost, dsMo, newVolume, secStorageUrl, volumeFolder, volumeName);
|
||||
|
||||
return new Pair<String, String>(volumeFolder, newVolume);
|
||||
@ -519,11 +498,11 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
String secStorageUrl, String workerVmName) throws Exception {
|
||||
VirtualMachineMO workerVm=null;
|
||||
VirtualMachineMO vmMo=null;
|
||||
String exportName = UUID.randomUUID().toString();
|
||||
String exportName = UUID.randomUUID().toString().replace("-", "");
|
||||
|
||||
try {
|
||||
ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, poolId);
|
||||
|
||||
|
||||
if (morDs == null) {
|
||||
String msg = "Unable to find volumes's storage pool for copy volume operation";
|
||||
s_logger.error(msg);
|
||||
@ -534,35 +513,15 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
if (vmMo == null) {
|
||||
// create a dummy worker vm for attaching the volume
|
||||
DatastoreMO dsMo = new DatastoreMO(hyperHost.getContext(), morDs);
|
||||
//restrict VM name to 32 chars, (else snapshot descriptor file name will be truncated to 32 chars of vm name)
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
vmConfig.setName(workerVmName);
|
||||
vmConfig.setMemoryMB((long) 4);
|
||||
vmConfig.setNumCPUs(1);
|
||||
vmConfig.setGuestId(VirtualMachineGuestOsIdentifier.OTHER_GUEST.value());
|
||||
VirtualMachineFileInfo fileInfo = new VirtualMachineFileInfo();
|
||||
fileInfo.setVmPathName(String.format("[%s]", dsMo.getName()));
|
||||
vmConfig.setFiles(fileInfo);
|
||||
|
||||
// Scsi controller
|
||||
VirtualLsiLogicController scsiController = new VirtualLsiLogicController();
|
||||
scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
scsiController.setBusNumber(0);
|
||||
scsiController.setKey(1);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
vmConfig.getDeviceChange().add(scsiControllerSpec);
|
||||
|
||||
hyperHost.createVm(vmConfig);
|
||||
workerVm = hyperHost.findVmOnHyperHost(workerVmName);
|
||||
workerVm = HypervisorHostHelper.createWorkerVM(hyperHost, dsMo, workerVmName);
|
||||
|
||||
if (workerVm == null) {
|
||||
String msg = "Unable to create worker VM to execute CopyVolumeCommand";
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
//attach volume to worker VM
|
||||
// attach volume to worker VM
|
||||
String datastoreVolumePath = getVolumePathInDatastore(dsMo, volumePath + ".vmdk");
|
||||
workerVm.attachDisk(new String[] { datastoreVolumePath }, morDs);
|
||||
vmMo = workerVm;
|
||||
@ -940,9 +899,8 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
postCreatePrivateTemplate(installFullPath, templateId, templateUniqueName, physicalSize, virtualSize);
|
||||
writeMetaOvaForTemplate(installFullPath, backupSSUuid + ".ovf", templateVMDKName, templateUniqueName, physicalSize);
|
||||
return new Ternary<String, Long, Long>(installPath + "/" + templateUniqueName + ".ova", physicalSize, virtualSize);
|
||||
} catch(Exception e) {
|
||||
} finally {
|
||||
// TODO, clean up left over files
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1043,6 +1001,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
installPath, backupUuid, workerVmName);
|
||||
return backupUuid + "/" + backupUuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer backupSnapshot(CopyCommand cmd) {
|
||||
SnapshotObjectTO srcSnapshot = (SnapshotObjectTO)cmd.getSrcTO();
|
||||
@ -1055,7 +1014,6 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
|
||||
NfsTO destNfsStore = (NfsTO)destStore;
|
||||
|
||||
|
||||
String secondaryStorageUrl = destNfsStore.getUrl();
|
||||
String snapshotUuid = srcSnapshot.getPath();
|
||||
String prevSnapshotUuid = srcSnapshot.getParentSnapshotPath();
|
||||
@ -1090,21 +1048,15 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
dsMo = new DatastoreMO(hyperHost.getContext(), morDs);
|
||||
|
||||
workerVMName = hostService.getWorkerName(context, cmd, 0);
|
||||
|
||||
// attach a volume to dummay wrapper VM for taking snapshot and exporting the VM for backup
|
||||
if (!hyperHost.createBlankVm(workerVMName, 1, 512, 0, false, 4, 0, VirtualMachineGuestOsIdentifier.OTHER_GUEST.value(), morDs, false)) {
|
||||
String msg = "Unable to create worker VM to execute BackupSnapshotCommand";
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
vmMo = hyperHost.findVmOnHyperHost(workerVMName);
|
||||
|
||||
vmMo = HypervisorHostHelper.createWorkerVM(hyperHost, dsMo, workerVMName);
|
||||
if (vmMo == null) {
|
||||
throw new Exception("Failed to find the newly create or relocated VM. vmName: " + workerVMName);
|
||||
}
|
||||
workerVm = vmMo;
|
||||
|
||||
// attach volume to worker VM
|
||||
String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumePath);
|
||||
String datastoreVolumePath = dsMo.getDatastorePath(volumePath + ".vmdk");
|
||||
vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs);
|
||||
}
|
||||
}
|
||||
@ -1205,7 +1157,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
}
|
||||
|
||||
DatastoreMO dsMo = new DatastoreMO(this.hostService.getServiceContext(null), morDs);
|
||||
String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), isManaged ? dsMo.getName() : volumeTO.getPath());
|
||||
String datastoreVolumePath = dsMo.getDatastorePath((isManaged ? dsMo.getName() : volumeTO.getPath()) + ".vmdk");
|
||||
|
||||
disk.setVdiUuid(datastoreVolumePath);
|
||||
|
||||
@ -1251,9 +1203,8 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
|
||||
return morDatastore;
|
||||
}
|
||||
|
||||
private Answer attachIso(DiskTO disk, boolean isAttach, String vmName) {
|
||||
|
||||
|
||||
try {
|
||||
VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(this.hostService.getServiceContext(null), null);
|
||||
VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
|
||||
@ -1341,33 +1292,6 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
return this.attachVolume(cmd, cmd.getDisk(), false, cmd.isManaged(), cmd.getVmName(), cmd.get_iScsiName(), cmd.getStorageHost(), cmd.getStoragePort());
|
||||
}
|
||||
|
||||
protected VirtualMachineMO prepareVolumeHostDummyVm(VmwareHypervisorHost hyperHost, DatastoreMO dsMo, String vmName) throws Exception {
|
||||
assert (hyperHost != null);
|
||||
|
||||
VirtualMachineMO vmMo = null;
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
vmConfig.setName(vmName);
|
||||
vmConfig.setMemoryMB((long) 4); // vmware request minimum of 4 MB
|
||||
vmConfig.setNumCPUs(1);
|
||||
vmConfig.setGuestId(VirtualMachineGuestOsIdentifier.OTHER_GUEST.value());
|
||||
VirtualMachineFileInfo fileInfo = new VirtualMachineFileInfo();
|
||||
fileInfo.setVmPathName(String.format("[%s]", dsMo.getName()));
|
||||
vmConfig.setFiles(fileInfo);
|
||||
|
||||
// Scsi controller
|
||||
VirtualLsiLogicController scsiController = new VirtualLsiLogicController();
|
||||
scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
scsiController.setBusNumber(0);
|
||||
scsiController.setKey(1);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
|
||||
vmConfig.getDeviceChange().add(scsiControllerSpec );
|
||||
hyperHost.createVm(vmConfig);
|
||||
vmMo = hyperHost.findVmOnHyperHost(vmName);
|
||||
return vmMo;
|
||||
}
|
||||
@Override
|
||||
public Answer createVolume(CreateObjectCommand cmd) {
|
||||
|
||||
@ -1388,17 +1312,19 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
// create data volume
|
||||
VirtualMachineMO vmMo = null;
|
||||
String volumeUuid = UUID.randomUUID().toString().replace("-", "");
|
||||
String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeUuid);
|
||||
String volumeDatastorePath = dsMo.getDatastorePath(volumeUuid + ".vmdk");
|
||||
|
||||
String dummyVmName = this.hostService.getWorkerName(context, cmd, 0);
|
||||
try {
|
||||
vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName);
|
||||
s_logger.info("Create worker VM " + dummyVmName);
|
||||
vmMo = HypervisorHostHelper.createWorkerVM(hyperHost, dsMo, dummyVmName);
|
||||
if (vmMo == null) {
|
||||
throw new Exception("Unable to create a dummy VM for volume creation");
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
// s_logger.info("Delete file if exists in datastore to clear the way for creating the volume. file: " + volumeDatastorePath);
|
||||
VmwareHelper.deleteVolumeVmdkFiles(dsMo, volumeUuid.toString(), dcMo);
|
||||
VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, volumeUuid.toString(), dcMo);
|
||||
|
||||
vmMo.createDisk(volumeDatastorePath, (int) (volume.getSize() / (1024L * 1024L)), morDatastore, vmMo.getScsiDeviceControllerKey());
|
||||
vmMo.detachDisk(volumeDatastorePath, false);
|
||||
@ -1410,10 +1336,11 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
return new CreateObjectAnswer(newVol);
|
||||
} finally {
|
||||
s_logger.info("Destroy dummy VM after volume creation");
|
||||
vmMo.detachAllDisks();
|
||||
vmMo.destroy();
|
||||
if(vmMo != null) {
|
||||
vmMo.detachAllDisks();
|
||||
vmMo.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof RemoteException) {
|
||||
s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
|
||||
@ -1674,7 +1601,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
String backupPath = backedUpSnapshotUuid.substring(0, index);
|
||||
backedUpSnapshotUuid = backedUpSnapshotUuid.substring(index + 1);
|
||||
String details = null;
|
||||
String newVolumeName = UUID.randomUUID().toString().replaceAll("-", "");
|
||||
String newVolumeName = VmwareHelper.getVCenterSafeUuid();
|
||||
|
||||
VmwareContext context = hostService.getServiceContext(cmd);
|
||||
try {
|
||||
@ -1715,4 +1642,10 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
return new Answer(cmd, false, "unsupported command");
|
||||
}
|
||||
}
|
||||
|
||||
private static String deriveTemplateUuidOnHost(VmwareHypervisorHost hyperHost, String storeIdentifier, String templateName) {
|
||||
String templateUuid = UUID.nameUUIDFromBytes((templateName + "@" + storeIdentifier + "-" + hyperHost.getMor().getValue()).getBytes()).toString();
|
||||
templateUuid = templateUuid.replaceAll("-", "");
|
||||
return templateUuid;
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,6 +125,23 @@ public class DatastoreMO extends BaseMO {
|
||||
|
||||
_context.getService().makeDirectory(morFileManager, fullPath, morDc, true);
|
||||
}
|
||||
|
||||
public String getDatastoreRootPath() throws Exception {
|
||||
return String.format("[%s]", getName());
|
||||
}
|
||||
|
||||
public String getDatastorePath(String relativePathWithoutDatastoreName) throws Exception {
|
||||
return getDatastorePath(relativePathWithoutDatastoreName, false);
|
||||
}
|
||||
|
||||
public String getDatastorePath(String relativePathWithoutDatastoreName, boolean endWithPathDelimiter) throws Exception {
|
||||
String path = String.format("[%s] %s", getName(), relativePathWithoutDatastoreName);
|
||||
if(endWithPathDelimiter) {
|
||||
if(!path.endsWith("/"))
|
||||
return path + "/";
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
public boolean deleteFile(String path, ManagedObjectReference morDc, boolean testExistence) throws Exception {
|
||||
String datastoreName = getName();
|
||||
@ -299,18 +316,6 @@ public class DatastoreMO extends BaseMO {
|
||||
|
||||
s_logger.info("File " + fileFullPath + " does not exist on datastore");
|
||||
return false;
|
||||
|
||||
/*
|
||||
String[] fileNames = listDirContent(dirFile.getPath());
|
||||
|
||||
String fileName = file.getFileName();
|
||||
for(String name : fileNames) {
|
||||
if(name.equalsIgnoreCase(fileName))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
*/
|
||||
}
|
||||
|
||||
public boolean folderExists(String folderParentDatastorePath, String folderName) throws Exception {
|
||||
|
||||
@ -58,6 +58,7 @@ import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
|
||||
import com.vmware.vim25.VirtualLsiLogicController;
|
||||
import com.vmware.vim25.VirtualMachineConfigSpec;
|
||||
import com.vmware.vim25.VirtualMachineFileInfo;
|
||||
import com.vmware.vim25.VirtualMachineGuestOsIdentifier;
|
||||
import com.vmware.vim25.VirtualMachineVideoCard;
|
||||
import com.vmware.vim25.VirtualSCSISharing;
|
||||
import com.vmware.vim25.VmwareDistributedVirtualSwitchPvlanSpec;
|
||||
@ -1188,8 +1189,40 @@ public class HypervisorHostHelper {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String resolveHostNameInUrl(DatacenterMO dcMo, String url) {
|
||||
public static VirtualMachineMO createWorkerVM(VmwareHypervisorHost hyperHost,
|
||||
DatastoreMO dsMo, String vmName) throws Exception {
|
||||
|
||||
// Allow worker VM to float within cluster so that we will have better chance to
|
||||
// create it successfully
|
||||
ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
|
||||
if(morCluster != null)
|
||||
hyperHost = new ClusterMO(hyperHost.getContext(), morCluster);
|
||||
|
||||
VirtualMachineMO workingVM = null;
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
vmConfig.setName(vmName);
|
||||
vmConfig.setMemoryMB((long) 4);
|
||||
vmConfig.setNumCPUs(1);
|
||||
vmConfig.setGuestId(VirtualMachineGuestOsIdentifier.OTHER_GUEST.value());
|
||||
VirtualMachineFileInfo fileInfo = new VirtualMachineFileInfo();
|
||||
fileInfo.setVmPathName(dsMo.getDatastoreRootPath());
|
||||
vmConfig.setFiles(fileInfo);
|
||||
|
||||
VirtualLsiLogicController scsiController = new VirtualLsiLogicController();
|
||||
scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
scsiController.setBusNumber(0);
|
||||
scsiController.setKey(1);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
|
||||
vmConfig.getDeviceChange().add(scsiControllerSpec);
|
||||
hyperHost.createVm(vmConfig);
|
||||
workingVM = hyperHost.findVmOnHyperHost(vmName);
|
||||
return workingVM;
|
||||
}
|
||||
|
||||
public static String resolveHostNameInUrl(DatacenterMO dcMo, String url) {
|
||||
s_logger.info("Resolving host name in url through vCenter, url: " + url);
|
||||
|
||||
URI uri;
|
||||
|
||||
@ -959,14 +959,12 @@ public class VirtualMachineMO extends BaseMO {
|
||||
newDisk.setCapacityInKB(sizeInMb*1024);
|
||||
|
||||
VirtualMachineConfigSpec reConfigSpec = new VirtualMachineConfigSpec();
|
||||
//VirtualDeviceConfigSpec[] deviceConfigSpecArray = new VirtualDeviceConfigSpec[1];
|
||||
VirtualDeviceConfigSpec deviceConfigSpec = new VirtualDeviceConfigSpec();
|
||||
|
||||
deviceConfigSpec.setDevice(newDisk);
|
||||
deviceConfigSpec.setFileOperation(VirtualDeviceConfigSpecFileOperation.CREATE);
|
||||
deviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
|
||||
//deviceConfigSpecArray[0] = deviceConfigSpec;
|
||||
reConfigSpec.getDeviceChange().add(deviceConfigSpec);
|
||||
|
||||
ManagedObjectReference morTask = _context.getService().reconfigVMTask(_mor, reConfigSpec);
|
||||
|
||||
@ -27,6 +27,7 @@ import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
@ -60,8 +61,6 @@ import com.vmware.vim25.VirtualPCNet32;
|
||||
import com.vmware.vim25.VirtualVmxnet2;
|
||||
import com.vmware.vim25.VirtualVmxnet3;
|
||||
|
||||
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
|
||||
import com.cloud.hypervisor.vmware.mo.DatastoreMO;
|
||||
import com.cloud.hypervisor.vmware.mo.HostMO;
|
||||
import com.cloud.hypervisor.vmware.mo.LicenseAssignmentManagerMO;
|
||||
import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType;
|
||||
@ -611,17 +610,6 @@ public class VmwareHelper {
|
||||
return ipAddress.equals(destName);
|
||||
}
|
||||
|
||||
public static void deleteVolumeVmdkFiles(DatastoreMO dsMo, String volumeName, DatacenterMO dcMo) throws Exception {
|
||||
String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeName);
|
||||
dsMo.deleteFile(volumeDatastorePath, dcMo.getMor(), true);
|
||||
|
||||
volumeDatastorePath = String.format("[%s] %s-flat.vmdk", dsMo.getName(), volumeName);
|
||||
dsMo.deleteFile(volumeDatastorePath, dcMo.getMor(), true);
|
||||
|
||||
volumeDatastorePath = String.format("[%s] %s-delta.vmdk", dsMo.getName(), volumeName);
|
||||
dsMo.deleteFile(volumeDatastorePath, dcMo.getMor(), true);
|
||||
}
|
||||
|
||||
public static String getExceptionMessage(Throwable e) {
|
||||
return getExceptionMessage(e, false);
|
||||
}
|
||||
@ -694,4 +682,9 @@ public class VmwareHelper {
|
||||
|
||||
return hotplugSupportedByLicense;
|
||||
}
|
||||
|
||||
public static String getVCenterSafeUuid() {
|
||||
// Object name that is greater than 32 is not safe in vCenter
|
||||
return UUID.randomUUID().toString().replaceAll("-", "");
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user