This is an automated email from the ASF dual-hosted git repository.
rohit pushed a commit to branch 4.15
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.15 by this push:
new 98e2ed3 vmware: Add force parameter to iso attach/detach operations
(#4907)
98e2ed3 is described below
commit 98e2ed3c4fbfb6ec731fb91b6e00a98c5ecf7253
Author: Pearl Dsilva <[email protected]>
AuthorDate: Wed Apr 28 13:46:03 2021 +0530
vmware: Add force parameter to iso attach/detach operations (#4907)
Fixes: #4808, #4941
This PR adds a force flag to the attachIso / detachIso commands, especially
for VMware where it is noticed that when trying to either detach an iso or
attach an iso when there already exists another present it fails to do the
necessary operation as from ACS end we either answer the question returned by
Esxi for CDRom disconnect operation as No (for detach operation) or do not
answer the question at all (for Attach operation).
Co-authored-by: Pearl Dsilva <[email protected]>
---
.../com/cloud/template/TemplateApiService.java | 4 +-
.../api/command/user/iso/AttachIsoCmd.java | 10 +-
.../api/command/user/iso/DetachIsoCmd.java | 14 +-
.../cloudstack/storage/command/AttachCommand.java | 9 ++
.../cloudstack/storage/command/DettachCommand.java | 9 ++
.../hypervisor/vmware/resource/VmwareResource.java | 82 ++++++----
.../storage/resource/VmwareStorageProcessor.java | 12 +-
.../KubernetesClusterActionWorker.java | 4 +-
.../com/cloud/template/TemplateManagerImpl.java | 20 +--
.../main/java/com/cloud/vm/UserVmManagerImpl.java | 2 +-
ui/src/config/section/compute.js | 8 +-
ui/src/views/compute/AttachIso.vue | 8 +
.../hypervisor/vmware/mo/VirtualMachineMO.java | 171 +++++++++++----------
13 files changed, 215 insertions(+), 138 deletions(-)
diff --git a/api/src/main/java/com/cloud/template/TemplateApiService.java
b/api/src/main/java/com/cloud/template/TemplateApiService.java
index b626285..ea818a5 100644
--- a/api/src/main/java/com/cloud/template/TemplateApiService.java
+++ b/api/src/main/java/com/cloud/template/TemplateApiService.java
@@ -56,9 +56,9 @@ public interface TemplateApiService {
VirtualMachineTemplate prepareTemplate(long templateId, long zoneId, Long
storageId);
- boolean detachIso(long vmId);
+ boolean detachIso(long vmId, boolean forced);
- boolean attachIso(long isoId, long vmId);
+ boolean attachIso(long isoId, long vmId, boolean forced);
/**
* Deletes a template
diff --git
a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/AttachIsoCmd.java
b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/AttachIsoCmd.java
index 2458400..74a98be 100644
---
a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/AttachIsoCmd.java
+++
b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/AttachIsoCmd.java
@@ -54,6 +54,10 @@ public class AttachIsoCmd extends BaseAsyncCmd implements
UserCmd {
required = true, description = "the ID of the virtual machine")
protected Long virtualMachineId;
+ @Parameter(name = ApiConstants.FORCED, type = CommandType.BOOLEAN,
+ description = "If true, ejects existing ISO before attaching on
VMware. Default: false", since = "4.15.1")
+ protected Boolean forced;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -66,6 +70,10 @@ public class AttachIsoCmd extends BaseAsyncCmd implements
UserCmd {
return virtualMachineId;
}
+ public Boolean isForced() {
+ return forced != null;
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@@ -98,7 +106,7 @@ public class AttachIsoCmd extends BaseAsyncCmd implements
UserCmd {
@Override
public void execute() {
CallContext.current().setEventDetails("Vm Id: " +
getVirtualMachineId() + " ISO ID: " + getId());
- boolean result = _templateService.attachIso(id, virtualMachineId);
+ boolean result = _templateService.attachIso(id, virtualMachineId,
isForced());
if (result) {
UserVm userVm =
_responseGenerator.findUserVmById(virtualMachineId);
if (userVm != null) {
diff --git
a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/DetachIsoCmd.java
b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/DetachIsoCmd.java
index ae86e2f..4f4a019 100644
---
a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/DetachIsoCmd.java
+++
b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/DetachIsoCmd.java
@@ -44,10 +44,14 @@ public class DetachIsoCmd extends BaseAsyncCmd implements
UserCmd {
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
- @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.UUID,
entityType = UserVmResponse.class,
- required=true, description="The ID of the virtual machine")
+ @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type =
CommandType.UUID, entityType = UserVmResponse.class,
+ required = true, description = "The ID of the virtual machine")
protected Long virtualMachineId;
+ @Parameter(name = ApiConstants.FORCED, type = CommandType.BOOLEAN,
+ description = "If true, ejects the ISO before detaching on VMware.
Default: false", since = "4.15.1")
+ protected Boolean forced;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -56,6 +60,10 @@ public class DetachIsoCmd extends BaseAsyncCmd implements
UserCmd {
return virtualMachineId;
}
+ public Boolean isForced() {
+ return forced != null;
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@@ -87,7 +95,7 @@ public class DetachIsoCmd extends BaseAsyncCmd implements
UserCmd {
@Override
public void execute() {
- boolean result = _templateService.detachIso(virtualMachineId);
+ boolean result = _templateService.detachIso(virtualMachineId,
isForced());
if (result) {
UserVm userVm = _entityMgr.findById(UserVm.class,
virtualMachineId);
UserVmResponse response =
_responseGenerator.createUserVmResponse(getResponseView(), "virtualmachine",
userVm).get(0);
diff --git
a/core/src/main/java/org/apache/cloudstack/storage/command/AttachCommand.java
b/core/src/main/java/org/apache/cloudstack/storage/command/AttachCommand.java
index d15a4e4..ae6ea1f 100644
---
a/core/src/main/java/org/apache/cloudstack/storage/command/AttachCommand.java
+++
b/core/src/main/java/org/apache/cloudstack/storage/command/AttachCommand.java
@@ -27,6 +27,7 @@ public final class AttachCommand extends
StorageSubSystemCommand {
private DiskTO disk;
private String vmName;
private boolean inSeq = false;
+ private boolean forced = false;
private Map<String, String> controllerInfo;
public AttachCommand(final DiskTO disk, final String vmName) {
@@ -69,6 +70,14 @@ public final class AttachCommand extends
StorageSubSystemCommand {
this.vmName = vmName;
}
+ public boolean isForced() {
+ return forced;
+ }
+
+ public void setForced(boolean forced) {
+ this.forced = forced;
+ }
+
@Override
public void setExecuteInSequence(final boolean inSeq) {
this.inSeq = inSeq;
diff --git
a/core/src/main/java/org/apache/cloudstack/storage/command/DettachCommand.java
b/core/src/main/java/org/apache/cloudstack/storage/command/DettachCommand.java
index 1d805b5..eeeadaa 100644
---
a/core/src/main/java/org/apache/cloudstack/storage/command/DettachCommand.java
+++
b/core/src/main/java/org/apache/cloudstack/storage/command/DettachCommand.java
@@ -31,6 +31,7 @@ public class DettachCommand extends StorageSubSystemCommand {
private String _storageHost;
private int _storagePort;
private Map<String, String> params;
+ private boolean forced;
public DettachCommand(final DiskTO disk, final String vmName) {
super();
@@ -106,6 +107,14 @@ public class DettachCommand extends
StorageSubSystemCommand {
this.params = params;
}
+ public boolean isForced() {
+ return forced;
+ }
+
+ public void setForced(boolean forced) {
+ this.forced = forced;
+ }
+
@Override
public void setExecuteInSequence(final boolean inSeq) {
diff --git
a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
index 97a10e5..3136608 100644
---
a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
+++
b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
@@ -2019,35 +2019,7 @@ public class VmwareResource implements
StoragePoolResource, ServerResource, Vmwa
if (volIso != null) {
for (DiskTO vol : disks) {
if (vol.getType() == Volume.Type.ISO) {
-
- TemplateObjectTO iso = (TemplateObjectTO)
vol.getData();
-
- if (iso.getPath() != null &&
!iso.getPath().isEmpty()) {
- DataStoreTO imageStore = iso.getDataStore();
- if (!(imageStore instanceof NfsTO)) {
- s_logger.debug("unsupported protocol");
- throw new Exception("unsupported
protocol");
- }
- NfsTO nfsImageStore = (NfsTO) imageStore;
- String isoPath = nfsImageStore.getUrl() +
File.separator + iso.getPath();
- Pair<String, ManagedObjectReference>
isoDatastoreInfo = getIsoDatastoreInfo(hyperHost, isoPath);
- assert (isoDatastoreInfo != null);
- assert (isoDatastoreInfo.second() != null);
-
- deviceConfigSpecArray[i] = new
VirtualDeviceConfigSpec();
- Pair<VirtualDevice, Boolean> isoInfo =
- VmwareHelper.prepareIsoDevice(vmMo,
isoDatastoreInfo.first(), isoDatastoreInfo.second(), true, true,
ideUnitNumber++, i + 1);
-
deviceConfigSpecArray[i].setDevice(isoInfo.first());
- if (isoInfo.second()) {
- if (s_logger.isDebugEnabled())
- s_logger.debug("Prepare ISO volume at
new device " + _gson.toJson(isoInfo.first()));
-
deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD);
- } else {
- if (s_logger.isDebugEnabled())
- s_logger.debug("Prepare ISO volume at
existing device " + _gson.toJson(isoInfo.first()));
-
deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.EDIT);
- }
- }
+ configureIso(hyperHost, vmMo, vol,
deviceConfigSpecArray, ideUnitNumber++, i);
i++;
}
}
@@ -2075,8 +2047,16 @@ public class VmwareResource implements
StoragePoolResource, ServerResource, Vmwa
//
// Setup ROOT/DATA disk devices
//
+ if (multipleIsosAtached(sortedDisks) && deployAsIs) {
+ sortedDisks = getDisks(sortedDisks);
+ }
+
for (DiskTO vol : sortedDisks) {
if (vol.getType() == Volume.Type.ISO) {
+ if (deployAsIs) {
+ configureIso(hyperHost, vmMo, vol,
deviceConfigSpecArray, ideUnitNumber++, i);
+ i++;
+ }
continue;
}
@@ -2457,6 +2437,46 @@ public class VmwareResource implements
StoragePoolResource, ServerResource, Vmwa
}
}
+ private boolean multipleIsosAtached(DiskTO[] sortedDisks) {
+ return Arrays.stream(sortedDisks).filter(disk -> disk.getType() ==
Volume.Type.ISO).count() > 1;
+ }
+
+ private DiskTO[] getDisks(DiskTO[] sortedDisks) {
+ return Arrays.stream(sortedDisks).filter(vol -> ((vol.getPath() != null
&&
+ vol.getPath().contains("configdrive"))) || (vol.getType() !=
Volume.Type.ISO)).toArray(DiskTO[]::new);
+ }
+ private void configureIso(VmwareHypervisorHost hyperHost, VirtualMachineMO
vmMo, DiskTO vol,
+ VirtualDeviceConfigSpec[] deviceConfigSpecArray,
int ideUnitNumber, int i) throws Exception {
+ TemplateObjectTO iso = (TemplateObjectTO) vol.getData();
+
+ if (iso.getPath() != null && !iso.getPath().isEmpty()) {
+ DataStoreTO imageStore = iso.getDataStore();
+ if (!(imageStore instanceof NfsTO)) {
+ s_logger.debug("unsupported protocol");
+ throw new Exception("unsupported protocol");
+ }
+ NfsTO nfsImageStore = (NfsTO) imageStore;
+ String isoPath = nfsImageStore.getUrl() + File.separator +
iso.getPath();
+ Pair<String, ManagedObjectReference> isoDatastoreInfo =
getIsoDatastoreInfo(hyperHost, isoPath);
+ assert (isoDatastoreInfo != null);
+ assert (isoDatastoreInfo.second() != null);
+
+ deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
+ Pair<VirtualDevice, Boolean> isoInfo =
+ VmwareHelper.prepareIsoDevice(vmMo,
isoDatastoreInfo.first(), isoDatastoreInfo.second(), true, true, ideUnitNumber,
i + 1);
+ deviceConfigSpecArray[i].setDevice(isoInfo.first());
+ if (isoInfo.second()) {
+ if (s_logger.isDebugEnabled())
+ s_logger.debug("Prepare ISO volume at new device " +
_gson.toJson(isoInfo.first()));
+
deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD);
+ } else {
+ if (s_logger.isDebugEnabled())
+ s_logger.debug("Prepare ISO volume at existing device " +
_gson.toJson(isoInfo.first()));
+
deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.EDIT);
+ }
+ }
+ }
+
private String mapAdapterType(String adapterStringFromOVF) {
if (StringUtils.isBlank(adapterStringFromOVF) ||
adapterStringFromOVF.equalsIgnoreCase(VirtualEthernetCardType.E1000.toString()))
{
return VirtualEthernetCardType.E1000.toString();
@@ -5382,7 +5402,7 @@ public class VmwareResource implements
StoragePoolResource, ServerResource, Vmwa
"Failed to unmount vmware-tools
installer ISO as the corresponding CDROM device is locked by VM. Please unmount
the CDROM device inside the VM and ret-try.");
}
} catch (Throwable e) {
- vmMo.detachIso(null);
+ vmMo.detachIso(null, cmd.isForce());
}
}
@@ -5411,7 +5431,7 @@ public class VmwareResource implements
StoragePoolResource, ServerResource, Vmwa
String isoDatastorePath = String.format("[%s] %s%s", storeName,
isoStorePathFromRoot, isoFileName);
if (cmd.isAttach()) {
- vmMo.attachIso(isoDatastorePath, morSecondaryDs, true, false,
cmd.getDeviceKey());
+ vmMo.attachIso(isoDatastorePath, morSecondaryDs, true, false,
cmd.getDeviceKey(), cmd.isForce());
return new AttachIsoAnswer(cmd);
} else {
int key = vmMo.detachIso(isoDatastorePath, cmd.isForce());
diff --git
a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java
b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java
index a2aee6b..b06c1be 100644
---
a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java
+++
b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java
@@ -2045,7 +2045,7 @@ public class VmwareStorageProcessor implements
StorageProcessor {
@Override
public Answer attachIso(AttachCommand cmd) {
- return this.attachIso(cmd.getDisk(), true, cmd.getVmName());
+ return this.attachIso(cmd.getDisk(), true, cmd.getVmName(),
cmd.isForced());
}
@Override
@@ -2411,7 +2411,7 @@ public class VmwareStorageProcessor implements
StorageProcessor {
return morDatastore;
}
- private Answer attachIso(DiskTO disk, boolean isAttach, String vmName) {
+ private Answer attachIso(DiskTO disk, boolean isAttach, String vmName,
boolean force) {
try {
VmwareContext context = hostService.getServiceContext(null);
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context,
null);
@@ -2441,7 +2441,7 @@ public class VmwareStorageProcessor implements
StorageProcessor {
return new AttachAnswer("Failed to unmount
vmware-tools installer ISO as the corresponding CDROM device is locked by VM.
Please unmount the CDROM device inside the VM and ret-try.");
}
} catch(Throwable e){
- vmMo.detachIso(null);
+ vmMo.detachIso(null, force);
}
}
@@ -2469,9 +2469,9 @@ public class VmwareStorageProcessor implements
StorageProcessor {
String isoDatastorePath = String.format("[%s] %s/%s", storeName,
isoStorePathFromRoot, isoFileName);
if (isAttach) {
- vmMo.attachIso(isoDatastorePath, morSecondaryDs, true, false);
+ vmMo.attachIso(isoDatastorePath, morSecondaryDs, true, false,
force);
} else {
- vmMo.detachIso(isoDatastorePath);
+ vmMo.detachIso(isoDatastorePath, force);
}
return new AttachAnswer(disk);
@@ -2497,7 +2497,7 @@ public class VmwareStorageProcessor implements
StorageProcessor {
@Override
public Answer dettachIso(DettachCommand cmd) {
- return this.attachIso(cmd.getDisk(), false, cmd.getVmName());
+ return this.attachIso(cmd.getDisk(), false, cmd.getVmName(),
cmd.isForced());
}
@Override
diff --git
a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java
b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java
index e5c8118..1ca58a0 100644
---
a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java
+++
b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java
@@ -319,7 +319,7 @@ public class KubernetesClusterActionWorker {
}
for (UserVm vm : clusterVMs) {
try {
- templateService.attachIso(iso.getId(), vm.getId());
+ templateService.attachIso(iso.getId(), vm.getId(), true);
if (LOGGER.isInfoEnabled()) {
LOGGER.info(String.format("Attached binaries ISO for VM :
%s in cluster: %s", vm.getDisplayName(), kubernetesCluster.getName()));
}
@@ -337,7 +337,7 @@ public class KubernetesClusterActionWorker {
for (UserVm vm : clusterVMs) {
boolean result = false;
try {
- result = templateService.detachIso(vm.getId());
+ result = templateService.detachIso(vm.getId(), true);
} catch (CloudRuntimeException ex) {
LOGGER.warn(String.format("Failed to detach binaries ISO from
VM : %s in the Kubernetes cluster : %s ", vm.getDisplayName(),
kubernetesCluster.getName()), ex);
}
diff --git a/server/src/main/java/com/cloud/template/TemplateManagerImpl.java
b/server/src/main/java/com/cloud/template/TemplateManagerImpl.java
index deb5feb..956c456 100755
--- a/server/src/main/java/com/cloud/template/TemplateManagerImpl.java
+++ b/server/src/main/java/com/cloud/template/TemplateManagerImpl.java
@@ -1150,7 +1150,7 @@ public class TemplateManagerImpl extends ManagerBase
implements TemplateManager,
@Override
@ActionEvent(eventType = EventTypes.EVENT_ISO_DETACH, eventDescription =
"detaching ISO", async = true)
- public boolean detachIso(long vmId) {
+ public boolean detachIso(long vmId, boolean forced) {
Account caller = CallContext.current().getCallingAccount();
Long userId = CallContext.current().getCallingUserId();
@@ -1178,7 +1178,7 @@ public class TemplateManagerImpl extends ManagerBase
implements TemplateManager,
throw new InvalidParameterValueException("Please specify a VM that
is either Stopped or Running.");
}
- boolean result = attachISOToVM(vmId, userId, isoId, false); //
attach=false
+ boolean result = attachISOToVM(vmId, userId, isoId, false, forced); //
attach=false
// => detach
if (result) {
return result;
@@ -1189,7 +1189,7 @@ public class TemplateManagerImpl extends ManagerBase
implements TemplateManager,
@Override
@ActionEvent(eventType = EventTypes.EVENT_ISO_ATTACH, eventDescription =
"attaching ISO", async = true)
- public boolean attachIso(long isoId, long vmId) {
+ public boolean attachIso(long isoId, long vmId, boolean forced) {
Account caller = CallContext.current().getCallingAccount();
Long userId = CallContext.current().getCallingUserId();
@@ -1231,7 +1231,7 @@ public class TemplateManagerImpl extends ManagerBase
implements TemplateManager,
if ("vmware-tools.iso".equals(iso.getName()) && vm.getHypervisorType()
!= Hypervisor.HypervisorType.VMware) {
throw new InvalidParameterValueException("Cannot attach VMware
tools drivers to incompatible hypervisor " + vm.getHypervisorType());
}
- boolean result = attachISOToVM(vmId, userId, isoId, true);
+ boolean result = attachISOToVM(vmId, userId, isoId, true, forced);
if (result) {
return result;
} else {
@@ -1270,7 +1270,7 @@ public class TemplateManagerImpl extends ManagerBase
implements TemplateManager,
}
}
- private boolean attachISOToVM(long vmId, long isoId, boolean attach) {
+ private boolean attachISOToVM(long vmId, long isoId, boolean attach,
boolean forced) {
UserVmVO vm = _userVmDao.findById(vmId);
if (vm == null) {
@@ -1302,19 +1302,21 @@ public class TemplateManagerImpl extends ManagerBase
implements TemplateManager,
Command cmd = null;
if (attach) {
- cmd = new AttachCommand(disk, vmName, vmTO.getDetails());
+ cmd = new AttachCommand(disk, vmName);
+ ((AttachCommand)cmd).setForced(forced);
} else {
- cmd = new DettachCommand(disk, vmName, vmTO.getDetails());
+ cmd = new DettachCommand(disk, vmName);
+ ((DettachCommand)cmd).setForced(forced);
}
Answer a = _agentMgr.easySend(vm.getHostId(), cmd);
return (a != null && a.getResult());
}
- private boolean attachISOToVM(long vmId, long userId, long isoId, boolean
attach) {
+ private boolean attachISOToVM(long vmId, long userId, long isoId, boolean
attach, boolean forced) {
UserVmVO vm = _userVmDao.findById(vmId);
VMTemplateVO iso = _tmpltDao.findById(isoId);
- boolean success = attachISOToVM(vmId, isoId, attach);
+ boolean success = attachISOToVM(vmId, isoId, attach, forced);
if (success && attach) {
vm.setIsoId(iso.getId());
_userVmDao.update(vmId, vm);
diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
index 53647ea..04de128 100644
--- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
@@ -5350,7 +5350,7 @@ public class UserVmManagerImpl extends ManagerBase
implements UserVmManager, Vir
for (VMTemplateVO tmpl: child_templates){
if (tmpl.getFormat() == Storage.ImageFormat.ISO){
s_logger.info("MDOV trying to attach disk to the VM " +
tmpl.getId() + " vmid=" + vm.getId());
- _tmplService.attachIso(tmpl.getId(), vm.getId());
+ _tmplService.attachIso(tmpl.getId(), vm.getId(), true);
}
}
diff --git a/ui/src/config/section/compute.js b/ui/src/config/section/compute.js
index 69a7018..9428725 100644
--- a/ui/src/config/section/compute.js
+++ b/ui/src/config/section/compute.js
@@ -253,7 +253,13 @@ export default {
label: 'label.action.detach.iso',
message: 'message.detach.iso.confirm',
dataView: true,
- args: ['virtualmachineid'],
+ args: (record, store) => {
+ var args = ['virtualmachineid']
+ if (record && record.hypervisor && record.hypervisor === 'VMware')
{
+ args.push('forced')
+ }
+ return args
+ },
show: (record) => { return ['Running',
'Stopped'].includes(record.state) && 'isoid' in record && record.isoid },
mapping: {
virtualmachineid: {
diff --git a/ui/src/views/compute/AttachIso.vue
b/ui/src/views/compute/AttachIso.vue
index efb591f..bc12c26 100644
--- a/ui/src/views/compute/AttachIso.vue
+++ b/ui/src/views/compute/AttachIso.vue
@@ -33,6 +33,9 @@
</a-select-option>
</a-select>
</a-form-item>
+ <a-form-item :label="$t('label.forced')" v-if="resource &&
resource.hypervisor === 'VMware'">
+ <a-switch v-decorator="['forced']" :auto-focus="true" />
+ </a-form-item>
</a-form>
<div :span="24" class="action-button">
<a-button @click="closeAction">{{ this.$t('label.cancel') }}</a-button>
@@ -116,6 +119,11 @@ export default {
id: values.id,
virtualmachineid: this.resource.id
}
+
+ if (values.forced) {
+ params.forced = values.forced
+ }
+
this.loading = true
const title = this.$t('label.action.attach.iso')
api('attachIso', params).then(json => {
diff --git
a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
index e1ba6b0..0d01931 100644
---
a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
+++
b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
@@ -1498,14 +1498,82 @@ public class VirtualMachineMO extends BaseMO {
s_logger.trace("vCenter API trace - detachAllDisk()
done(successfully)");
}
+ private Future<?> answerVmwareQuestion(Boolean[] flags, VirtualMachineMO
vmMo, boolean force) {
+ Future<?> future = MonitorServiceExecutor.submit(new Runnable() {
+ @Override
+ public void run() {
+ s_logger.info("VM Question monitor started...");
+ while (!flags[0]) {
+ try {
+ VirtualMachineRuntimeInfo runtimeInfo =
vmMo.getRuntimeInfo();
+ VirtualMachineQuestionInfo question =
runtimeInfo.getQuestion();
+ if (question != null) {
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace("Question id: " +
question.getId());
+ s_logger.trace("Question text: " +
question.getText());
+ }
+ if (question.getMessage() != null) {
+ for (VirtualMachineMessage msg :
question.getMessage()) {
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace("msg id: " +
msg.getId());
+ s_logger.trace("msg text: " +
msg.getText());
+ }
+ if
("msg.cdromdisconnect.locked".equalsIgnoreCase(msg.getId())) {
+ s_logger.info("Found that VM has a
pending question that we need to answer programmatically, question id: " +
msg.getId() +
+ ", for safe operation we will
automatically decline it");
+ vmMo.answerVM(question.getId(), force
? ANSWER_YES : ANSWER_NO);
+ break;
+ }
+ }
+ } else if (question.getText() != null) {
+ String text = question.getText();
+ String msgId;
+ String msgText;
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("question text : " + text);
+ }
+ String[] tokens = text.split(":");
+ msgId = tokens[0];
+ msgText = tokens[1];
+ if
("msg.cdromdisconnect.locked".equalsIgnoreCase(msgId)) {
+ s_logger.info("Found that VM has a pending
question that we need to answer programmatically, question id: " +
question.getId() +
+ ". Message id : " + msgId + ".
Message text : " + msgText + ", for safe operation we will automatically
decline it.");
+ vmMo.answerVM(question.getId(), force ?
ANSWER_YES : ANSWER_NO);
+ }
+ }
+
+ ChoiceOption choice = question.getChoice();
+ if (choice != null) {
+ for (ElementDescription info :
choice.getChoiceInfo()) {
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace("Choice option key: " +
info.getKey());
+ s_logger.trace("Choice option label: "
+ info.getLabel());
+ }
+ }
+ }
+ }
+ } catch (Throwable e) {
+ s_logger.error("Unexpected exception: ", e);
+ }
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ s_logger.debug("[ignored] interupted while handling vm
question about iso detach.");
+ }
+ }
+ s_logger.info("VM Question monitor stopped");
+ }
+ });
+ return future;
+ }
// isoDatastorePath: [datastore name] isoFilePath
- public void attachIso(String isoDatastorePath, ManagedObjectReference
morDs, boolean connect, boolean connectAtBoot) throws Exception {
- attachIso(isoDatastorePath, morDs, connect, connectAtBoot, null);
+ public void attachIso(String isoDatastorePath, ManagedObjectReference
morDs, boolean connect, boolean connectAtBoot, boolean forced) throws Exception
{
+ attachIso(isoDatastorePath, morDs, connect, connectAtBoot, null,
forced);
}
// isoDatastorePath: [datastore name] isoFilePath
public void attachIso(String isoDatastorePath, ManagedObjectReference
morDs,
- boolean connect, boolean connectAtBoot, Integer key) throws Exception {
+ boolean connect, boolean connectAtBoot, Integer key, boolean force) throws
Exception {
if (s_logger.isTraceEnabled())
s_logger.trace("vCenter API trace - attachIso(). target MOR: " +
_mor.getValue() + ", isoDatastorePath: " + isoDatastorePath + ", datastore: " +
@@ -1556,22 +1624,26 @@ public class VirtualMachineMO extends BaseMO {
reConfigSpec.getDeviceChange().add(deviceConfigSpec);
ManagedObjectReference morTask =
_context.getService().reconfigVMTask(_mor, reConfigSpec);
- boolean result = _context.getVimClient().waitForTask(morTask);
- if (!result) {
- if (s_logger.isTraceEnabled())
- s_logger.trace("vCenter API trace - attachIso() done(failed)");
- throw new Exception("Failed to attach ISO due to " +
TaskMO.getTaskFailureInfo(_context, morTask));
- }
-
- _context.waitForTaskProgressDone(morTask);
+ final Boolean[] flags = {false};
+ final VirtualMachineMO vmMo = this;
+ Future<?> future = answerVmwareQuestion(flags, vmMo, force);
+ try {
+ boolean result = _context.getVimClient().waitForTask(morTask);
- if (s_logger.isTraceEnabled())
- s_logger.trace("vCenter API trace - attachIso()
done(successfully)");
- }
+ if (!result) {
+ if (s_logger.isTraceEnabled())
+ s_logger.trace("vCenter API trace - attachIso()
done(failed)");
+ throw new Exception("Failed to attach ISO due to " +
TaskMO.getTaskFailureInfo(_context, morTask));
+ }
+ _context.waitForTaskProgressDone(morTask);
- public int detachIso(String isoDatastorePath) throws Exception {
- return detachIso(isoDatastorePath, false);
+ if (s_logger.isTraceEnabled())
+ s_logger.trace("vCenter API trace - attachIso()
done(successfully)");
+ } finally {
+ flags[0] = true;
+ future.cancel(true);
+ }
}
public int detachIso(String isoDatastorePath, final boolean force) throws
Exception {
@@ -1604,72 +1676,7 @@ public class VirtualMachineMO extends BaseMO {
// Monitor VM questions
final Boolean[] flags = {false};
final VirtualMachineMO vmMo = this;
- Future<?> future = MonitorServiceExecutor.submit(new Runnable() {
- @Override
- public void run() {
- s_logger.info("VM Question monitor started...");
-
- while (!flags[0]) {
- try {
- VirtualMachineRuntimeInfo runtimeInfo =
vmMo.getRuntimeInfo();
- VirtualMachineQuestionInfo question =
runtimeInfo.getQuestion();
- if (question != null) {
- if (s_logger.isTraceEnabled()) {
- s_logger.trace("Question id: " +
question.getId());
- s_logger.trace("Question text: " +
question.getText());
- }
- if (question.getMessage() != null) {
- for (VirtualMachineMessage msg :
question.getMessage()) {
- if (s_logger.isTraceEnabled()) {
- s_logger.trace("msg id: " +
msg.getId());
- s_logger.trace("msg text: " +
msg.getText());
- }
- if
("msg.cdromdisconnect.locked".equalsIgnoreCase(msg.getId())) {
- s_logger.info("Found that VM has a
pending question that we need to answer programmatically, question id: " +
msg.getId() +
- ", for safe operation we will
automatically decline it");
- vmMo.answerVM(question.getId(), force
? ANSWER_YES : ANSWER_NO);
- break;
- }
- }
- } else if (question.getText() != null) {
- String text = question.getText();
- String msgId;
- String msgText;
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("question text : " + text);
- }
- String[] tokens = text.split(":");
- msgId = tokens[0];
- msgText = tokens[1];
- if
("msg.cdromdisconnect.locked".equalsIgnoreCase(msgId)) {
- s_logger.info("Found that VM has a pending
question that we need to answer programmatically, question id: " +
question.getId() +
- ". Message id : " + msgId + ".
Message text : " + msgText + ", for safe operation we will automatically
decline it.");
- vmMo.answerVM(question.getId(), force ?
ANSWER_YES : ANSWER_NO);
- }
- }
-
- ChoiceOption choice = question.getChoice();
- if (choice != null) {
- for (ElementDescription info :
choice.getChoiceInfo()) {
- if (s_logger.isTraceEnabled()) {
- s_logger.trace("Choice option key: " +
info.getKey());
- s_logger.trace("Choice option label: "
+ info.getLabel());
- }
- }
- }
- }
- } catch (Throwable e) {
- s_logger.error("Unexpected exception: ", e);
- }
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- s_logger.debug("[ignored] interupted while handling vm
question about iso detach.");
- }
- }
- s_logger.info("VM Question monitor stopped");
- }
- });
+ Future<?> future = answerVmwareQuestion(flags, vmMo, force);
try {
boolean result = _context.getVimClient().waitForTask(morTask);
if (!result) {