This is an automated email from the ASF dual-hosted git repository. rohit pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/cloudstack-primate.git
The following commit(s) were added to refs/heads/master by this push: new fb1ce46 compute: Adding custom Vue to change the vm service offering (#413) fb1ce46 is described below commit fb1ce46afda28928b7019b3a85cf8951ca41885b Author: davidjumani <dj.davidjumani1...@gmail.com> AuthorDate: Thu Jun 25 11:44:08 2020 +0000 compute: Adding custom Vue to change the vm service offering (#413) Fixes #381 --- src/config/section/compute.js | 15 +- src/views/compute/ScaleVM.vue | 233 +++++++++++++++++++++ .../compute/wizard/ComputeOfferingSelection.vue | 3 + src/views/compute/wizard/ComputeSelection.vue | 3 + 4 files changed, 242 insertions(+), 12 deletions(-) diff --git a/src/config/section/compute.js b/src/config/section/compute.js index a1e727a..053acae 100644 --- a/src/config/section/compute.js +++ b/src/config/section/compute.js @@ -292,21 +292,12 @@ export default { { api: 'scaleVirtualMachine', icon: 'arrows-alt', - // label: label.change.service.offering label: 'Scale VM', docHelp: 'adminguide/virtual_machines.html#how-to-dynamically-scale-cpu-and-ram', dataView: true, - args: ['serviceofferingid', 'details'], - show: (record) => { return ['Running'].includes(record.state) && record.hypervisor !== 'KVM' && record.hypervisor !== 'LXC' } - }, - { - api: 'changeServiceForVirtualMachine', - icon: 'sliders', - label: 'label.change.service.offering', - docHelp: 'adminguide/virtual_machines.html#changing-the-service-offering-for-a-vm', - dataView: true, - args: ['serviceofferingid'], - show: (record) => { return ['Stopped'].includes(record.state) || (['Running'].includes(record.state) && record.hypervisor !== 'KVM' && record.hypervisor !== 'LXC') } + show: (record) => { return ['Stopped'].includes(record.state) || (['Running'].includes(record.state) && record.hypervisor !== 'KVM' && record.hypervisor !== 'LXC') }, + popup: true, + component: () => import('@/views/compute/ScaleVM.vue') }, { api: 'migrateVirtualMachine', diff --git a/src/views/compute/ScaleVM.vue b/src/views/compute/ScaleVM.vue new file mode 100644 index 0000000..1bff110 --- /dev/null +++ b/src/views/compute/ScaleVM.vue @@ -0,0 +1,233 @@ +// 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. + +<template> + <a-form class="form"> + <p v-html="getMessage()"></p> + + <div v-if="loading" class="loading"> + <a-icon type="loading" style="color: #1890ff;"></a-icon> + </div> + + <compute-offering-selection + :compute-items="offerings" + :loading="loading" + :rowCount="total" + size="small" + @select-compute-item="($event) => updateComputeOffering($event)" + @handle-search-filter="($event) => fetchData($event)" /> + + <compute-selection + v-if="selectedOffering && selectedOffering.iscustomized" + :cpunumber-input-decorator="cpuNumberKey" + :cpuspeed-input-decorator="cpuSpeedKey" + :memory-input-decorator="memoryKey" + :computeOfferingId="selectedOffering.id" + :isConstrained="'serviceofferingdetails' in selectedOffering" + :minCpu="getMinCpu()" + :maxCpu="'serviceofferingdetails' in selectedOffering ? selectedOffering.serviceofferingdetails.maxcpunumber*1 : Number.MAX_SAFE_INTEGER" + :minMemory="getMinMemory()" + :maxMemory="'serviceofferingdetails' in selectedOffering ? selectedOffering.serviceofferingdetails.maxmemory*1 : Number.MAX_SAFE_INTEGER" + @update-compute-cpunumber="updateFieldValue" + @update-compute-cpuspeed="updateFieldValue" + @update-compute-memory="updateFieldValue" /> + + <div :span="24" class="action-button"> + <a-button @click="closeAction">{{ this.$t('label.cancel') }}</a-button> + <a-button :loading="loading" type="primary" @click="handleSubmit">{{ this.$t('label.ok') }}</a-button> + </div> + </a-form> +</template> + +<script> +import { api } from '@/api' +import ComputeOfferingSelection from '@views/compute/wizard/ComputeOfferingSelection' +import ComputeSelection from '@views/compute/wizard/ComputeSelection' + +export default { + name: 'ScaleVM', + components: { + ComputeOfferingSelection, + ComputeSelection + }, + props: { + resource: { + type: Object, + required: true + } + }, + inject: ['parentFetchData'], + data () { + return { + offeringsMap: {}, + offerings: [], + selectedOffering: {}, + total: 0, + params: { id: this.resource.id }, + loading: false, + cpuNumberKey: 'details[0].cpuNumber', + cpuSpeedKey: 'details[0].cpuSpeed', + memoryKey: 'details[0].memory' + } + }, + mounted () { + this.fetchData({ + keyword: '', + pageSize: 10, + page: 1 + }) + }, + methods: { + fetchData (options) { + this.loading = true + this.total = 0 + this.offerings = [] + this.offeringsMap = [] + api('listServiceOfferings', { + virtualmachineid: this.resource.id, + keyword: options.keyword, + page: options.page, + pageSize: options.pageSize, + details: 'min', + response: 'json' + }).then(response => { + this.total = response.listserviceofferingsresponse.count + if (this.total === 0) { + return + } + this.offerings = response.listserviceofferingsresponse.serviceoffering + this.offerings.map(i => { this.offeringsMap[i.id] = i }) + }).finally(() => { + this.loading = false + }) + }, + getMinCpu () { + // We can only scale up while a VM is running + if (this.resource.state === 'Running') { + return this.resource.cpunumber + } + return 'serviceofferingdetails' in this.selectedOffering ? this.selectedOffering.serviceofferingdetails.mincpunumber * 1 : 1 + }, + getMinMemory () { + // We can only scale up while a VM is running + if (this.resource.state === 'Running') { + return this.resource.memory + } + return 'serviceofferingdetails' in this.selectedOffering ? this.selectedOffering.serviceofferingdetails.minmemory * 1 : 32 + }, + getMessage () { + if (this.resource.hypervisor === 'VMware') { + return this.$t('message.read.admin.guide.scaling.up') + } + return this.$t('message.change.offering.confirm') + }, + updateComputeOffering (id) { + this.params.serviceofferingid = id + this.selectedOffering = this.offeringsMap[id] + + // Delete custom details + delete this.params[this.cpuNumberKey] + delete this.params[this.cpuSpeedKey] + delete this.params[this.memoryKey] + + if (!this.selectedOffering.iscustomized) { + return + } + + // Set custom defaults if unconstrained + if (!this.selectedOffering.serviceofferingdetails) { + this.params[this.cpuNumberKey] = 1 + this.params[this.cpuSpeedKey] = 1 + this.params[this.memoryKey] = 32 // Min allowed by the backend is 32MB + return + } + + // Set min defaults + if (this.selectedOffering.serviceofferingdetails.mincpunumber) { + this.params[this.cpuNumberKey] = this.selectedOffering.serviceofferingdetails.mincpunumber + } + if (this.selectedOffering.serviceofferingdetails.mincpuspeed) { + this.params[this.cpuSpeedKey] = this.selectedOffering.serviceofferingdetails.mincpuspeed + } + if (this.selectedOffering.serviceofferingdetails.minmemory) { + this.params[this.memoryKey] = this.selectedOffering.serviceofferingdetails.minmemory + } + }, + updateFieldValue (name, value) { + this.params[name] = value + }, + closeAction () { + this.$emit('close-action') + }, + handleSubmit () { + this.loading = true + let apiName = 'scaleVirtualMachine' + if (this.resource.state === 'Stopped') { + apiName = 'changeServiceForVirtualMachine' + } + api(apiName, this.params).then(response => { + if (apiName === 'scaleVirtualMachine') { + const jobId = response.scalevirtualmachineresponse.jobid + if (jobId) { + this.$pollJob({ + jobId, + successMethod: result => { + this.$notification.success({ + message: 'Successfully changed offering' + }) + }, + loadingMessage: 'Scale in progress', + catchMessage: 'Error encountered while fetching async job result' + }) + } + } else { + this.$notification.success({ + message: 'Successfully changed offering' + }) + } + this.$parent.$parent.close() + this.parentFetchData() + }).catch(error => { + this.$notifyError(error) + this.$parent.$parent.close() + this.parentFetchData() + }).finally(() => { + this.loading = false + }) + } + } +} +</script> + +<style scoped lang="scss"> + +.form { + width: 90vw; + @media (min-width: 700px) { + width: 50vw; + } +} + +.action-button { + margin-top: 10px; + text-align: right; + + button { + margin-right: 5px; + } +} +</style> diff --git a/src/views/compute/wizard/ComputeOfferingSelection.vue b/src/views/compute/wizard/ComputeOfferingSelection.vue index 6d72af7..432fdb1 100644 --- a/src/views/compute/wizard/ComputeOfferingSelection.vue +++ b/src/views/compute/wizard/ComputeOfferingSelection.vue @@ -152,6 +152,9 @@ export default { }, loading () { if (!this.loading) { + if (!this.preFillContent) { + return + } if (this.preFillContent.computeofferingid) { this.selectedRowKeys = [this.preFillContent.computeofferingid] this.$emit('select-compute-item', this.preFillContent.computeofferingid) diff --git a/src/views/compute/wizard/ComputeSelection.vue b/src/views/compute/wizard/ComputeSelection.vue index 358099c..c70193f 100644 --- a/src/views/compute/wizard/ComputeSelection.vue +++ b/src/views/compute/wizard/ComputeSelection.vue @@ -170,6 +170,9 @@ export default { }, methods: { fillValue () { + if (!this.preFillContent) { + return + } if (this.preFillContent.cpunumber) { this.cpuNumberInputValue = this.preFillContent.cpunumber }