From 0f926b5d68975e93f924e41ae6f4b137868f58c1 Mon Sep 17 00:00:00 2001 From: Hoang Nguyen Date: Mon, 10 Jan 2022 20:31:53 +0700 Subject: [PATCH] UI: Add s3 provider option to create secondary storage (#5726) * add s3 provider option to create secondary storage * fixes label name * add storagepolicy for swift provider --- ui/public/locales/en.json | 3 + ui/src/views/infra/AddSecondaryStorage.vue | 178 +++++++++++++++++- ui/src/views/infra/zone/StaticInputsForm.vue | 24 ++- .../infra/zone/ZoneWizardAddResources.vue | 33 +++- .../views/infra/zone/ZoneWizardLaunchZone.vue | 6 + 5 files changed, 212 insertions(+), 32 deletions(-) diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 9dbbd854a1d..ad017345221 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -2949,6 +2949,9 @@ "message.error.retrieve.kubeconfig": "Unable to retrieve Kubernetes cluster config", "message.error.s3nfs.path": "Please enter S3 NFS Path", "message.error.s3nfs.server": "Please enter S3 NFS Server", +"message.error.swift.account": "Please enter account", +"message.error.swift.key": "Please enter key", +"message.error.swift.username": "Please enter username", "message.error.save.setting": "There was an error saving this setting.", "message.error.sbdomain": "Please enter SMB Domain", "message.error.sbdomain.password": "Please enter SMB Domain Password", diff --git a/ui/src/views/infra/AddSecondaryStorage.vue b/ui/src/views/infra/AddSecondaryStorage.vue index 0d34e6f4575..f7b6203a84e 100644 --- a/ui/src/views/infra/AddSecondaryStorage.vue +++ b/ui/src/views/infra/AddSecondaryStorage.vue @@ -42,7 +42,7 @@ >{{ prov }} -
+
+ + + + + + + {{ zone.name }} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
{{ $t('label.cancel') }} {{ $t('label.ok') }} @@ -189,11 +274,12 @@ export default { inject: ['parentFetchData'], data () { return { - providers: ['NFS', 'SMB/CIFS', 'Swift'], + providers: ['NFS', 'SMB/CIFS', 'S3', 'Swift'], provider: '', zones: [], zoneSelected: '', - loading: false + loading: false, + secondaryStorageNFSStaging: false } }, beforeCreate () { @@ -245,7 +331,7 @@ export default { handleSubmit (e) { e.preventDefault() if (this.loading) return - this.form.validateFieldsAndScroll((err, values) => { + this.form.validateFieldsAndScroll(async (err, values) => { if (err) { return } @@ -283,26 +369,100 @@ export default { data['details[' + index.toString() + '].key'] = key data['details[' + index.toString() + '].value'] = swiftParams[key] }) + } else if (provider === 'S3') { + let detailIdx = 0 + const s3Params = { + accesskey: values.secondaryStorageAccessKey, + secretkey: values.secondaryStorageSecretKey, + bucket: values.secondaryStorageBucket, + usehttps: values.secondaryStorageHttps ? values.secondaryStorageHttps : false + } + Object.keys(s3Params).forEach((key, index) => { + data['details[' + index.toString() + '].key'] = key + data['details[' + index.toString() + '].value'] = s3Params[key] + detailIdx = index + }) + + if (values.secondaryStorageEndpoint && values.secondaryStorageEndpoint.length > 0) { + detailIdx++ + data['details[' + detailIdx.toString() + '].key'] = 'endpoint' + data['details[' + detailIdx.toString() + '].value'] = values.secondaryStorageEndpoint + } + + if (values.secondaryStorageConnectionTimeout && values.secondaryStorageConnectionTimeout.length > 0) { + detailIdx++ + data['details[' + detailIdx.toString() + '].key'] = 'connectiontimeout' + data['details[' + detailIdx.toString() + '].value'] = values.secondaryStorageConnectionTimeout + } + + if (values.secondaryStorageMaxError && values.secondaryStorageMaxError.length > 0) { + detailIdx++ + data['details[' + detailIdx.toString() + '].key'] = 'maxerrorretry' + data['details[' + detailIdx.toString() + '].value'] = values.secondaryStorageMaxError + } + + if (values.secondaryStorageSocketTimeout && values.secondaryStorageSocketTimeout.length > 0) { + detailIdx++ + data['details[' + detailIdx.toString() + '].key'] = 'sockettimeout' + data['details[' + detailIdx.toString() + '].value'] = values.secondaryStorageSocketTimeout + } } - data.url = url + if (provider !== 'S3') { + data.url = url + } data.provider = provider - if (values.zone && provider !== 'Swift') { + if (values.zone && !['Swift', 'S3'].includes(provider)) { data.zoneid = values.zone } + const nfsParams = {} + if (values.secondaryStorageNFSStaging) { + const nfsServer = values.secondaryStorageNFSServer + const path = values.secondaryStorageNFSPath + const nfsUrl = this.nfsURL(nfsServer, path) + + nfsParams.provider = 'nfs' + nfsParams.zoneid = values.zone + nfsParams.url = nfsUrl + } + this.loading = true - api('addImageStore', data).then(json => { + + try { + await this.addImageStore(data) + + if (values.secondaryStorageNFSStaging) { + await this.createSecondaryStagingStore(nfsParams) + } this.$notification.success({ message: this.$t('label.add.secondary.storage'), description: this.$t('label.add.secondary.storage') }) + this.loading = false this.closeModal() this.parentFetchData() - }).catch(error => { + } catch (error) { this.$notifyError(error) - }).finally(() => { this.loading = false + } + }) + }, + addImageStore (params) { + return new Promise((resolve, reject) => { + api('addImageStore', params).then(json => { + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + createSecondaryStagingStore (params) { + return new Promise((resolve, reject) => { + api('createSecondaryStagingStore', params).then(json => { + resolve() + }).catch(error => { + reject(error) }) }) } diff --git a/ui/src/views/infra/zone/StaticInputsForm.vue b/ui/src/views/infra/zone/StaticInputsForm.vue index 97590a320ab..dc93c090701 100644 --- a/ui/src/views/infra/zone/StaticInputsForm.vue +++ b/ui/src/views/infra/zone/StaticInputsForm.vue @@ -216,21 +216,19 @@ export default { if (!conditions || Object.keys(conditions).length === 0) { return true } - let isShow = false + let isShow = true Object.keys(conditions).forEach(key => { - const condition = conditions[key] - const fieldVal = this.form.getFieldValue(key) - ? this.form.getFieldValue(key) - : (this.prefillContent[key] ? this.prefillContent[key].value : null) - if (Array.isArray(condition) && condition.includes(fieldVal)) { - isShow = true - return false - } else if (!Array.isArray(condition) && fieldVal === condition) { - isShow = true - return false + if (isShow) { + const condition = conditions[key] + const fieldVal = this.form.getFieldValue(key) + ? this.form.getFieldValue(key) + : (this.prefillContent[key] ? this.prefillContent[key].value : null) + if (Array.isArray(condition) && !condition.includes(fieldVal)) { + isShow = false + } else if (!Array.isArray(condition) && fieldVal !== condition) { + isShow = false + } } - - return true }) return isShow diff --git a/ui/src/views/infra/zone/ZoneWizardAddResources.vue b/ui/src/views/infra/zone/ZoneWizardAddResources.vue index 5804676fe9f..ee16e26ca5c 100644 --- a/ui/src/views/infra/zone/ZoneWizardAddResources.vue +++ b/ui/src/views/infra/zone/ZoneWizardAddResources.vue @@ -570,7 +570,7 @@ export default { } }, { - title: 'label.s3.access_key', + title: 'label.s3.access.key', key: 'secondaryStorageAccessKey', required: true, placeHolder: 'message.error.access.key', @@ -579,7 +579,7 @@ export default { } }, { - title: 'label.s3.secret_key', + title: 'label.s3.secret.key', key: 'secondaryStorageSecretKey', required: true, placeHolder: 'message.error.secret.key', @@ -605,7 +605,7 @@ export default { } }, { - title: 'label.s3.use_https', + title: 'label.s3.use.https', key: 'secondaryStorageHttps', required: false, switch: true, @@ -615,7 +615,7 @@ export default { } }, { - title: 'label.s3.connection_timeoutt', + title: 'label.s3.connection.timeout', key: 'secondaryStorageConnectionTimeout', required: false, display: { @@ -623,7 +623,7 @@ export default { } }, { - title: 'label.s3.max_error_retry', + title: 'label.s3.max.error.retry', key: 'secondaryStorageMaxError', required: false, display: { @@ -631,7 +631,7 @@ export default { } }, { - title: 'label.s3.socket_timeout', + title: 'label.s3.socket.timeout', key: 'secondaryStorageSocketTimeout', required: false, display: { @@ -653,7 +653,8 @@ export default { required: true, placeHolder: 'message.error.s3nfs.server', display: { - secondaryStorageProvider: ['S3'] + secondaryStorageProvider: ['S3'], + secondaryStorageNFSStaging: true } }, { @@ -662,7 +663,8 @@ export default { required: true, placeHolder: 'message.error.s3nfs.path', display: { - secondaryStorageProvider: ['S3'] + secondaryStorageProvider: ['S3'], + secondaryStorageNFSStaging: true } }, { @@ -677,7 +679,8 @@ export default { { title: 'label.account', key: 'secondaryStorageAccount', - required: false, + required: true, + placeHolder: 'message.error.swift.account', display: { secondaryStorageProvider: ['Swift'] } @@ -685,7 +688,8 @@ export default { { title: 'label.username', key: 'secondaryStorageUsername', - required: false, + required: true, + placeHolder: 'message.error.swift.username', display: { secondaryStorageProvider: ['Swift'] } @@ -693,6 +697,15 @@ export default { { title: 'label.key', key: 'secondaryStorageKey', + required: true, + placeHolder: 'message.error.swift.key', + display: { + secondaryStorageProvider: ['Swift'] + } + }, + { + title: 'label.storagepolicy', + key: 'secondaryStoragePolicy', required: false, display: { secondaryStorageProvider: ['Swift'] diff --git a/ui/src/views/infra/zone/ZoneWizardLaunchZone.vue b/ui/src/views/infra/zone/ZoneWizardLaunchZone.vue index eb18181aa88..d22cd35c8fd 100644 --- a/ui/src/views/infra/zone/ZoneWizardLaunchZone.vue +++ b/ui/src/views/infra/zone/ZoneWizardLaunchZone.vue @@ -1471,6 +1471,12 @@ export default { params['details[' + index.toString() + '].value'] = this.prefillContent.secondaryStorageKey.value index++ } + if (this.prefillContent.secondaryStoragePolicy && + this.prefillContent.secondaryStoragePolicy.value.length > 0) { + params['details[' + index.toString() + '].key'] = 'storagepolicy' + params['details[' + index.toString() + '].value'] = this.prefillContent.secondaryStoragePolicy.value + index++ + } } try {