src: assorted bug fixes (#594)

Fixes:
#588
#589
#590
#591
#601
Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
davidjumani 2020-08-21 17:51:51 +05:30 committed by Rohit Yadav
parent 76432c328d
commit 58dddc24d8
9 changed files with 95 additions and 48 deletions

19
ui/src/config/eventBus.js Normal file
View File

@ -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()

View File

@ -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')
}

View File

@ -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",

View File

@ -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)
}

View File

@ -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,

View File

@ -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)) {

View File

@ -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')}` }]
}]"

View File

@ -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')}` }]
}]"

View File

@ -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>