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 70760d5 src: assorted bug fixes (#594)
70760d5 is described below
commit 70760d557a05590b721436778ed988f91ba84ec3
Author: davidjumani <[email protected]>
AuthorDate: Fri Aug 21 17:51:51 2020 +0530
src: assorted bug fixes (#594)
Fixes:
#588
#589
#590
#591
#601
---
src/config/eventBus.js | 19 ++++++++++
src/config/section/compute.js | 10 ++++--
src/locales/en.json | 23 ++++++------
src/views/AutogenView.vue | 51 ++++++++++++++++-----------
src/views/compute/DeployVM.vue | 16 ++++++---
src/views/compute/wizard/ComputeSelection.vue | 20 ++++++-----
src/views/image/RegisterOrUploadIso.vue | 1 +
src/views/image/RegisterOrUploadTemplate.vue | 1 +
src/views/offering/AddComputeOffering.vue | 2 +-
9 files changed, 95 insertions(+), 48 deletions(-)
diff --git a/src/config/eventBus.js b/src/config/eventBus.js
new file mode 100644
index 0000000..ed61648
--- /dev/null
+++ b/src/config/eventBus.js
@@ -0,0 +1,19 @@
+// 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.
+
+import Vue from 'vue'
+export default new Vue()
diff --git a/src/config/section/compute.js b/src/config/section/compute.js
index 818f6bc..03d68b1 100644
--- a/src/config/section/compute.js
+++ b/src/config/section/compute.js
@@ -94,8 +94,11 @@ export default {
groupAction: true,
groupMap: (selection) => { return selection.map(x => { return { id:
x } }) },
show: (record) => { return ['Stopped'].includes(record.state) },
- args: (record, store) => {
+ args: (record, store, group) => {
var fields = []
+ if (group) {
+ return fields
+ }
if (store.userInfo.roletype === 'Admin') {
fields = ['podid', 'clusterid', 'hostid']
}
@@ -116,7 +119,7 @@ export default {
docHelp:
'adminguide/virtual_machines.html#stopping-and-starting-vms',
dataView: true,
groupAction: true,
- groupMap: (selection) => { return selection.map(x => { return { id:
x } }) },
+ groupMap: (selection, values) => { return selection.map(x => {
return { id: x, forced: values.forced } }) },
args: ['forced'],
show: (record) => { return ['Running'].includes(record.state) }
},
@@ -384,8 +387,9 @@ export default {
docHelp: 'adminguide/virtual_machines.html#deleting-vms',
dataView: true,
groupAction: true,
+ args: ['expunge'],
popup: true,
- groupMap: (selection) => { return selection.map(x => { return { id:
x, expunge: true } }) },
+ groupMap: (selection, values) => { return selection.map(x => {
return { id: x, expunge: values.expunge } }) },
show: (record) => { return ['Running', 'Stopped',
'Error'].includes(record.state) },
component: () => import('@/views/compute/DestoryVM.vue')
}
diff --git a/src/locales/en.json b/src/locales/en.json
index a400472..00dc048 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -612,11 +612,11 @@
"label.create.nfs.secondary.staging.store": "Create NFS secondary staging
store",
"label.create.project": "Create project",
"label.create.project.role": "Create Project Role",
-"label.create.user": "Create user",
"label.create.site.vpn.connection": "Create Site-to-Site VPN Connection",
"label.create.site.vpn.gateway": "Create Site-to-Site VPN Gateway",
"label.create.ssh.key.pair": "Create a SSH Key Pair",
"label.create.template": "Create template",
+"label.create.user": "Create user",
"label.create.vpn.connection": "Create VPN Connection",
"label.created": "Created",
"label.created.by.system": "Created by system",
@@ -635,6 +635,7 @@
"label.daily": "Daily",
"label.dashboard": "Dashboard",
"label.dashboard.endpoint": "Dashboard endpoint",
+"label.data.disk": "Data Disk",
"label.data.disk.offering": "Data Disk Offering",
"label.date": "Date",
"label.day": "Day",
@@ -699,9 +700,9 @@
"label.deleting.failed": "Deleting Failed",
"label.deleting.iso": "Deleting ISO",
"label.deleting.processing": "Deleting....",
+"label.deleting.template": "Deleting template",
"label.demote.project.owner": "Demote account to Regular role",
"label.demote.project.owner.user": "Demote user to Regular role",
-"label.deleting.template": "Deleting template",
"label.deny": "Deny",
"label.deployasis":"Deploy As-Is",
"label.deploymentplanner": "Deployment planner",
@@ -805,10 +806,10 @@
"label.edit.region": "Edit Region",
"label.edit.role": "Edit Role",
"label.edit.rule": "Edit rule",
-"label.edit.user": "Edit user",
"label.edit.secondary.ips": "Edit secondary IPs",
"label.edit.tags": "Edit tags",
"label.edit.traffic.type": "Edit traffic type",
+"label.edit.user": "Edit user",
"label.edit.vpc": "Edit VPC",
"label.egress": "Egress",
"label.egress.default.policy": "Egress Default Policy",
@@ -1004,6 +1005,7 @@
"label.hypervisortype": "Hypervisor",
"label.hypervisorversion": "Hypervisor Version",
"label.hypervnetworklabel": "HyperV Traffic Label",
+"label.i.accept.all.license.agreements": "I accept all license agreement",
"label.icmp": "ICMP",
"label.icmpcode": "ICMP Code",
"label.icmpcode.end.port": "ICMP Code / End Port",
@@ -1145,7 +1147,6 @@
"label.isvolatile": "Volatile",
"label.item.listing": "Item listing",
"label.items": "items",
-"label.i.accept.all.license.agreements": "I accept all license agreement",
"label.japanese.keyboard": "Japanese keyboard",
"label.keep": "Keep",
"label.keep.colon": "Keep:",
@@ -1290,6 +1291,7 @@
"label.memallocated": "Mem Allocation",
"label.memory": "Memory",
"label.memory.maximum.mb": "Max Memory (in MB)",
+"label.memory.mb": "Memory (in MB)",
"label.memory.total": "Memory Total",
"label.memory.used": "Memory Used",
"label.memoryallocated": "Memory Allocated",
@@ -1602,7 +1604,6 @@
"label.profiledn": "Associated Profile",
"label.profilename": "Profile",
"label.project": "Project",
-"label.projectname": "Project",
"label.project.dashboard": "Project dashboard",
"label.project.ids": "Project IDs",
"label.project.invitation": "Project Invitations",
@@ -1610,12 +1611,13 @@
"label.project.name": "Project name",
"label.project.owner": "Project Owner(s)",
"label.project.role": "Project Role",
-"label.project.roles": "Project Roles",
"label.project.role.permissions": "Project Role Permissions",
+"label.project.roles": "Project Roles",
"label.project.view": "Project View",
"label.projectaccountname": "Project Account Name",
"label.projectid": "Project ID",
"label.projectlimit": "Project Limits",
+"label.projectname": "Project",
"label.projects": "Projects",
"label.promiscuousmode": "Promiscuous Mode",
"label.property": "Property",
@@ -1690,9 +1692,9 @@
"label.rbdmonitor": "Ceph monitor",
"label.rbdpool": "Ceph pool",
"label.rbdsecret": "Cephx secret",
-"label.readonly": "Read-Only",
"label.read": "Read",
"label.read.io": "Read (IO)",
+"label.readonly": "Read-Only",
"label.reason": "Reason",
"label.reboot": "Reboot",
"label.receivedbytes": "Bytes Received",
@@ -2929,8 +2931,8 @@
"message.number.storage": "<h2><span> # of </span> Primary Storage
Volumes</h2>",
"message.number.zones": "<h2><span> # of </span> Zones</h2>",
"message.outofbandmanagement.action.maintenance": "Warning host is in
maintenance mode",
-"message.ovf.properties.available": "There are OVF properties available for
customizing the selected appliance. Please edit the values accordingly.",
"message.ovf.configurations": "OVF configurations available for the selected
appliance. Please select the desired value. Incompatible compute offerings will
get disbaled.",
+"message.ovf.properties.available": "There are OVF properties available for
customizing the selected appliance. Please edit the values accordingly.",
"message.password.has.been.reset.to": "Password has been reset to",
"message.password.of.the.vm.has.been.reset.to": "Password of the VM has been
reset to",
"message.pending.projects.1": "You have pending project invitations:",
@@ -3035,9 +3037,6 @@
"message.step.4.desc": "Please select the primary network that your virtual
instance will be connected to.",
"message.step.license.agreements.continue": "Please aceept all license
agreements to continue",
"message.storage.traffic": "Traffic between CloudStack's internal resources,
including any components that communicate with the Management Server, such as
hosts and CloudStack system VMs. Please configure storage traffic here.",
-"message.success.enable.saml.auth": "Successfully enabled SAML Authorization",
-"message.success.create.user": "Successfully created user",
-"message.success.update.user": "Successfully updated user",
"message.success.acquire.ip": "Successfully acquired IP",
"message.success.add.egress.rule": "Successfully added new Egress rule",
"message.success.add.firewall.rule": "Successfully added new Firewall rule",
@@ -3071,6 +3070,7 @@
"message.success.create.kubernetes.cluter": "Successfully created Kubernetes
cluster",
"message.success.create.l2.network": "Successfully created L2 network",
"message.success.create.snapshot.from.vmsnapshot": "Successfully created
Snapshot from VM snapshot",
+"message.success.create.user": "Successfully created user",
"message.success.create.volume": "Successfully created volume",
"message.success.delete": "Delete success",
"message.success.delete.acl.rule": "Successfully removed ACL rule",
@@ -3106,6 +3106,7 @@
"message.success.scale.kubernetes": "Successfully scaled Kubernetes cluster",
"message.success.update.ipaddress": "Successfully updated IP Address",
"message.success.update.kubeversion": "Successfully updated Kubernetes
supported version",
+"message.success.update.user": "Successfully updated user",
"message.success.upgrade.kubernetes": "Successfully upgraded Kubernetes
cluster",
"message.success.upload": "Upload Successfully",
"message.success.upload.description": "This ISO file has been uploaded. Please
check its status at Templates menu",
diff --git a/src/views/AutogenView.vue b/src/views/AutogenView.vue
index 4acf522..a00637f 100644
--- a/src/views/AutogenView.vue
+++ b/src/views/AutogenView.vue
@@ -70,7 +70,7 @@
:selectedRowKeys="selectedRowKeys"
:dataView="dataView"
:resource="resource"
- @exec-action="execAction"/>
+ @exec-action="(action) => execAction(action, action.groupAction &&
!dataView)"/>
<search-view
v-if="!dataView"
:searchFilters="searchFilters"
@@ -143,7 +143,6 @@
<a-form
:form="form"
@submit="handleSubmit"
- v-show="dataView || !currentAction.groupAction ||
this.selectedRowKeys.length === 0"
layout="vertical" >
<a-form-item
v-for="(field, fieldIndex) in currentAction.paramFields"
@@ -238,6 +237,7 @@
</span>
<span v-else-if="field.type==='long'">
<a-input-number
+ :autoFocus="fieldIndex === 0"
style="width: 100%;"
v-decorator="[field.name, {
rules: [{ required: field.required, message:
`${$t('message.validate.number')}` }]
@@ -273,6 +273,7 @@
</span>
<span v-else>
<a-input
+ :autoFocus="fieldIndex === 0"
v-decorator="[field.name, {
rules: [{ required: field.required, message:
`${$t('message.error.required.input')}` }]
}]"
@@ -326,6 +327,7 @@ import { api } from '@/api'
import { mixinDevice } from '@/utils/mixin.js'
import { genericCompare } from '@/utils/sort.js'
import store from '@/store'
+import eventBus from '@/config/eventBus'
import Breadcrumb from '@/components/widgets/Breadcrumb'
import ChartCard from '@/components/widgets/ChartCard'
@@ -387,6 +389,9 @@ export default {
beforeCreate () {
this.form = this.$form.createForm(this)
},
+ created () {
+ eventBus.$on('refresh-data', this.fetchData)
+ },
mounted () {
if (this.device === 'desktop') {
this.pageSize = 20
@@ -647,7 +652,7 @@ export default {
onRowSelectionChange (selection) {
this.selectedRowKeys = selection
},
- execAction (action) {
+ execAction (action, isGroupAction) {
const self = this
this.form = this.$form.createForm(this)
this.formModel = {}
@@ -672,7 +677,7 @@ export default {
if ('args' in action) {
var args = action.args
if (typeof action.args === 'function') {
- args = action.args(action.resource, this.$store.getters)
+ args = action.args(action.resource, this.$store.getters,
isGroupAction)
}
if (args.length > 0) {
this.currentAction.paramFields = args.map(function (arg) {
@@ -814,24 +819,28 @@ export default {
},
handleSubmit (e) {
if (!this.dataView && this.currentAction.groupAction &&
this.selectedRowKeys.length > 0) {
- const paramsList = this.currentAction.groupMap(this.selectedRowKeys)
- this.actionLoading = true
- for (const params of paramsList) {
- api(this.currentAction.api, params).then(json => {
- }).catch(error => {
- this.$notifyError(error)
- })
- }
- this.$message.info({
- content: this.$t(this.currentAction.label),
- key: this.currentAction.label,
- duration: 3
+ this.form.validateFields((err, values) => {
+ if (!err) {
+ const paramsList =
this.currentAction.groupMap(this.selectedRowKeys, values)
+ this.actionLoading = true
+ for (const params of paramsList) {
+ api(this.currentAction.api, params).then(json => {
+ }).catch(error => {
+ this.$notifyError(error)
+ })
+ }
+ this.$message.info({
+ content: this.$t(this.currentAction.label),
+ key: this.currentAction.label,
+ duration: 3
+ })
+ setTimeout(() => {
+ this.actionLoading = false
+ this.closeAction()
+ this.fetchData()
+ }, 2000)
+ }
})
- setTimeout(() => {
- this.actionLoading = false
- this.closeAction()
- this.fetchData()
- }, 2000)
} else {
this.execSubmit(e)
}
diff --git a/src/views/compute/DeployVM.vue b/src/views/compute/DeployVM.vue
index 18f90a4..35ea64c 100644
--- a/src/views/compute/DeployVM.vue
+++ b/src/views/compute/DeployVM.vue
@@ -193,7 +193,7 @@
:isConstrained="'serviceofferingdetails' in
serviceOffering"
:minCpu="'serviceofferingdetails' in serviceOffering ?
serviceOffering.serviceofferingdetails.mincpunumber*1 : 1"
:maxCpu="'serviceofferingdetails' in serviceOffering ?
serviceOffering.serviceofferingdetails.maxcpunumber*1 : Number.MAX_SAFE_INTEGER"
- :minMemory="'serviceofferingdetails' in serviceOffering
? serviceOffering.serviceofferingdetails.minmemory*1 : 1"
+ :minMemory="'serviceofferingdetails' in serviceOffering
? serviceOffering.serviceofferingdetails.minmemory*1 : 0"
:maxMemory="'serviceofferingdetails' in serviceOffering
? serviceOffering.serviceofferingdetails.maxmemory*1 : Number.MAX_SAFE_INTEGER"
@update-compute-cpunumber="updateFieldValue"
@update-compute-cpuspeed="updateFieldValue"
@@ -215,7 +215,7 @@
</template>
</a-step>
<a-step
- :title="this.$t('label.diskofferingid')"
+ :title="tabKey == 'templateid' ? $t('label.data.disk') :
$t('label.disk.size')"
:status="zoneSelected ? 'process' : 'wait'">
<template slot="description">
<div v-if="zoneSelected">
@@ -543,6 +543,7 @@ import { api } from '@/api'
import _ from 'lodash'
import { mixin, mixinDevice } from '@/utils/mixin.js'
import store from '@/store'
+import eventBus from '@/config/eventBus'
import InfoCard from '@/components/view/InfoCard'
import ComputeOfferingSelection from
'@views/compute/wizard/ComputeOfferingSelection'
@@ -1289,7 +1290,7 @@ export default {
}
// step 3: select service offering
deployVmData.serviceofferingid = values.computeofferingid
- if (values.cpunumber || values.cpuspeed || values.memory) {
+ if (this.serviceOffering && this.serviceOffering.iscustomized) {
if (values.cpunumber) {
deployVmData['details[0].cpuNumber'] = values.cpunumber
}
@@ -1383,9 +1384,16 @@ export default {
duration: 0
})
}
+ eventBus.$emit('refresh-data')
+ },
+ errorMethod: () => {
+ eventBus.$emit('refresh-data')
},
loadingMessage: `${title} ${this.$t('label.in.progress')}`,
- catchMessage: this.$t('error.fetching.async.job.result')
+ catchMessage: this.$t('error.fetching.async.job.result'),
+ catchMethod: () => {
+ eventBus.$emit('refresh-data')
+ }
})
this.$store.dispatch('AddAsyncJob', {
title: title,
diff --git a/src/views/compute/wizard/ComputeSelection.vue
b/src/views/compute/wizard/ComputeSelection.vue
index bd5ee02..2b40268 100644
--- a/src/views/compute/wizard/ComputeSelection.vue
+++ b/src/views/compute/wizard/ComputeSelection.vue
@@ -56,7 +56,7 @@
</a-col>
<a-col :md="colContraned" :lg="colContraned">
<a-form-item
- :label="this.$t('label.memory')"
+ :label="this.$t('label.memory.mb')"
:validate-status="errors.memory.status"
:help="errors.memory.message">
<a-row :gutter="12">
@@ -71,8 +71,6 @@
<a-col :md="4" :lg="4">
<a-input-number
v-model="memoryInputValue"
- :formatter="value => `${value} MB`"
- :parser="value => value.replace(' MB', '')"
@change="($event) => updateComputeMemory($event)"
/>
</a-col>
@@ -106,7 +104,7 @@ export default {
},
minMemory: {
type: Number,
- default: 1
+ default: 0
},
maxMemory: {
type: Number,
@@ -158,19 +156,22 @@ export default {
watch: {
computeOfferingId (newValue, oldValue) {
if (newValue !== oldValue) {
- this.cpuNumberInputValue = this.minCpu
- this.memoryInputValue = this.minMemory
+ this.fillValue()
}
}
},
mounted () {
- this.cpuNumberInputValue = this.minCpu
- this.memoryInputValue = this.minMemory
this.fillValue()
},
methods: {
fillValue () {
+ this.cpuNumberInputValue = this.minCpu
+ this.memoryInputValue = this.minMemory
+
if (!this.preFillContent) {
+ this.updateComputeCpuNumber(this.cpuNumberInputValue)
+ this.updateComputeCpuSpeed(this.cpuSpeedInputValue)
+ this.updateComputeMemory(this.memoryInputValue)
return
}
if (this.preFillContent.cpunumber) {
@@ -182,6 +183,9 @@ export default {
if (this.preFillContent.memory) {
this.memoryInputValue = this.preFillContent.memory
}
+ this.updateComputeCpuNumber(this.preFillContent.cpunumber ||
this.cpuNumberInputValue)
+ this.updateComputeCpuSpeed(this.preFillContent.cpuspeed ||
this.cpuSpeedInputValue)
+ this.updateComputeMemory(this.preFillContent.memory ||
this.memoryInputValue)
},
updateComputeCpuNumber (value) {
if (!this.validateInput('cpu', value)) {
diff --git a/src/views/image/RegisterOrUploadIso.vue
b/src/views/image/RegisterOrUploadIso.vue
index f632fc6..501d528 100644
--- a/src/views/image/RegisterOrUploadIso.vue
+++ b/src/views/image/RegisterOrUploadIso.vue
@@ -29,6 +29,7 @@
layout="vertical">
<a-form-item v-if="currentForm === 'Create'" :label="$t('label.url')">
<a-input
+ autoFocus
v-decorator="['url', {
rules: [{ required: true, message:
`${this.$t('label.upload.iso.from.local')}` }]
}]"
diff --git a/src/views/image/RegisterOrUploadTemplate.vue
b/src/views/image/RegisterOrUploadTemplate.vue
index 65c8bb9..19d85fc 100644
--- a/src/views/image/RegisterOrUploadTemplate.vue
+++ b/src/views/image/RegisterOrUploadTemplate.vue
@@ -31,6 +31,7 @@
<a-row :gutter="12">
<a-form-item :label="$t('label.url')">
<a-input
+ autoFocus
v-decorator="['url', {
rules: [{ required: true, message:
`${this.$t('message.error.required.input')}` }]
}]"
diff --git a/src/views/offering/AddComputeOffering.vue
b/src/views/offering/AddComputeOffering.vue
index 80b7c41..3178460 100644
--- a/src/views/offering/AddComputeOffering.vue
+++ b/src/views/offering/AddComputeOffering.vue
@@ -247,7 +247,7 @@
</a-form-item>
<a-form-item v-if="this.offeringType === 'fixed'">
<span slot="label">
- {{ $t('label.memory') }}
+ {{ $t('label.memory.mb') }}
<a-tooltip :title="apiParams.memory.description">
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
</a-tooltip>