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 cb2be30 infraa: add secondary storage form (#121) cb2be30 is described below commit cb2be303e25085623e8b19b2dbfe22c8c70bff10 Author: Pearl Dsilva <pearl1...@gmail.com> AuthorDate: Wed Jan 22 14:11:50 2020 +0530 infraa: add secondary storage form (#121) This implements the add secondary storage form Signed-off-by: Rohit Yadav <rohit.ya...@shapeblue.com> Co-authored-by: Rohit Yadav <ro...@apache.org> --- src/config/section/infra/secondaryStorages.js | 3 +- src/views/infra/AddSecondaryStorage.vue | 314 ++++++++++++++++++++++++++ 2 files changed, 316 insertions(+), 1 deletion(-) diff --git a/src/config/section/infra/secondaryStorages.js b/src/config/section/infra/secondaryStorages.js index 0deea35..ffd8245 100644 --- a/src/config/section/infra/secondaryStorages.js +++ b/src/config/section/infra/secondaryStorages.js @@ -35,7 +35,8 @@ export default { icon: 'plus', label: 'label.add.secondary.storage', listView: true, - args: ['name', 'provider', 'zoneid', 'url', 'details'] + popup: true, + component: () => import('@/views/infra/AddSecondaryStorage.vue') }, { api: 'deleteImageStore', diff --git a/src/views/infra/AddSecondaryStorage.vue b/src/views/infra/AddSecondaryStorage.vue new file mode 100644 index 0000000..6a97dd6 --- /dev/null +++ b/src/views/infra/AddSecondaryStorage.vue @@ -0,0 +1,314 @@ +// 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 class="form-layout"> + <a-spin :spinning="loading"> + <a-form :form="form" layout="vertical"> + <a-form-item :label="$t('name')"> + <a-input v-decorator="['name']" /> + </a-form-item> + <a-form-item :label="$t('providername')"> + <a-select + v-decorator="[ + 'provider', + { + initialValue: 'NFS' + }]" + @change="val => { this.provider = val }" + > + <a-select-option + :value="prov" + v-for="(prov,idx) in providers" + :key="idx" + >{{ prov }}</a-select-option> + </a-select> + </a-form-item> + <div v-if="provider !== 'Swift'"> + <a-form-item :label="$t('zone')"> + <a-select + v-decorator="[ + 'zone', + { + initialValue: this.zoneSelected, + rules: [{ required: true, message: 'required'}] + }]" + > + <a-select-option + :value="zone.id" + v-for="(zone) in zones" + :key="zone.id" + >{{ zone.name }}</a-select-option> + </a-select> + </a-form-item> + <a-form-item :label="$t('server')"> + <a-input + v-decorator="[ + 'server', + { + rules: [{ required: true, message: 'required' }] + }]" + /> + </a-form-item> + <a-form-item :label="$t('path')"> + <a-input + v-decorator="[ + 'path', + { + rules: [{ required: true, message: 'required' }] + }]" + /> + </a-form-item> + </div> + <div v-if="provider === 'SMB/CIFS'"> + <a-form-item :label="$t('smbUsername')"> + <a-input + v-decorator="[ + 'smbUsername', + { + rules: [{ required: true, message: 'required' }] + }]" + /> + </a-form-item> + <a-form-item :label="$t('smbPassword')"> + <a-input-password + v-decorator="[ + 'smbPassword', + { + rules: [{ required: true, message: 'required' }] + }]" + /> + </a-form-item> + <a-form-item :label="$t('smbDomain')"> + <a-input + v-decorator="[ + 'smbDomain', + { + rules: [{ required: true, message: 'required' }] + }]" + /> + </a-form-item> + </div> + <div v-if="provider === 'Swift'"> + <a-form-item :label="$t('url')"> + <a-input + v-decorator="[ + 'url', + { + rules: [{ required: true, message: 'required' }] + }]" + /> + </a-form-item> + <a-form-item :label="$t('account')"> + <a-input + v-decorator="[ + 'account', + { + rules: [{ required: true, message: 'required' }] + }]" + /> + </a-form-item> + <a-form-item :label="$t('username')"> + <a-input + v-decorator="[ + 'username', + { + rules: [{ required: true, message: 'required' }] + }]" + /> + </a-form-item> + <a-form-item :label="$t('key')"> + <a-input + v-decorator="[ + 'key', + { + rules: [{ required: true, message: 'required' }] + }]" + /> + </a-form-item> + <a-form-item :label="$t('storagepolicy')"> + <a-input + v-decorator="[ + 'storagepolicy' + ]" + /> + </a-form-item> + </div> + <div class="actions"> + <a-button @click="closeModal">{{ $t('Cancel') }}</a-button> + <a-button type="primary" @click="handleSubmit">{{ $t('OK') }}</a-button> + </div> + </a-form> + </a-spin> + </div> +</template> +<script> +import { api } from '@/api' + +export default { + name: 'AddSecondryStorage', + props: { + resource: { + type: Object, + required: true + } + }, + inject: ['parentFetchData'], + data () { + return { + providers: ['NFS', 'SMB/CIFS', 'Swift'], + provider: '', + zones: [], + zoneSelected: '', + loading: false + } + }, + beforeCreate () { + this.form = this.$form.createForm(this) + }, + mounted () { + this.fetchData() + }, + methods: { + fetchData () { + this.listZones() + }, + closeModal () { + this.$parent.$parent.close() + }, + listZones () { + api('listZones').then(json => { + if (json && json.listzonesresponse && json.listzonesresponse.zone) { + this.zones = json.listzonesresponse.zone + if (this.zones.length > 0) { + this.zoneSelected = this.zones[0].name + } + } + }) + }, + nfsURL (server, path) { + var url + if (path.substring(0, 1) !== '/') { + path = '/' + path + } + if (server.indexOf('://') === -1) { + url = 'nfs://' + server + path + } else { + url = server + path + } + return url + }, + smbURL (server, path, smbUsername, smbPassword, smbDomain) { + var url = '' + if (path.substring(0, 1) !== '/') { + path = '/' + path + } + if (server.indexOf('://') === -1) { + url += 'cifs://' + } + url += (server + path) + return url + }, + handleSubmit (e) { + e.preventDefault() + this.form.validateFields((err, values) => { + if (err) { + return + } + + var data = { + name: values.name + } + var url = '' + var provider = values.provider + if (provider === 'NFS') { + url = this.nfsURL(values.server, values.path) + } + if (provider === 'SMB/CIFS') { + provider = 'SMB' + url = this.smbURL(values.server, values.path, values.smbUsername, values.smbPassword, values.smbDomain) + const smbParams = { + user: values.smbUsername, + password: values.smbPassword, + domain: values.smbDomain + } + Object.keys(smbParams).forEach((key, index) => { + data['details[' + index.toString() + '].key'] = key + data['details[' + index.toString() + '].value'] = smbParams[key] + }) + } + if (provider === 'Swift') { + url = values.url + const swiftParams = { + account: values.account, + username: values.username, + key: values.key, + storagepolicy: values.storagepolicy + } + Object.keys(swiftParams).forEach((key, index) => { + data['details[' + index.toString() + '].key'] = key + data['details[' + index.toString() + '].value'] = swiftParams[key] + }) + } + + data.url = url + data.provider = provider + if (values.zone && provider !== 'Swift') { + data.zoneid = values.zone + } + + this.loading = true + api('addImageStore', data).then(json => { + this.$notification.success({ + message: this.$t('label.add.secondary.storage'), + description: this.$t('label.add.secondary.storage') + }) + }).catch(error => { + this.$notification.error({ + message: 'Request Failed', + description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message + }) + }).finally(() => { + this.loading = false + this.closeModal() + this.parentFetchData() + }) + }) + } + } +} +</script> +<style lang="scss" scoped> +.form-layout { + width: 85vw; + + @media (min-width: 1000px) { + width: 35vw; + } +} + +.actions { + display: flex; + justify-content: flex-end; + margin-top: 20px; + button { + &:not(:last-child) { + margin-right: 10px; + } + } +} +</style>