From 974e57a7c24a30d99eaa0192ecd452310d3fdd90 Mon Sep 17 00:00:00 2001
From: Bryan Lima <42067040+BryanMLima@users.noreply.github.com>
Date: Thu, 21 Apr 2022 23:28:42 -0300
Subject: [PATCH] Added attach and detach features to UI for ROOT disks as well
as deviceID for ROOT and DATADISK (#6201)
---
.../command/user/volume/AttachVolumeCmd.java | 7 +++---
ui/src/config/section/storage.js | 7 ++----
ui/src/views/storage/AttachVolume.vue | 25 +++++++++++++++++--
3 files changed, 29 insertions(+), 10 deletions(-)
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java
index 18770b210b7..87ecc5700e4 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java
@@ -48,9 +48,10 @@ public class AttachVolumeCmd extends BaseAsyncCmd implements UserCmd {
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
- @Parameter(name = ApiConstants.DEVICE_ID, type = CommandType.LONG, description = "the ID of the device to map the volume to within the guest OS. "
- + "If no deviceId is passed in, the next available deviceId will be chosen. " + "Possible values for a Linux OS are:" + "* 0 - /dev/xvda" + "* 1 - /dev/xvdb" + "* 2 - /dev/xvdc"
- + "* 4 - /dev/xvde" + "* 5 - /dev/xvdf" + "* 6 - /dev/xvdg" + "* 7 - /dev/xvdh" + "* 8 - /dev/xvdi" + "* 9 - /dev/xvdj")
+ @Parameter(name = ApiConstants.DEVICE_ID, type = CommandType.LONG, description = "The ID of the device to map the volume to the guest OS. "
+ + "If no deviceID is informed, the next available deviceID will be chosen. When using a linux operating system and the hypervisor XenServer, the devices IDs will be mapped as follows:"
+ + "
- 0 maps to /dev/xvda;
- 1 maps to /dev/xvdb;
- 2 maps /dev/xvdc and so on.
"
+ + "Please refer to the docs of your hypervisor for the correct mapping of the deviceID and the actual logical disk structure.")
private Long deviceId;
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = VolumeResponse.class, required = true, description = "the ID of the disk volume")
diff --git a/ui/src/config/section/storage.js b/ui/src/config/section/storage.js
index c5990dae98f..338dc14b43d 100644
--- a/ui/src/config/section/storage.js
+++ b/ui/src/config/section/storage.js
@@ -107,7 +107,7 @@ export default {
icon: 'paper-clip-outlined',
label: 'label.action.attach.disk',
dataView: true,
- show: (record) => { return record.type !== 'ROOT' && ['Allocated', 'Ready', 'Uploaded'].includes(record.state) && !('virtualmachineid' in record) },
+ show: (record) => { return ['Allocated', 'Ready', 'Uploaded'].includes(record.state) && !('virtualmachineid' in record) },
popup: true,
component: shallowRef(defineAsyncComponent(() => import('@/views/storage/AttachVolume.vue')))
},
@@ -117,10 +117,7 @@ export default {
label: 'label.action.detach.disk',
message: 'message.detach.disk',
dataView: true,
- show: (record) => {
- return record.type !== 'ROOT' && record.virtualmachineid &&
- ['Running', 'Stopped', 'Destroyed'].includes(record.vmstate)
- }
+ show: (record) => { return record.virtualmachineid && ['Running', 'Stopped', 'Destroyed'].includes(record.vmstate) }
},
{
api: 'updateVolume',
diff --git a/ui/src/views/storage/AttachVolume.vue b/ui/src/views/storage/AttachVolume.vue
index 080911496b6..96e81ba38e9 100644
--- a/ui/src/views/storage/AttachVolume.vue
+++ b/ui/src/views/storage/AttachVolume.vue
@@ -47,6 +47,25 @@
{{ vm.name || vm.displayname }}
+
+
+
+
@@ -85,7 +104,8 @@ export default {
this.formRef = ref()
this.form = reactive({})
this.rules = reactive({
- virtualmachineid: [{ required: true, message: this.$t('message.error.select') }]
+ virtualmachineid: [{ required: true, message: this.$t('message.error.select') }],
+ deviceid: [{ required: true, message: this.$t('message.error.select') }]
})
},
fetchData () {
@@ -127,7 +147,8 @@ export default {
this.loading = true
api('attachVolume', {
id: this.resource.id,
- virtualmachineid: values.virtualmachineid
+ virtualmachineid: values.virtualmachineid,
+ deviceid: values.deviceid
}).then(response => {
this.$pollJob({
jobId: response.attachvolumeresponse.jobid,