You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ro...@apache.org on 2019/12/14 15:29:04 UTC
[cloudstack-primate] branch master updated: compute: VM assign to
other account/project/domain (#69)
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 b384cd4 compute: VM assign to other account/project/domain (#69)
b384cd4 is described below
commit b384cd4b5a298d5b958f0bb2631ff0d2d0dd6901
Author: Ritchie Vincent <rf...@gmail.com>
AuthorDate: Sat Dec 14 15:28:56 2019 +0000
compute: VM assign to other account/project/domain (#69)
Custom form to assign a VM to either an account or a project.
Signed-off-by: Rohit Yadav <ro...@shapeblue.com>
---
src/config/section/compute.js | 2 +
src/locales/en.json | 3 +
src/utils/request.js | 4 +-
src/views/AutogenView.vue | 9 +-
src/views/compute/AssignInstance.vue | 274 +++++++++++++++++++++++++++++++++++
5 files changed, 288 insertions(+), 4 deletions(-)
diff --git a/src/config/section/compute.js b/src/config/section/compute.js
index a4241a2..51a7ffc 100644
--- a/src/config/section/compute.js
+++ b/src/config/section/compute.js
@@ -241,6 +241,8 @@ export default {
icon: 'user-add',
label: 'Assign Instance to Another Account',
dataView: true,
+ component: () => import('@/views/compute/AssignInstance'),
+ popup: true,
show: (record) => { return ['Stopped'].includes(record.state) },
args: ['virtualmachineid', 'account', 'domainid'],
mapping: {
diff --git a/src/locales/en.json b/src/locales/en.json
index ec0282e..d330ce2 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -631,6 +631,7 @@
"memoryusedgb": "Used",
"memused": "Memory Usage",
"message.edit.account": "Edit (\"-1\" indicates no limit to the amount of resources create)",
+"message.assign.instance.another": "Please specify the account type, domain, account name and network (optional) of the new account. <br> If the default nic of the vm is on a shared network, CloudStack will check if the network can be used by the new account if you do not specify one network. <br> If the default nic of the vm is on a isolated network, and the new account has more one isolated networks, you should specify one.",
"minCPUNumber": "Min CPU Cores",
"minInstance": "Min Instances",
"minIops": "Min IOPS",
@@ -754,6 +755,7 @@
"redundantvpcrouter": "Redundant VPC",
"reenterpassword": "Re-enter Password",
"relationaloperator": "Operator",
+"required": "Required",
"requireshvm": "HVM",
"requiresupgrade": "Requires Upgrade",
"reservedSystemEndIp": "End Reserved system IP",
@@ -836,6 +838,7 @@
"storagepolicy": "Storage policy",
"storagetype": "Storage Type",
"subdomainaccess": "Subdomain Access",
+"submit": "Submit",
"supportedServices": "Supported Services",
"supportspublicaccess": "Supports Public Access",
"supportsregionLevelvpc": "Supports Region Level VPC",
diff --git a/src/utils/request.js b/src/utils/request.js
index c38e7f4..235793a 100644
--- a/src/utils/request.js
+++ b/src/utils/request.js
@@ -57,10 +57,10 @@ const err = (error) => {
// request interceptor
service.interceptors.request.use(config => {
- const project = Vue.ls.get(CURRENT_PROJECT)
if (config && config.params) {
config.params.response = 'json'
- if (project && project.id) {
+ const project = Vue.ls.get(CURRENT_PROJECT)
+ if (!config.params.projectid && project && project.id) {
config.params.projectid = project.id
}
}
diff --git a/src/views/AutogenView.vue b/src/views/AutogenView.vue
index 0050239..1e57073 100644
--- a/src/views/AutogenView.vue
+++ b/src/views/AutogenView.vue
@@ -19,10 +19,10 @@
<div>
<a-card class="breadcrumb-card">
<a-row>
- <a-col :span="14">
+ <a-col :span="12">
<breadcrumb style="padding-top: 6px" />
</a-col>
- <a-col :span="10">
+ <a-col :span="12">
<span style="float: right">
<a-tooltip placement="bottom">
<template slot="title">
@@ -263,6 +263,11 @@ export default {
Status
},
mixins: [mixinDevice],
+ provide: function () {
+ return {
+ parentFetchData: this.fetchData
+ }
+ },
data () {
return {
apiName: '',
diff --git a/src/views/compute/AssignInstance.vue b/src/views/compute/AssignInstance.vue
new file mode 100644
index 0000000..3945e90
--- /dev/null
+++ b/src/views/compute/AssignInstance.vue
@@ -0,0 +1,274 @@
+// 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>
+ <div>
+ <p v-html="$t('message.assign.instance.another')"></p>
+
+ <div class="form">
+
+ <div v-if="loading" class="loading">
+ <a-icon type="loading" style="color: #1890ff;"></a-icon>
+ </div>
+
+ <div class="form__item">
+ <p class="form__label">{{ $t('accounttype') }}</p>
+ <a-select v-model="selectedAccountType" defaultValue="account">
+ <a-select-option :value="$t('account')">{{ $t('account') }}</a-select-option>
+ <a-select-option :value="$t('project')">{{ $t('project') }}</a-select-option>
+ </a-select>
+ </div>
+
+ <div class="form__item">
+ <p class="form__label"><span class="required">*</span>{{ $t('domain') }}</p>
+ <a-select @change="changeDomain" v-model="selectedDomain" :defaultValue="selectedDomain">
+ <a-select-option v-for="domain in domains" :key="domain.name" :value="domain.id">
+ {{ domain.path }}
+ </a-select-option>
+ </a-select>
+ </div>
+
+ <template v-if="selectedAccountType === 'Account'">
+ <div class="form__item">
+ <p class="form__label"><span class="required">*</span>{{ $t('account') }}</p>
+ <a-select @change="changeAccount" v-model="selectedAccount">
+ <a-select-option v-for="account in accounts" :key="account.name" :value="account.name">
+ {{ account.name }}
+ </a-select-option>
+ </a-select>
+ <span v-if="accountError" class="required">{{ $t('required') }}</span>
+ </div>
+ </template>
+
+ <template v-else>
+ <div class="form__item">
+ <p class="form__label"><span class="required">*</span>{{ $t('project') }}</p>
+ <a-select @change="changeProject" v-model="selectedProject">
+ <a-select-option v-for="project in projects" :key="project.id" :value="project.id">
+ {{ project.name }}
+ </a-select-option>
+ </a-select>
+ <span v-if="projectError" class="required">{{ $t('required') }}</span>
+ </div>
+ </template>
+
+ <div class="form__item">
+ <p class="form__label">{{ $t('network') }}</p>
+ <a-select v-model="selectedNetwork">
+ <a-select-option v-for="network in networks" :key="network.id" :value="network.id">
+ {{ network.name ? network.name : '-' }}
+ </a-select-option>
+ </a-select>
+ </div>
+
+ <a-button type="primary" class="submit-btn" @click="submitData">
+ {{ $t('submit') }}
+ </a-button>
+
+ </div>
+
+ </div>
+</template>
+
+<script>
+import { api } from '@/api'
+
+export default {
+ name: 'AssignInstance',
+ props: {
+ resource: {
+ type: Object,
+ required: true
+ }
+ },
+ inject: ['parentFetchData'],
+ data () {
+ return {
+ domains: [],
+ accounts: [],
+ projects: [],
+ networks: [],
+ selectedAccountType: 'Account',
+ selectedDomain: null,
+ selectedAccount: null,
+ selectedProject: null,
+ selectedNetwork: null,
+ accountError: false,
+ projectError: false,
+ loading: false
+ }
+ },
+ mounted () {
+ this.fetchData()
+ },
+ methods: {
+ fetchData () {
+ this.loading = true
+ api('listDomains', {
+ response: 'json',
+ listAll: true,
+ details: 'min'
+ }).then(response => {
+ this.domains = response.listdomainsresponse.domain
+ this.selectedDomain = this.domains[0].id
+ this.fetchAccounts()
+ this.fetchProjects()
+ })
+ },
+ fetchAccounts () {
+ this.loading = true
+ api('listAccounts', {
+ response: 'json',
+ domainId: this.selectedDomain,
+ state: 'Enabled',
+ listAll: true
+ }).then(response => {
+ this.accounts = response.listaccountsresponse.account
+ this.loading = false
+ })
+ },
+ fetchProjects () {
+ this.loading = true
+ api('listProjects', {
+ response: 'json',
+ domainId: this.selectedDomain,
+ state: 'Active',
+ details: 'min',
+ listAll: true
+ }).then(response => {
+ this.projects = response.listprojectsresponse.project
+ this.loading = false
+ })
+ },
+ fetchNetworks () {
+ this.loading = true
+ api('listNetworks', {
+ response: 'json',
+ domainId: this.selectedDomain,
+ listAll: true,
+ isrecursive: false,
+ account: this.selectedAccount,
+ projectid: this.selectedProject
+ }).then(response => {
+ this.networks = response.listnetworksresponse.network
+ this.loading = false
+ })
+ },
+ changeDomain () {
+ this.selectedAccount = null
+ this.fetchAccounts()
+ this.fetchProjects()
+ },
+ changeAccount () {
+ this.selectedProject = null
+ this.fetchNetworks()
+ },
+ changeProject () {
+ this.selectedAccount = null
+ this.fetchNetworks()
+ },
+ submitData () {
+ let variableKey = ''
+ let variableValue = ''
+
+ if (this.selectedAccountType === 'Account') {
+ if (!this.selectedAccount) {
+ this.accountError = true
+ return
+ }
+ variableKey = 'account'
+ variableValue = this.selectedAccount
+ } else if (this.selectedAccountType === 'Project') {
+ if (!this.selectedProject) {
+ this.projectError = true
+ return
+ }
+ variableKey = 'projectid'
+ variableValue = this.selectedProject
+ }
+
+ this.loading = true
+ api('assignVirtualMachine', {
+ response: 'json',
+ virtualmachineid: this.resource.id,
+ domainid: this.selectedDomain,
+ [variableKey]: variableValue,
+ networkids: this.selectedNetwork
+ }).then(response => {
+ this.$notification.success({
+ message: 'Successfully assigned instance'
+ })
+ this.loading = false
+ this.$parent.$parent.close()
+ this.parentFetchData()
+ }).catch(error => {
+ this.$notification.error({
+ message: 'Failed to assign instance',
+ description: error.response.data.assignvirtualmachineresponse.errortext && error.response.data.assignvirtualmachineresponse.errortext
+ })
+ this.$parent.$parent.close()
+ this.parentFetchData()
+ })
+ }
+ }
+}
+</script>
+
+<style scoped lang="scss">
+ .form {
+ display: flex;
+ flex-direction: column;
+
+ &__item {
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ margin-bottom: 10px;
+ }
+
+ &__label {
+ display: flex;
+ font-weight: bold;
+ margin-bottom: 5px;
+ }
+
+ }
+
+ .submit-btn {
+ margin-top: 10px;
+ align-self: flex-end;
+ }
+
+ .required {
+ margin-right: 2px;
+ color: red;
+ font-size: 0.7rem;
+ }
+
+ .loading {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 3rem;
+ }
+</style>