diff --git a/engine/schema/pom.xml b/engine/schema/pom.xml index 21066ff3c8f..4ffef5c532e 100644 --- a/engine/schema/pom.xml +++ b/engine/schema/pom.xml @@ -122,7 +122,7 @@ wget - https://download.cloudstack.org/systemvm/${cs.version}/md5sum.txt + ${project.systemvm.template.location}/${cs.version}/md5sum.txt ${basedir}/dist/systemvm-templates/ true true @@ -181,7 +181,7 @@ true - https://download.cloudstack.org/systemvm/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-kvm.qcow2.bz2 + ${project.systemvm.template.location}/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-kvm.qcow2.bz2 ${basedir}/dist/systemvm-templates/ ${kvm.checksum} @@ -217,7 +217,7 @@ true - https://download.cloudstack.org/systemvm/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-vmware.ova + ${project.systemvm.template.location}/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-vmware.ova ${basedir}/dist/systemvm-templates/ ${vmware.checksum} @@ -253,7 +253,7 @@ true - https://download.cloudstack.org/systemvm/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-xen.vhd.bz2 + ${project.systemvm.template.location}/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-xen.vhd.bz2 ${basedir}/dist/systemvm-templates/ ${xen.checksum} @@ -289,7 +289,7 @@ true - https://download.cloudstack.org/systemvm/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-ovm.raw.bz2 + ${project.systemvm.template.location}/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-ovm.raw.bz2 ${basedir}/dist/systemvm-templates/ ${ovm.checksum} @@ -325,7 +325,7 @@ true - https://download.cloudstack.org/systemvm/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-hyperv.vhd.zip + ${project.systemvm.template.location}/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-hyperv.vhd.zip ${basedir}/dist/systemvm-templates/ ${hyperv.checksum} diff --git a/packaging/centos7/cloud.spec b/packaging/centos7/cloud.spec index 44dc06d1849..c6ae6a63ae5 100644 --- a/packaging/centos7/cloud.spec +++ b/packaging/centos7/cloud.spec @@ -61,6 +61,7 @@ intelligent IaaS cloud implementation. %package management Summary: CloudStack management server UI Requires: java-11-openjdk +Requires: tzdata-java Requires: python Requires: python3 Requires: bash @@ -107,6 +108,7 @@ The Apache CloudStack files shared between agent and management server Summary: CloudStack Agent for KVM hypervisors Requires: openssh-clients Requires: java-11-openjdk +Requires: tzdata-java Requires: %{name}-common = %{_ver} Requires: libvirt Requires: bridge-utils @@ -142,6 +144,7 @@ The CloudStack baremetal agent %package usage Summary: CloudStack Usage calculation server Requires: java-11-openjdk +Requires: tzdata-java Group: System Environment/Libraries %description usage The CloudStack usage calculation service diff --git a/packaging/centos8/cloud.spec b/packaging/centos8/cloud.spec index f2b020518db..a6b148afbe9 100644 --- a/packaging/centos8/cloud.spec +++ b/packaging/centos8/cloud.spec @@ -53,6 +53,7 @@ intelligent IaaS cloud implementation. %package management Summary: CloudStack management server UI Requires: java-11-openjdk +Requires: tzdata-java Requires: python3 Requires: bash Requires: gawk @@ -98,6 +99,7 @@ The Apache CloudStack files shared between agent and management server Summary: CloudStack Agent for KVM hypervisors Requires: (openssh-clients or openssh) Requires: java-11-openjdk +Requires: tzdata-java Requires: %{name}-common = %{_ver} Requires: libvirt Requires: ebtables @@ -134,6 +136,7 @@ The CloudStack baremetal agent %package usage Summary: CloudStack Usage calculation server Requires: java-11-openjdk +Requires: tzdata-java Group: System Environment/Libraries %description usage The CloudStack usage calculation service diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index f4ce29c5762..81298a9c898 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -2791,10 +2791,15 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv grd.setMemBalloning(!_noMemBalloon); - Long maxRam = ByteScaleUtils.bytesToKibibytes(vmTO.getMaxRam()); + long maxRam = ByteScaleUtils.bytesToKibibytes(vmTO.getMaxRam()); + long currRam = vmTO.getType() == VirtualMachine.Type.User ? getCurrentMemAccordingToMemBallooning(vmTO, maxRam) : maxRam; + + if (s_logger.isTraceEnabled()) { + s_logger.trace(String.format("memory values for VM %s are %d/%d",vmTO.getName(),maxRam, currRam)); + } grd.setMemorySize(maxRam); - grd.setCurrentMem(getCurrentMemAccordingToMemBallooning(vmTO, maxRam)); + grd.setCurrentMem(currRam); int vcpus = vmTO.getCpus(); Integer maxVcpus = vmTO.getVcpuMaxLimit(); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java index aac44fc1419..3ea7dd69eed 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java @@ -282,7 +282,7 @@ public class LibvirtVMDef { @Override public String toString() { StringBuilder response = new StringBuilder(); - response.append(String.format("%s\n", this.currentMemory)); + response.append(String.format("%s\n", this.memory)); response.append(String.format("%s\n", this.currentMemory)); if (this.memory > this.currentMemory) { @@ -1238,7 +1238,7 @@ public class LibvirtVMDef { @Override public String toString() { StringBuilder memBalloonBuilder = new StringBuilder(); - memBalloonBuilder.append("\n"); + memBalloonBuilder.append("\n"); if (StringUtils.isNotBlank(memBalloonStatsPeriod)) { memBalloonBuilder.append("\n"); } diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java index ffe20b4ad30..58682b2663c 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java @@ -760,7 +760,7 @@ public class LibvirtComputingResourceTest { private void verifyMemory(VirtualMachineTO to, Document domainDoc, String minRam) { assertXpath(domainDoc, "/domain/maxMemory/text()", String.valueOf( to.getMaxRam() / 1024 )); - assertXpath(domainDoc, "/domain/memory/text()",minRam); + assertXpath(domainDoc, "/domain/currentMemory/text()",minRam); assertXpath(domainDoc, "/domain/cpu/numa/cell/@memory", minRam); assertXpath(domainDoc, "/domain/currentMemory/text()", minRam); } diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java index 57bdf81f528..db7cea5e218 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java @@ -266,11 +266,11 @@ public class LibvirtVMDefTest extends TestCase { assertEquals(bus, disk.getBusType()); assertEquals(DiskDef.DeviceType.DISK, disk.getDeviceType()); - String xmlDef = disk.toString(); + String resultingXml = disk.toString(); String expectedXml = "\n\n" + "\n\n\n"; - assertEquals(xmlDef, expectedXml); + assertEquals(expectedXml, resultingXml); } @Test @@ -288,7 +288,7 @@ public class LibvirtVMDefTest extends TestCase { "\n" + "\n" + "\n"; - assertEquals(disk.toString(), expectedXML); + assertEquals(expectedXML, disk.toString()); } @Test @@ -398,7 +398,7 @@ public class LibvirtVMDefTest extends TestCase { LibvirtVMDef.setGlobalQemuVersion(2006000L); LibvirtVMDef.setGlobalLibvirtVersion(9008L); - String xmlDef = disk.toString(); + String resultingXml = disk.toString(); String expectedXml = "\n\n" + "\n\n" + "\n"+bytesReadRate+"\n"+bytesWriteRate+"\n" + @@ -408,29 +408,29 @@ public class LibvirtVMDefTest extends TestCase { ""+bytesReadRateMaxLength+"\n"+bytesWriteRateMaxLength+"\n" + ""+iopsReadRateMaxLength+"\n"+iopsWriteRateMaxLength+"\n\n\n"; - assertEquals(xmlDef, expectedXml); + assertEquals(expectedXml, resultingXml); } @Test public void memBalloonDefTestNone() { - String expectedXml = "\n"; + String expectedXml = "\n"; MemBalloonDef memBalloonDef = new MemBalloonDef(); memBalloonDef.defNoneMemBalloon(); - String xmlDef = memBalloonDef.toString(); + String resultingXml = memBalloonDef.toString(); - assertEquals(xmlDef, expectedXml); + assertEquals(expectedXml, resultingXml); } @Test public void memBalloonDefTestVirtio() { - String expectedXml = "\n\n"; + String expectedXml = "\n\n"; MemBalloonDef memBalloonDef = new MemBalloonDef(); memBalloonDef.defVirtioMemBalloon("60"); - String xmlDef = memBalloonDef.toString(); + String resultingXml = memBalloonDef.toString(); - assertEquals(xmlDef, expectedXml); + assertEquals(expectedXml, resultingXml); } @Test @@ -465,11 +465,11 @@ public class LibvirtVMDefTest extends TestCase { int bytes = 2048; LibvirtVMDef.RngDef def = new LibvirtVMDef.RngDef(path, backendModel, bytes, period); - assertEquals(def.getPath(), path); - assertEquals(def.getRngBackendModel(), backendModel); - assertEquals(def.getRngModel(), LibvirtVMDef.RngDef.RngModel.VIRTIO); - assertEquals(def.getRngRateBytes(), bytes); - assertEquals(def.getRngRatePeriod(), period); + assertEquals(path, def.getPath()); + assertEquals(backendModel, def.getRngBackendModel()); + assertEquals(LibvirtVMDef.RngDef.RngModel.VIRTIO, def.getRngModel()); + assertEquals(bytes, def.getRngRateBytes()); + assertEquals(period, def.getRngRatePeriod()); } @Test @@ -493,8 +493,8 @@ public class LibvirtVMDefTest extends TestCase { LibvirtVMDef.WatchDogDef.WatchDogAction action = LibvirtVMDef.WatchDogDef.WatchDogAction.RESET; LibvirtVMDef.WatchDogDef def = new LibvirtVMDef.WatchDogDef(action, model); - assertEquals(def.getModel(), model); - assertEquals(def.getAction(), action); + assertEquals(model, def.getModel()); + assertEquals(action, def.getAction()); } @Test @@ -505,6 +505,6 @@ public class LibvirtVMDefTest extends TestCase { "
\n" + "\n" + "\n"; - assertEquals(str, expected); + assertEquals(expected, str); } } diff --git a/pom.xml b/pom.xml index 204c74cc765..c42049fec5c 100644 --- a/pom.xml +++ b/pom.xml @@ -49,6 +49,7 @@ UTF-8 UTF-8 + https://download.cloudstack.org/systemvm 4.18.0.0 apache https://sonarcloud.io diff --git a/python/lib/cloudutils/configFileOps.py b/python/lib/cloudutils/configFileOps.py index 698f2b31a3a..41e9c7a1e8e 100644 --- a/python/lib/cloudutils/configFileOps.py +++ b/python/lib/cloudutils/configFileOps.py @@ -15,6 +15,7 @@ # specific language governing permissions and limitations # under the License. import re +import os import tempfile import shutil from .utilities import bash @@ -59,39 +60,42 @@ class configFileOps: return "" def save(self): - fp = open(self.fileName, "r") newLines = [] - for line in fp.readlines(): - matched = False - for entry in self.entries: - if entry.op == "add": - if entry.separator == "=": - matchString = "^\ *" + entry.name + ".*" - elif entry.separator == " ": - matchString = "^\ *" + entry.name + "\ *" + entry.value - else: - if entry.separator == "=": - matchString = "^\ *" + entry.name + "\ *=\ *" + entry.value + if os.path.exists(self.fileName) and os.path.isfile(self.fileName): + fp = open(self.fileName, "r") + for line in fp.readlines(): + matched = False + for entry in self.entries: + if entry.op == "add": + if entry.separator == "=": + matchString = "^\ *" + entry.name + ".*" + elif entry.separator == " ": + matchString = "^\ *" + entry.name + "\ *" + entry.value else: - matchString = "^\ *" + entry.name + "\ *" + entry.value + if entry.separator == "=": + matchString = "^\ *" + entry.name + "\ *=\ *" + entry.value + else: + matchString = "^\ *" + entry.name + "\ *" + entry.value - match = re.match(matchString, line) - if match is not None: - if entry.op == "add" and entry.separator == "=": - newline = "\n" + entry.name + "=" + entry.value + "\n" - entry.setState("set") - newLines.append(newline) - self.backups.append([line, newline]) - matched = True - break - elif entry.op == "rm": - entry.setState("set") - self.backups.append([line, None]) - matched = True - break + match = re.match(matchString, line) + if match is not None: + if entry.op == "add" and entry.separator == "=": + newline = "\n" + entry.name + "=" + entry.value + "\n" + entry.setState("set") + newLines.append(newline) + self.backups.append([line, newline]) + matched = True + break + elif entry.op == "rm": + entry.setState("set") + self.backups.append([line, None]) + matched = True + break - if not matched: - newLines.append(line) + if not matched: + newLines.append(line) + + fp.close() for entry in self.entries: if entry.getState() != "set": @@ -101,8 +105,6 @@ class configFileOps: self.backups.append([None, newline]) entry.setState("set") - fp.close() - open(self.fileName, "w").writelines(newLines) def replace_line(self, startswith,stanza,always_add=False): diff --git a/server/src/main/java/com/cloud/hypervisor/KVMGuru.java b/server/src/main/java/com/cloud/hypervisor/KVMGuru.java index f0ccffbc719..7c02d95f3eb 100644 --- a/server/src/main/java/com/cloud/hypervisor/KVMGuru.java +++ b/server/src/main/java/com/cloud/hypervisor/KVMGuru.java @@ -213,7 +213,7 @@ public class KVMGuru extends HypervisorGuruBase implements HypervisorGuru { Integer maxHostCpuCore = max.second(); long minMemory = virtualMachineTo.getMinRam(); - Long maxMemory = minMemory; + Long maxMemory = virtualMachineTo.getMaxRam(); int minCpuCores = virtualMachineTo.getCpus(); Integer maxCpuCores = minCpuCores; diff --git a/server/src/main/java/com/cloud/resourcelimit/CheckedReservation.java b/server/src/main/java/com/cloud/resourcelimit/CheckedReservation.java index d0c20a3a7af..5650af15339 100644 --- a/server/src/main/java/com/cloud/resourcelimit/CheckedReservation.java +++ b/server/src/main/java/com/cloud/resourcelimit/CheckedReservation.java @@ -76,7 +76,7 @@ public class CheckedReservation implements AutoCloseable, ResourceReservation { resourceLimitService.checkResourceLimit(account,resourceType,amount); ReservationVO reservationVO = new ReservationVO(account.getAccountId(), account.getDomainId(), resourceType, amount); this.reservation = reservationDao.persist(reservationVO); - CallContext.current().putContextParameter(getContextParameterKey(), reservationVO.getId()); + CallContext.current().putContextParameter(getContextParameterKey(), reservation.getId()); } catch (NullPointerException npe) { throw new CloudRuntimeException("not enough means to check limits", npe); } finally { diff --git a/ui/src/components/view/SearchView.vue b/ui/src/components/view/SearchView.vue index 267d8937c4c..bce8a6bb9e5 100644 --- a/ui/src/components/view/SearchView.vue +++ b/ui/src/components/view/SearchView.vue @@ -65,7 +65,8 @@ :filterOption="(input, option) => { return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0 }" - :loading="field.loading"> + :loading="field.loading" + @input="onchange($event, field.name)"> { @@ -291,14 +295,9 @@ export default { }) arrayField.push(item) }) - - const promises = [] - let zoneIndex = -1 - let domainIndex = -1 - let podIndex = -1 - let clusterIndex = -1 - let groupIndex = -1 - + return arrayField + }, + fetchStaticFieldData (arrayField) { if (arrayField.includes('type')) { if (this.$route.path === '/guestnetwork' || this.$route.path.includes('/guestnetwork/')) { const typeIndex = this.fields.findIndex(item => item.name === 'type') @@ -322,36 +321,6 @@ export default { this.fields[levelIndex].loading = false } - if (arrayField.includes('zoneid')) { - zoneIndex = this.fields.findIndex(item => item.name === 'zoneid') - this.fields[zoneIndex].loading = true - promises.push(await this.fetchZones()) - } - - if (arrayField.includes('domainid')) { - domainIndex = this.fields.findIndex(item => item.name === 'domainid') - this.fields[domainIndex].loading = true - promises.push(await this.fetchDomains()) - } - - if (arrayField.includes('podid')) { - podIndex = this.fields.findIndex(item => item.name === 'podid') - this.fields[podIndex].loading = true - promises.push(await this.fetchPods()) - } - - if (arrayField.includes('clusterid')) { - clusterIndex = this.fields.findIndex(item => item.name === 'clusterid') - this.fields[clusterIndex].loading = true - promises.push(await this.fetchClusters()) - } - - if (arrayField.includes('groupid')) { - groupIndex = this.fields.findIndex(item => item.name === 'groupid') - this.fields[groupIndex].loading = true - promises.push(await this.fetchInstanceGroups()) - } - if (arrayField.includes('entitytype')) { const entityTypeIndex = this.fields.findIndex(item => item.name === 'entitytype') this.fields[entityTypeIndex].loading = true @@ -374,6 +343,44 @@ export default { ] this.fields[resourceTypeIndex].loading = false } + }, + async fetchDynamicFieldData (arrayField, searchKeyword) { + const promises = [] + let zoneIndex = -1 + let domainIndex = -1 + let podIndex = -1 + let clusterIndex = -1 + let groupIndex = -1 + + if (arrayField.includes('zoneid')) { + zoneIndex = this.fields.findIndex(item => item.name === 'zoneid') + this.fields[zoneIndex].loading = true + promises.push(await this.fetchZones(searchKeyword)) + } + + if (arrayField.includes('domainid')) { + domainIndex = this.fields.findIndex(item => item.name === 'domainid') + this.fields[domainIndex].loading = true + promises.push(await this.fetchDomains(searchKeyword)) + } + + if (arrayField.includes('podid')) { + podIndex = this.fields.findIndex(item => item.name === 'podid') + this.fields[podIndex].loading = true + promises.push(await this.fetchPods(searchKeyword)) + } + + if (arrayField.includes('clusterid')) { + clusterIndex = this.fields.findIndex(item => item.name === 'clusterid') + this.fields[clusterIndex].loading = true + promises.push(await this.fetchClusters(searchKeyword)) + } + + if (arrayField.includes('groupid')) { + groupIndex = this.fields.findIndex(item => item.name === 'groupid') + this.fields[groupIndex].loading = true + promises.push(await this.fetchInstanceGroups(searchKeyword)) + } Promise.all(promises).then(response => { if (zoneIndex > -1) { @@ -425,6 +432,13 @@ export default { this.fillFormFieldValues() }) }, + initFormFieldData () { + const arrayField = this.initFields() + + this.fetchStaticFieldData(arrayField) + + this.fetchDynamicFieldData(arrayField) + }, sortArray (data, key = 'name') { return data.sort(function (a, b) { if (a[key] < b[key]) { return -1 } @@ -447,9 +461,9 @@ export default { this.inputKey = this.fieldValues['tags[0].key'] || null this.inputValue = this.fieldValues['tags[0].value'] || null }, - fetchZones () { + fetchZones (searchKeyword) { return new Promise((resolve, reject) => { - api('listZones', { showicon: true }).then(json => { + api('listZones', { showicon: true, keyword: searchKeyword }).then(json => { const zones = json.listzonesresponse.zone resolve({ type: 'zoneid', @@ -460,9 +474,9 @@ export default { }) }) }, - fetchDomains () { + fetchDomains (searchKeyword) { return new Promise((resolve, reject) => { - api('listDomains', { listAll: true, showicon: true }).then(json => { + api('listDomains', { listAll: true, showicon: true, keyword: searchKeyword }).then(json => { const domain = json.listdomainsresponse.domain resolve({ type: 'domainid', @@ -473,9 +487,9 @@ export default { }) }) }, - fetchPods () { + fetchPods (searchKeyword) { return new Promise((resolve, reject) => { - api('listPods').then(json => { + api('listPods', { keyword: searchKeyword }).then(json => { const pods = json.listpodsresponse.pod resolve({ type: 'podid', @@ -486,9 +500,9 @@ export default { }) }) }, - fetchClusters () { + fetchClusters (searchKeyword) { return new Promise((resolve, reject) => { - api('listClusters').then(json => { + api('listClusters', { keyword: searchKeyword }).then(json => { const clusters = json.listclustersresponse.cluster resolve({ type: 'clusterid', @@ -499,9 +513,9 @@ export default { }) }) }, - fetchInstanceGroups () { + fetchInstanceGroups (searchKeyword) { return new Promise((resolve, reject) => { - api('listInstanceGroups', { listAll: true }).then(json => { + api('listInstanceGroups', { listAll: true, keyword: searchKeyword }).then(json => { const instancegroups = json.listinstancegroupsresponse.instancegroup resolve({ type: 'groupid', diff --git a/ui/src/config/section/compute.js b/ui/src/config/section/compute.js index 058c41ed444..6d2c55b4111 100644 --- a/ui/src/config/section/compute.js +++ b/ui/src/config/section/compute.js @@ -164,6 +164,14 @@ export default { message: 'message.reinstall.vm', dataView: true, args: ['virtualmachineid', 'templateid'], + filters: (record) => { + var filters = {} + var filterParams = {} + filterParams.hypervisortype = record.hypervisor + filterParams.zoneid = record.zoneid + filters.templateid = filterParams + return filters + }, show: (record) => { return ['Running', 'Stopped'].includes(record.state) }, mapping: { virtualmachineid: { diff --git a/ui/src/views/AutogenView.vue b/ui/src/views/AutogenView.vue index 0bcf3dfbd3d..3c476e168ae 100644 --- a/ui/src/views/AutogenView.vue +++ b/ui/src/views/AutogenView.vue @@ -794,6 +794,10 @@ export default { this.dataView = false } + if (this.dataView && ['Admin'].includes(this.$store.getters.userInfo.roletype) && this.routeName === 'volume') { + params.listsystemvms = true + } + if ('listview' in this.$refs && this.$refs.listview) { this.$refs.listview.resetSelection() } @@ -1047,7 +1051,6 @@ export default { this.setModalWidthByScreen() }, execAction (action, isGroupAction) { - const self = this this.formRef = ref() this.form = reactive({}) this.rules = reactive({}) @@ -1085,6 +1088,7 @@ export default { return 0 }) this.currentAction.paramFields = [] + this.currentAction.paramFilters = [] if ('message' in action) { var message = action.message if (typeof action.message === 'function') { @@ -1092,6 +1096,29 @@ export default { } action.message = message } + + this.getArgs(action, isGroupAction, paramFields) + this.getFilters(action, isGroupAction, paramFields) + this.getFirstIndexFocus() + + this.showAction = true + const listIconForFillValues = ['copy-outlined', 'CopyOutlined', 'edit-outlined', 'EditOutlined', 'share-alt-outlined', 'ShareAltOutlined'] + for (const param of this.currentAction.paramFields) { + if (param.type === 'list' && ['tags', 'hosttags', 'storagetags', 'files'].includes(param.name)) { + param.type = 'string' + } + this.setRules(param) + if (param.type === 'uuid' || param.type === 'list' || param.name === 'account' || (this.currentAction.mapping && param.name in this.currentAction.mapping)) { + this.listUuidOpts(param, this.currentAction.paramFilters[param.name]) + } + } + this.actionLoading = false + if (action.dataView && listIconForFillValues.includes(action.icon)) { + this.fillEditFormFieldValues() + } + }, + getArgs (action, isGroupAction, paramFields) { + const self = this if ('args' in action) { var args = action.args if (typeof action.args === 'function') { @@ -1121,22 +1148,14 @@ export default { }) } } - this.getFirstIndexFocus() - - this.showAction = true - const listIconForFillValues = ['copy-outlined', 'CopyOutlined', 'edit-outlined', 'EditOutlined', 'share-alt-outlined', 'ShareAltOutlined'] - for (const param of this.currentAction.paramFields) { - if (param.type === 'list' && ['tags', 'hosttags', 'storagetags', 'files'].includes(param.name)) { - param.type = 'string' + }, + getFilters (action, isGroupAction, paramFields) { + if ('filters' in action) { + var filters = action.filters + if (typeof action.filters === 'function') { + filters = action.filters(action.resource, this.$store.getters, isGroupAction) } - this.setRules(param) - if (param.type === 'uuid' || param.type === 'list' || param.name === 'account' || (this.currentAction.mapping && param.name in this.currentAction.mapping)) { - this.listUuidOpts(param) - } - } - this.actionLoading = false - if (action.dataView && listIconForFillValues.includes(action.icon)) { - this.fillEditFormFieldValues() + this.currentAction.paramFilters = filters } }, getFirstIndexFocus () { @@ -1149,13 +1168,16 @@ export default { } } }, - listUuidOpts (param) { + listUuidOpts (param, filters) { if (this.currentAction.mapping && param.name in this.currentAction.mapping && !this.currentAction.mapping[param.name].api) { return } var paramName = param.name var extractedParamName = paramName.replace('ids', '').replace('id', '').toLowerCase() var params = { listall: true } + for (const filter in filters) { + params[filter] = filters[filter] + } const possibleName = 'list' + extractedParamName + 's' var showIcon = false if (this.$showIcon(extractedParamName)) {