From 4392cc4d485b31c90648871d970294f538624935 Mon Sep 17 00:00:00 2001 From: Hoang Nguyen Date: Mon, 3 Jan 2022 22:29:49 +0700 Subject: [PATCH 1/4] ui: refactoring $notification according to the old version (#5819) Related to PR #5549 changed the notification from $notification to $showNotification. This PR aims to change it back to the way it was for easier use while keeping the delete all button. --- ui/src/components/view/DetailSettings.vue | 3 +- ui/src/components/view/ListView.vue | 3 +- ui/src/components/view/ResourceLimitTab.vue | 3 +- ui/src/components/view/SettingsTab.vue | 3 +- ui/src/components/view/UploadResourceIcon.vue | 12 ++-- ui/src/config/section/compute.js | 6 +- ui/src/core/lazy_lib/components_use.js | 1 - ui/src/utils/plugins.js | 56 ++++++++++++------- ui/src/views/AutogenView.vue | 3 +- ui/src/views/compute/AssignInstance.vue | 3 +- ui/src/views/compute/ChangeAffinity.vue | 3 +- ui/src/views/compute/CreateSSHKeyPair.vue | 3 +- ui/src/views/compute/CreateSnapshotWizard.vue | 3 +- ui/src/views/compute/DeployVM.vue | 23 +++----- ui/src/views/compute/KubernetesServiceTab.vue | 3 +- ui/src/views/compute/MigrateWizard.vue | 3 +- ui/src/views/compute/ScaleVM.vue | 3 +- ui/src/views/compute/StartVirtualMachine.vue | 9 +-- .../views/compute/backup/BackupSchedule.vue | 3 +- ui/src/views/compute/backup/FormSchedule.vue | 3 +- ui/src/views/iam/AddAccount.vue | 15 ++--- ui/src/views/iam/AddLdapAccount.vue | 6 +- ui/src/views/iam/AddUser.vue | 18 ++---- ui/src/views/iam/ChangeUserPassword.vue | 3 +- ui/src/views/iam/ConfigureSamlSsoAuth.vue | 6 +- ui/src/views/iam/CreateRole.vue | 3 +- ui/src/views/iam/DomainActionForm.vue | 6 +- ui/src/views/iam/DomainView.vue | 3 +- ui/src/views/iam/EditUser.vue | 6 +- ui/src/views/iam/ImportRole.vue | 6 +- ui/src/views/image/IsoZones.vue | 3 +- ui/src/views/image/RegisterOrUploadIso.vue | 15 ++--- .../views/image/RegisterOrUploadTemplate.vue | 12 ++-- ui/src/views/image/TemplateZones.vue | 3 +- .../image/UpdateTemplateIsoPermissions.vue | 3 +- ui/src/views/infra/AddPrimaryStorage.vue | 3 +- ui/src/views/infra/AddSecondaryStorage.vue | 3 +- ui/src/views/infra/ClusterAdd.vue | 9 +-- ui/src/views/infra/HostAdd.vue | 6 +- ui/src/views/infra/InfraSummary.vue | 6 +- ui/src/views/infra/MigrateData.vue | 6 +- ui/src/views/infra/PodAdd.vue | 6 +- .../views/infra/network/DedicatedVLANTab.vue | 3 +- .../views/infra/network/EditTrafficLabel.vue | 3 +- .../views/infra/network/IpRangesTabPublic.vue | 15 ++--- .../infra/network/ServiceProvidersTab.vue | 6 +- .../network/providers/AddF5LoadBalancer.vue | 3 +- .../providers/AddNetscalerLoadBalancer.vue | 3 +- .../network/providers/AddNiciraNvpDevice.vue | 3 +- .../network/providers/AddPaloAltoFirewall.vue | 3 +- .../network/providers/AddSrxFirewall.vue | 3 +- .../infra/network/providers/ProviderItem.vue | 3 +- .../network/providers/ProviderListView.vue | 6 +- .../views/infra/zone/ZoneWizardLaunchZone.vue | 3 +- ui/src/views/network/AclListRulesTab.vue | 3 +- .../network/CreateIsolatedNetworkForm.vue | 3 +- ui/src/views/network/CreateL2NetworkForm.vue | 3 +- .../views/network/CreateSharedNetworkForm.vue | 6 +- ui/src/views/network/CreateVlanIpRange.vue | 6 +- .../views/network/InternalLBAssignVmForm.vue | 3 +- ui/src/views/network/IpAddressesTab.vue | 6 +- ui/src/views/network/VpcTiersTab.vue | 3 +- ui/src/views/network/VpnDetails.vue | 3 +- .../views/offering/UpdateOfferingAccess.vue | 3 +- .../plugins/quota/EditTariffValueWizard.vue | 3 +- ui/src/views/project/iam/ProjectRoleTab.vue | 9 +-- ui/src/views/storage/FormSchedule.vue | 3 +- ui/src/views/storage/ResizeVolume.vue | 3 +- ui/src/views/storage/ScheduledSnapshots.vue | 3 +- ui/src/views/storage/UploadLocalVolume.vue | 9 +-- .../views/tools/ImportUnmanagedInstance.vue | 21 +++---- ui/tests/unit/views/AutogenView.spec.js | 33 ++++++----- .../unit/views/compute/MigrateWizard.spec.js | 20 +++++-- 73 files changed, 198 insertions(+), 295 deletions(-) diff --git a/ui/src/components/view/DetailSettings.vue b/ui/src/components/view/DetailSettings.vue index 07f0a49cefd..2588c11fb2e 100644 --- a/ui/src/components/view/DetailSettings.vue +++ b/ui/src/components/view/DetailSettings.vue @@ -219,8 +219,7 @@ export default { apiName = 'updateTemplate' } if (!(apiName in this.$store.getters.apis)) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('error.execute.api.failed') + ' ' + apiName, description: this.$t('message.user.not.permitted.api') }) diff --git a/ui/src/components/view/ListView.vue b/ui/src/components/view/ListView.vue index 0918dd688f6..7ea3e39a13d 100644 --- a/ui/src/components/view/ListView.vue +++ b/ui/src/components/view/ListView.vue @@ -514,8 +514,7 @@ export default { json.updateconfigurationresponse.configuration && !json.updateconfigurationresponse.configuration.isdynamic && ['Admin'].includes(this.$store.getters.userInfo.roletype)) { - this.$showNotification({ - type: 'warning', + this.$notification.warning({ message: this.$t('label.status'), description: this.$t('message.restart.mgmt.server') }) diff --git a/ui/src/components/view/ResourceLimitTab.vue b/ui/src/components/view/ResourceLimitTab.vue index 2bf9619322b..93cce68fd7b 100644 --- a/ui/src/components/view/ResourceLimitTab.vue +++ b/ui/src/components/view/ResourceLimitTab.vue @@ -107,8 +107,7 @@ export default { this.dataResource = await this.listResourceLimits(params) this.formLoading = false } catch (e) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: e }) diff --git a/ui/src/components/view/SettingsTab.vue b/ui/src/components/view/SettingsTab.vue index 4f71e1957f3..349d51691dd 100644 --- a/ui/src/components/view/SettingsTab.vue +++ b/ui/src/components/view/SettingsTab.vue @@ -164,8 +164,7 @@ export default { }).catch(error => { console.error(error) this.$message.error(this.$t('message.error.save.setting')) - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('label.error'), description: this.$t('message.error.try.save.setting') }) diff --git a/ui/src/components/view/UploadResourceIcon.vue b/ui/src/components/view/UploadResourceIcon.vue index cd8eb2f8902..ecf6d6668e0 100644 --- a/ui/src/components/view/UploadResourceIcon.vue +++ b/ui/src/components/view/UploadResourceIcon.vue @@ -234,15 +234,13 @@ export default { }).then(json => { console.log(this.resource) if (json?.uploadresourceiconresponse?.success) { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.upload.icon'), description: `${this.$t('message.success.upload.icon')} ${resourceType}: ` + (this.resource.name || this.resource.username || resourceid) }) } }).catch((error) => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('label.upload.icon'), description: error?.response?.data?.uploadresourceiconresponse?.errortext || '', duration: 0 @@ -266,15 +264,13 @@ export default { resourceids: resourceid }).then(json => { if (json?.deleteresourceiconresponse?.success) { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.delete.icon'), description: `${this.$t('message.success.delete.icon')} ${resourceType}: ` + (this.resource.name || this.resource.username || resourceid) }) } }).catch((error) => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('label.delete.icon'), description: error?.response?.data?.deleteresourceiconresponse?.errortext || '', duration: 0 diff --git a/ui/src/config/section/compute.js b/ui/src/config/section/compute.js index 416fa985082..835923d9f07 100644 --- a/ui/src/config/section/compute.js +++ b/ui/src/config/section/compute.js @@ -152,8 +152,7 @@ export default { const vm = result.jobresult.virtualmachine || {} if (result.jobstatus === 1 && vm.password) { const name = vm.displayname || vm.name || vm.id - obj.$showNotification({ - type: 'success', + obj.$notification.success({ message: `${obj.$t('label.reinstall.vm')}: ` + name, description: `${obj.$t('label.password.reset.confirm')}: ` + vm.password, duration: 0 @@ -362,8 +361,7 @@ export default { const vm = result.jobresult.virtualmachine || {} if (result.jobstatus === 1 && vm.password) { const name = vm.displayname || vm.name || vm.id - obj.$showNotification({ - type: 'success', + obj.$notification.success({ message: `${obj.$t('label.reset.ssh.key.pair.on.vm')}: ` + name, description: `${obj.$t('label.password.reset.confirm')}: ` + vm.password, duration: 0 diff --git a/ui/src/core/lazy_lib/components_use.js b/ui/src/core/lazy_lib/components_use.js index a9adc5d924d..b0bfcca5109 100644 --- a/ui/src/core/lazy_lib/components_use.js +++ b/ui/src/core/lazy_lib/components_use.js @@ -122,7 +122,6 @@ Vue.use(VueCropper) Vue.prototype.$confirm = Modal.confirm Vue.prototype.$message = message -Vue.prototype.$notification = notification Vue.prototype.$info = Modal.info Vue.prototype.$success = Modal.success Vue.prototype.$error = Modal.error diff --git a/ui/src/utils/plugins.js b/ui/src/utils/plugins.js index 5f32cf2b931..16937507c14 100644 --- a/ui/src/utils/plugins.js +++ b/ui/src/utils/plugins.js @@ -237,33 +237,47 @@ export const notifierPlugin = { }) } - Vue.prototype.$showNotification = function (config) { - let countNotify = store.getters.countNotify - countNotify++ - store.commit('SET_COUNT_NOTIFY', countNotify) - const defaultConfig = { + Vue.prototype.$notification = { + defaultConfig: { top: '65px', onClose: () => { let countNotify = store.getters.countNotify countNotify > 0 ? countNotify-- : countNotify = 0 store.commit('SET_COUNT_NOTIFY', countNotify) } - } - config = Object.assign({}, defaultConfig, config) - switch (config.type) { - case 'info': - notification.info(config) - break - case 'error': - notification.error(config) - break - case 'success': - notification.success(config) - break - case 'warning': - notification.warning(config) - break - } + }, + setCountNotify: () => { + let countNotify = store.getters.countNotify + countNotify++ + store.commit('SET_COUNT_NOTIFY', countNotify) + }, + info: (config) => { + Vue.prototype.$notification.setCountNotify() + config = Object.assign({}, Vue.prototype.$notification.defaultConfig, config) + notification.info(config) + }, + error: (config) => { + Vue.prototype.$notification.setCountNotify() + config = Object.assign({}, Vue.prototype.$notification.defaultConfig, config) + notification.error(config) + }, + success: (config) => { + Vue.prototype.$notification.setCountNotify() + config = Object.assign({}, Vue.prototype.$notification.defaultConfig, config) + notification.success(config) + }, + warning: (config) => { + Vue.prototype.$notification.setCountNotify() + config = Object.assign({}, Vue.prototype.$notification.defaultConfig, config) + notification.warning(config) + }, + warn: (config) => { + Vue.prototype.$notification.setCountNotify() + config = Object.assign({}, Vue.prototype.$notification.defaultConfig, config) + notification.warn(config) + }, + close: (key) => notification.close(key), + destroy: () => notification.destroy() } } } diff --git a/ui/src/views/AutogenView.vue b/ui/src/views/AutogenView.vue index 705a439e899..4c128a78090 100644 --- a/ui/src/views/AutogenView.vue +++ b/ui/src/views/AutogenView.vue @@ -1128,8 +1128,7 @@ export default { if (action.response) { const description = action.response(result.jobresult) if (description) { - this.$showNotification({ - type: 'info', + this.$notification.info({ message: this.$t(action.label), description: (), duration: 0 diff --git a/ui/src/views/compute/AssignInstance.vue b/ui/src/views/compute/AssignInstance.vue index bba7ee4cbbb..9341064b3fd 100644 --- a/ui/src/views/compute/AssignInstance.vue +++ b/ui/src/views/compute/AssignInstance.vue @@ -294,8 +294,7 @@ export default { [variableKey]: variableValue, networkids: this.selectedNetwork }).then(response => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.loadbalancerinstance') }) this.$parent.$parent.close() diff --git a/ui/src/views/compute/ChangeAffinity.vue b/ui/src/views/compute/ChangeAffinity.vue index 5f97c255abc..d1dabebe70b 100644 --- a/ui/src/views/compute/ChangeAffinity.vue +++ b/ui/src/views/compute/ChangeAffinity.vue @@ -149,8 +149,7 @@ export default { id: this.resource.id, affinitygroupids: this.selectedRowKeys.join(',') }).then(response => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('message.success.change.affinity.group') }) this.$parent.$parent.close() diff --git a/ui/src/views/compute/CreateSSHKeyPair.vue b/ui/src/views/compute/CreateSSHKeyPair.vue index f244fe2abb2..15a6f9797e8 100644 --- a/ui/src/views/compute/CreateSSHKeyPair.vue +++ b/ui/src/views/compute/CreateSSHKeyPair.vue @@ -198,8 +198,7 @@ export default { this.hiddenElement.click() }, notifyCopied () { - this.$showNotification({ - type: 'info', + this.$notification.info({ message: this.$t('message.success.copy.clipboard') }) }, diff --git a/ui/src/views/compute/CreateSnapshotWizard.vue b/ui/src/views/compute/CreateSnapshotWizard.vue index 061fa875e75..ed4fbc9e975 100644 --- a/ui/src/views/compute/CreateSnapshotWizard.vue +++ b/ui/src/views/compute/CreateSnapshotWizard.vue @@ -141,8 +141,7 @@ export default { const volumeId = result.jobresult.snapshot.volumeid const snapshotId = result.jobresult.snapshot.id const message = `${this.$t('label.create.snapshot.for.volume')} ${volumeId} ${this.$t('label.with.snapshotid')} ${snapshotId}` - this.$showNotification({ - type: 'success', + this.$notification.success({ message: message, duration: 0 }) diff --git a/ui/src/views/compute/DeployVM.vue b/ui/src/views/compute/DeployVM.vue index 37008fcd7a6..bc59d58ce51 100644 --- a/ui/src/views/compute/DeployVM.vue +++ b/ui/src/views/compute/DeployVM.vue @@ -1491,7 +1491,7 @@ export default { this.form.validateFieldsAndScroll(options, async (err, values) => { if (err) { if (err.licensesaccepted) { - this.$showNotification({ + this.$notification.error({ type: 'error', message: this.$t('message.license.agreements.not.accepted'), description: this.$t('message.step.license.agreements.continue') @@ -1499,8 +1499,7 @@ export default { return } - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: this.$t('error.form.message') }) @@ -1508,31 +1507,27 @@ export default { } if (!values.templateid && !values.isoid) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: this.$t('message.template.iso') }) return } else if (values.isoid && (!values.diskofferingid || values.diskofferingid === '0')) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: this.$t('message.step.3.continue') }) return } if (!values.computeofferingid) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: this.$t('message.step.2.continue') }) return } if (this.error) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: this.$t('error.form.message') }) @@ -1645,8 +1640,7 @@ export default { } } } else { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: this.$t('message.step.4.continue') }) @@ -1708,8 +1702,7 @@ export default { const vm = result.jobresult.virtualmachine const name = vm.displayname || vm.name || vm.id if (vm.password) { - this.$showNotification({ - type: 'success', + this.$notification.error({ message: password + ` ${this.$t('label.for')} ` + name, description: vm.password, duration: 0 diff --git a/ui/src/views/compute/KubernetesServiceTab.vue b/ui/src/views/compute/KubernetesServiceTab.vue index 55254dd537f..97f1c5456ec 100644 --- a/ui/src/views/compute/KubernetesServiceTab.vue +++ b/ui/src/views/compute/KubernetesServiceTab.vue @@ -321,8 +321,7 @@ export default { config.configdata !== '') { this.clusterConfig = config.configdata } else { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: this.$t('message.error.retrieve.kubeconfig') }) diff --git a/ui/src/views/compute/MigrateWizard.vue b/ui/src/views/compute/MigrateWizard.vue index 39493b8b2f4..310799859ba 100644 --- a/ui/src/views/compute/MigrateWizard.vue +++ b/ui/src/views/compute/MigrateWizard.vue @@ -220,8 +220,7 @@ export default { }) this.$emit('close-action') }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message, duration: 0 diff --git a/ui/src/views/compute/ScaleVM.vue b/ui/src/views/compute/ScaleVM.vue index 4a9087d9fd8..a0cf5b197a1 100644 --- a/ui/src/views/compute/ScaleVM.vue +++ b/ui/src/views/compute/ScaleVM.vue @@ -166,8 +166,7 @@ export default { this.$pollJob({ jobId, successMethod: result => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('message.success.change.offering') }) }, diff --git a/ui/src/views/compute/StartVirtualMachine.vue b/ui/src/views/compute/StartVirtualMachine.vue index d7515459c0d..db8412c8e61 100644 --- a/ui/src/views/compute/StartVirtualMachine.vue +++ b/ui/src/views/compute/StartVirtualMachine.vue @@ -143,8 +143,7 @@ export default { api('listPods', params).then(json => { this.pods = json.listpodsresponse.pod || [] if (this.pods.length === 0) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: 'No pods found', duration: 0 }) @@ -163,8 +162,7 @@ export default { api('listClusters', params).then(json => { this.clusters = json.listclustersresponse.cluster || [] if (this.clusters.length === 0) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: 'No clusters found', duration: 0 }) @@ -186,8 +184,7 @@ export default { api('listHosts', params).then(json => { this.hosts = json.listhostsresponse.host || [] if (this.hosts.length === 0) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: 'No hosts found', duration: 0 }) diff --git a/ui/src/views/compute/backup/BackupSchedule.vue b/ui/src/views/compute/backup/BackupSchedule.vue index d1d78d8d53e..66b7dc7d44e 100644 --- a/ui/src/views/compute/backup/BackupSchedule.vue +++ b/ui/src/views/compute/backup/BackupSchedule.vue @@ -157,8 +157,7 @@ export default { this.actionLoading = true api('deleteBackupSchedule', params).then(json => { if (json.deletebackupscheduleresponse.success) { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.scheduled.backups'), description: this.$t('message.success.delete.backup.schedule') }) diff --git a/ui/src/views/compute/backup/FormSchedule.vue b/ui/src/views/compute/backup/FormSchedule.vue index ffac01c4bab..1220315097a 100644 --- a/ui/src/views/compute/backup/FormSchedule.vue +++ b/ui/src/views/compute/backup/FormSchedule.vue @@ -284,8 +284,7 @@ export default { } this.actionLoading = true api('createBackupSchedule', params).then(json => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.scheduled.backups'), description: this.$t('message.success.config.backup.schedule') }) diff --git a/ui/src/views/iam/AddAccount.vue b/ui/src/views/iam/AddAccount.vue index 864e4a1851f..940addeaafb 100644 --- a/ui/src/views/iam/AddAccount.vue +++ b/ui/src/views/iam/AddAccount.vue @@ -266,8 +266,7 @@ export default { this.domainsList = response.listdomainsresponse.domain || [] this.selectedDomain = this.domainsList[0].id || '' }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: `${this.$t('label.error')} ${error.response.status}`, description: error.response.data.errorresponse.errortext }) @@ -342,8 +341,7 @@ export default { api('createAccount', {}, 'POST', params).then(response => { this.$emit('refresh-data') - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.create.account'), description: `${this.$t('message.success.create.account')} ${params.username}` }) @@ -355,14 +353,12 @@ export default { entityid: values.samlentity, userid: users[i].id }).then(response => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.samlenable'), description: this.$t('message.success.enable.saml.auth') }) }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message, duration: 0 @@ -372,8 +368,7 @@ export default { } this.closeAction() }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message, duration: 0 diff --git a/ui/src/views/iam/AddLdapAccount.vue b/ui/src/views/iam/AddLdapAccount.vue index 821ff314301..982cebdd676 100644 --- a/ui/src/views/iam/AddLdapAccount.vue +++ b/ui/src/views/iam/AddLdapAccount.vue @@ -410,15 +410,13 @@ export default { this.authorizeUsersForSamlSSO(users, entityId) } } else if (apiName === 'importLdapUsers' && response.ldapuserresponse && values.samlEnable) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: this.$t('message.error.enable.saml') }) } else { if (apiName === 'ldapCreateAccount') { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.add.ldap.account'), description: response.createaccountresponse.account.name }) diff --git a/ui/src/views/iam/AddUser.vue b/ui/src/views/iam/AddUser.vue index 4b4c0ce88a6..f57585c60f7 100644 --- a/ui/src/views/iam/AddUser.vue +++ b/ui/src/views/iam/AddUser.vue @@ -238,8 +238,7 @@ export default { this.domainsList = response.listdomainsresponse.domain || [] this.selectedDomain = this.domainsList[0].id || '' }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: `${this.$t('label.error')} ${error.response.status}`, description: error.response.data.errorresponse.errortext }) @@ -253,8 +252,7 @@ export default { api('listAccounts', { listAll: true, showicon: true }).then(response => { this.accountList = response.listaccountsresponse.account || [] }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: `${this.$t('label.error')} ${error.response.status}`, description: error.response.data.errorresponse.errortext }) @@ -321,8 +319,7 @@ export default { api('createUser', {}, 'POST', params).then(response => { this.$emit('refresh-data') - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.create.user'), description: `${this.$t('message.success.create.user')} ${params.username}` }) @@ -333,14 +330,12 @@ export default { entityid: values.samlentity, userid: user.id }).then(response => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.samlenable'), description: this.$t('message.success.enable.saml.auth') }) }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message, duration: 0 @@ -349,8 +344,7 @@ export default { } this.closeAction() }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message, duration: 0 diff --git a/ui/src/views/iam/ChangeUserPassword.vue b/ui/src/views/iam/ChangeUserPassword.vue index 3e19738065f..ae7453583db 100644 --- a/ui/src/views/iam/ChangeUserPassword.vue +++ b/ui/src/views/iam/ChangeUserPassword.vue @@ -128,8 +128,7 @@ export default { params.currentpassword = values.currentpassword } api('updateUser', {}, 'POST', params).then(json => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.action.change.password'), description: `${this.$t('message.success.change.password')} ${this.resource.username}` }) diff --git a/ui/src/views/iam/ConfigureSamlSsoAuth.vue b/ui/src/views/iam/ConfigureSamlSsoAuth.vue index 34f9254044e..63ba49afedf 100644 --- a/ui/src/views/iam/ConfigureSamlSsoAuth.vue +++ b/ui/src/views/iam/ConfigureSamlSsoAuth.vue @@ -108,16 +108,14 @@ export default { userid: this.resource.id, entityid: values.samlEntity }).then(response => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: values.samlEnable ? this.$t('label.saml.enable') : this.$t('label.saml.disable'), description: values.samlEnable ? `${this.$t('message.success.enable.saml.auth')} ${this.$t('label.for')} ${this.resource.username}` : `${this.$t('message.success.disable.saml.auth')} ${this.$t('label.for')} ${this.resource.username}` }) this.handleClose() }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message, duration: 0 diff --git a/ui/src/views/iam/CreateRole.vue b/ui/src/views/iam/CreateRole.vue index 88c42b9fe81..9b80397c138 100644 --- a/ui/src/views/iam/CreateRole.vue +++ b/ui/src/views/iam/CreateRole.vue @@ -174,8 +174,7 @@ export default { const role = json.createroleresponse.role if (role) { this.$emit('refresh-data') - this.$showNotification({ - type: 'success', + this.$notification.success({ message: 'Create Role', description: 'Sucessfully created role ' + params.name }) diff --git a/ui/src/views/iam/DomainActionForm.vue b/ui/src/views/iam/DomainActionForm.vue index ae5b0691b3b..1696d525810 100644 --- a/ui/src/views/iam/DomainActionForm.vue +++ b/ui/src/views/iam/DomainActionForm.vue @@ -253,8 +253,7 @@ export default { if (this.action.response) { const description = this.action.response(result.jobresult) if (description) { - this.$showNotification({ - type: 'info', + this.$notification.info({ message: this.$t(this.action.label), description: (), duration: 0 @@ -290,8 +289,7 @@ export default { } this.parentCloseAction() }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message }) diff --git a/ui/src/views/iam/DomainView.vue b/ui/src/views/iam/DomainView.vue index 6f11967431c..e69edc55ac1 100644 --- a/ui/src/views/iam/DomainView.vue +++ b/ui/src/views/iam/DomainView.vue @@ -187,8 +187,7 @@ export default { return } - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: error.response.headers['x-description'], duration: 0 diff --git a/ui/src/views/iam/EditUser.vue b/ui/src/views/iam/EditUser.vue index dedfcfdbf86..7009e01b364 100644 --- a/ui/src/views/iam/EditUser.vue +++ b/ui/src/views/iam/EditUser.vue @@ -178,15 +178,13 @@ export default { api('updateUser', params).then(response => { this.$emit('refresh-data') - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.edit.user'), description: `${this.$t('message.success.update.user')} ${params.username}` }) this.closeAction() }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message, duration: 0 diff --git a/ui/src/views/iam/ImportRole.vue b/ui/src/views/iam/ImportRole.vue index 2e18873a3bd..b285ace6564 100644 --- a/ui/src/views/iam/ImportRole.vue +++ b/ui/src/views/iam/ImportRole.vue @@ -128,8 +128,7 @@ export default { }, handleChange (info) { if (info.file.status === 'error') { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('label.error.file.upload'), description: this.$t('label.error.file.upload') }) @@ -186,8 +185,7 @@ export default { const role = json.importroleresponse.role if (role) { this.$emit('refresh-data') - this.$showNotification({ - type: 'success', + this.$notification.success({ message: 'Import Role', description: 'Sucessfully imported role ' + params.name }) diff --git a/ui/src/views/image/IsoZones.vue b/ui/src/views/image/IsoZones.vue index 7396f352d81..f838262a21b 100644 --- a/ui/src/views/image/IsoZones.vue +++ b/ui/src/views/image/IsoZones.vue @@ -455,8 +455,7 @@ export default { catchMessage: this.$t('error.fetching.async.job.result') }) }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message }) diff --git a/ui/src/views/image/RegisterOrUploadIso.vue b/ui/src/views/image/RegisterOrUploadIso.vue index 0c2ab4edf04..e4ab9703e7f 100644 --- a/ui/src/views/image/RegisterOrUploadIso.vue +++ b/ui/src/views/image/RegisterOrUploadIso.vue @@ -265,8 +265,7 @@ export default { handleUpload () { const { fileList } = this if (this.fileList.length > 1) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.upload.iso.failed'), description: this.$t('message.error.upload.iso.description'), duration: 0 @@ -291,16 +290,14 @@ export default { }, timeout: 86400000 }).then((json) => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('message.success.upload'), description: this.$t('message.success.upload.description') }) this.closeAction() this.$emit('refresh-data') }).catch(e => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.upload.failed'), description: `${this.$t('message.upload.iso.failed.description')} - ${e}`, duration: 0 @@ -345,8 +342,7 @@ export default { if (this.currentForm === 'Create') { this.loading = true api('registerIso', params).then(json => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.action.register.iso'), description: `${this.$t('message.success.register.iso')} ${params.name}` }) @@ -367,8 +363,7 @@ export default { this.uploadParams = (json.postuploadisoresponse && json.postuploadisoresponse.getuploadparams) ? json.postuploadisoresponse.getuploadparams : '' const response = this.handleUpload() if (response === 'upload successful') { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('message.success.upload'), description: this.$t('message.success.upload.iso.description') }) diff --git a/ui/src/views/image/RegisterOrUploadTemplate.vue b/ui/src/views/image/RegisterOrUploadTemplate.vue index ce9ea5600d0..c4116019d4f 100644 --- a/ui/src/views/image/RegisterOrUploadTemplate.vue +++ b/ui/src/views/image/RegisterOrUploadTemplate.vue @@ -511,16 +511,14 @@ export default { }, timeout: 86400000 }).then((json) => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('message.success.upload'), description: this.$t('message.success.upload.template.description') }) this.$emit('refresh-data') this.closeAction() }).catch(e => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.upload.failed'), description: `${this.$t('message.upload.template.failed.description')} - ${e}`, duration: 0 @@ -889,8 +887,7 @@ export default { if (this.currentForm === 'Create') { this.loading = true api('registerTemplate', params).then(json => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.register.template'), description: `${this.$t('message.success.register.template')} ${params.name}` }) @@ -904,8 +901,7 @@ export default { } else { this.loading = true if (this.fileList.length > 1) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.error.upload.template'), description: this.$t('message.error.upload.template.description'), duration: 0 diff --git a/ui/src/views/image/TemplateZones.vue b/ui/src/views/image/TemplateZones.vue index bc5d72d9e72..ca83293a5d8 100644 --- a/ui/src/views/image/TemplateZones.vue +++ b/ui/src/views/image/TemplateZones.vue @@ -554,8 +554,7 @@ export default { catchMessage: this.$t('error.fetching.async.job.result') }) }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message }) diff --git a/ui/src/views/image/UpdateTemplateIsoPermissions.vue b/ui/src/views/image/UpdateTemplateIsoPermissions.vue index f27e72ee3a7..f731f7e84f3 100644 --- a/ui/src/views/image/UpdateTemplateIsoPermissions.vue +++ b/ui/src/views/image/UpdateTemplateIsoPermissions.vue @@ -289,8 +289,7 @@ export default { featured: this.resource.featured, op: this.selectedOperation.toLowerCase() }).then(response => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: `${this.$t('label.success.updated')} ${resourceType} ${this.$t('label.permissions')}` }) this.closeModal() diff --git a/ui/src/views/infra/AddPrimaryStorage.vue b/ui/src/views/infra/AddPrimaryStorage.vue index 461af0663f2..dbab19ea9e2 100644 --- a/ui/src/views/infra/AddPrimaryStorage.vue +++ b/ui/src/views/infra/AddPrimaryStorage.vue @@ -709,8 +709,7 @@ export default { } this.loading = true api('createStoragePool', {}, 'POST', params).then(json => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.add.primary.storage'), description: this.$t('label.add.primary.storage') }) diff --git a/ui/src/views/infra/AddSecondaryStorage.vue b/ui/src/views/infra/AddSecondaryStorage.vue index e57e0164802..0d34e6f4575 100644 --- a/ui/src/views/infra/AddSecondaryStorage.vue +++ b/ui/src/views/infra/AddSecondaryStorage.vue @@ -293,8 +293,7 @@ export default { this.loading = true api('addImageStore', data).then(json => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.add.secondary.storage'), description: this.$t('label.add.secondary.storage') }) diff --git a/ui/src/views/infra/ClusterAdd.vue b/ui/src/views/infra/ClusterAdd.vue index 8e6642862b4..d3c25c6c610 100644 --- a/ui/src/views/infra/ClusterAdd.vue +++ b/ui/src/views/infra/ClusterAdd.vue @@ -257,8 +257,7 @@ export default { } this.addCluster() }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: `${this.$t('label.error')} ${error.response.status}`, description: error.response.data.listvmwaredcsresponse.errortext, duration: 0 @@ -309,8 +308,7 @@ export default { this.parentToggleLoading() this.$parent.$parent.close() }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: `${this.$t('label.error')} ${error.response.status}`, description: error.response.data.addclusterresponse.errortext, duration: 0 @@ -345,8 +343,7 @@ export default { } }) }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: `${this.$t('label.error')} ${error.response.status}`, description: error.response.data.errorresponse.errortext, duration: 0 diff --git a/ui/src/views/infra/HostAdd.vue b/ui/src/views/infra/HostAdd.vue index 1003031e504..e4edfbc46af 100644 --- a/ui/src/views/infra/HostAdd.vue +++ b/ui/src/views/infra/HostAdd.vue @@ -362,8 +362,7 @@ export default { this.parentFetchData() this.$parent.$parent.close() }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: `${this.$t('label.error')} ${error.response.status}`, description: error.response.data.addhostresponse.errortext, duration: 0 @@ -398,8 +397,7 @@ export default { } }) }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: `${this.$t('label.error')} ${error.response.status}`, description: error.response.data.errorresponse.errortext, duration: 0 diff --git a/ui/src/views/infra/InfraSummary.vue b/ui/src/views/infra/InfraSummary.vue index 69534193793..5656dc58a44 100644 --- a/ui/src/views/infra/InfraSummary.vue +++ b/ui/src/views/infra/InfraSummary.vue @@ -241,14 +241,12 @@ export default { const result = json.queryasyncjobresultresponse if (result.jobstatus === 1 && this.maxCerts === count) { this.$message.success(`${this.$t('label.certificate.upload')}: ${result.jobresult.customcertificate.message}`) - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.certificate.upload'), description: result.jobresult.customcertificate.message || this.$t('message.success.certificate.upload') }) } else if (result.jobstatus === 2) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('label.certificate.upload.failed'), description: result.jobresult.errortext || this.$t('label.certificate.upload.failed.description'), duration: 0 diff --git a/ui/src/views/infra/MigrateData.vue b/ui/src/views/infra/MigrateData.vue index 6d1af2457b9..6ebe6531969 100644 --- a/ui/src/views/infra/MigrateData.vue +++ b/ui/src/views/infra/MigrateData.vue @@ -154,14 +154,12 @@ export default { const success = result.imagestore.success || false const message = result.imagestore.message || '' if (success) { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: title, description: message }) } else { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: title, description: message, duration: 0 diff --git a/ui/src/views/infra/PodAdd.vue b/ui/src/views/infra/PodAdd.vue index 8434be67cbc..1fffa560f08 100644 --- a/ui/src/views/infra/PodAdd.vue +++ b/ui/src/views/infra/PodAdd.vue @@ -207,8 +207,7 @@ export default { this.parentFetchData() this.$parent.$parent.close() }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: `${this.$t('label.error')} ${error.response.status}`, description: error.response.data.createpodresponse.errortext, duration: 0 @@ -243,8 +242,7 @@ export default { } }) }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: `${this.$t('label.error')} ${error.response.status}`, description: error.response.data.errorresponse.errortext, duration: 0 diff --git a/ui/src/views/infra/network/DedicatedVLANTab.vue b/ui/src/views/infra/network/DedicatedVLANTab.vue index 1aca6263bbd..a2b5e55c2ed 100644 --- a/ui/src/views/infra/network/DedicatedVLANTab.vue +++ b/ui/src/views/infra/network/DedicatedVLANTab.vue @@ -254,8 +254,7 @@ export default { this.items = response.listdedicatedguestvlanrangesresponse.dedicatedguestvlanrange || [] this.totalCount = response.listdedicatedguestvlanrangesresponse.count || 0 }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: `${this.$t('label.error')} ${error.response.status}`, description: error.response.data.errorresponse.errortext, duration: 0 diff --git a/ui/src/views/infra/network/EditTrafficLabel.vue b/ui/src/views/infra/network/EditTrafficLabel.vue index 4afe9a09d57..a56165ed19e 100644 --- a/ui/src/views/infra/network/EditTrafficLabel.vue +++ b/ui/src/views/infra/network/EditTrafficLabel.vue @@ -133,8 +133,7 @@ export default { this.traffictype = this.trafficTypes[0].traffictype || undefined }) .catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: `${this.$t('label.error')} ${error.response.status}`, description: error.response.data.errorresponse.errortext }) diff --git a/ui/src/views/infra/network/IpRangesTabPublic.vue b/ui/src/views/infra/network/IpRangesTabPublic.vue index c94223a1a18..ff1976f71e6 100644 --- a/ui/src/views/infra/network/IpRangesTabPublic.vue +++ b/ui/src/views/infra/network/IpRangesTabPublic.vue @@ -504,8 +504,7 @@ export default { handleDeleteIpRange (id) { this.componentLoading = true api('deleteVlanIpRange', { id }).then(() => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: 'Removed IP Range' }) }).catch(error => { @@ -541,13 +540,11 @@ export default { params.networkid = this.network.id } api('createVlanIpRange', params).then(() => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('message.success.add.iprange') }) }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: `${this.$t('label.error')} ${error.response.status}`, description: error.response.data.createvlaniprangeresponse ? error.response.data.createvlaniprangeresponse.errortext : error.response.data.errorresponse.errortext, @@ -575,13 +572,11 @@ export default { forsystemvms: values.forsystemvms } api('updateVlanIpRange', params).then(() => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('message.success.update.iprange') }) }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: `${this.$t('label.error')} ${error.response.status}`, description: error.response.data.updatevlaniprangeresponse ? error.response.data.updatevlaniprangeresponse.errortext : error.response.data.errorresponse.errortext, diff --git a/ui/src/views/infra/network/ServiceProvidersTab.vue b/ui/src/views/infra/network/ServiceProvidersTab.vue index c8f6bbdfc60..101762197c1 100644 --- a/ui/src/views/infra/network/ServiceProvidersTab.vue +++ b/ui/src/views/infra/network/ServiceProvidersTab.vue @@ -1219,8 +1219,7 @@ export default { this.onCloseAction() } catch (error) { this.actionLoading = false - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: error }) @@ -1356,8 +1355,7 @@ export default { this.onCloseAction() } catch (message) { this.actionLoading = false - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: message }) diff --git a/ui/src/views/infra/network/providers/AddF5LoadBalancer.vue b/ui/src/views/infra/network/providers/AddF5LoadBalancer.vue index d10e570397e..227520c8880 100644 --- a/ui/src/views/infra/network/providers/AddF5LoadBalancer.vue +++ b/ui/src/views/infra/network/providers/AddF5LoadBalancer.vue @@ -253,8 +253,7 @@ export default { this.loading = false } catch (error) { this.loading = false - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message }) diff --git a/ui/src/views/infra/network/providers/AddNetscalerLoadBalancer.vue b/ui/src/views/infra/network/providers/AddNetscalerLoadBalancer.vue index 41f0b6d20b5..7e12f545d46 100644 --- a/ui/src/views/infra/network/providers/AddNetscalerLoadBalancer.vue +++ b/ui/src/views/infra/network/providers/AddNetscalerLoadBalancer.vue @@ -288,8 +288,7 @@ export default { this.loading = false } catch (error) { this.loading = false - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message }) diff --git a/ui/src/views/infra/network/providers/AddNiciraNvpDevice.vue b/ui/src/views/infra/network/providers/AddNiciraNvpDevice.vue index 512da751c45..60a33b52f3a 100644 --- a/ui/src/views/infra/network/providers/AddNiciraNvpDevice.vue +++ b/ui/src/views/infra/network/providers/AddNiciraNvpDevice.vue @@ -160,8 +160,7 @@ export default { this.loading = false } catch (error) { this.loading = false - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message }) diff --git a/ui/src/views/infra/network/providers/AddPaloAltoFirewall.vue b/ui/src/views/infra/network/providers/AddPaloAltoFirewall.vue index a8c8db9121f..aff9d57f3ed 100644 --- a/ui/src/views/infra/network/providers/AddPaloAltoFirewall.vue +++ b/ui/src/views/infra/network/providers/AddPaloAltoFirewall.vue @@ -377,8 +377,7 @@ export default { this.loading = false } catch (error) { this.loading = false - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message }) diff --git a/ui/src/views/infra/network/providers/AddSrxFirewall.vue b/ui/src/views/infra/network/providers/AddSrxFirewall.vue index 6c4b6796b05..8a61d5fd5d6 100644 --- a/ui/src/views/infra/network/providers/AddSrxFirewall.vue +++ b/ui/src/views/infra/network/providers/AddSrxFirewall.vue @@ -322,8 +322,7 @@ export default { this.loading = false } catch (error) { this.loading = false - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message }) diff --git a/ui/src/views/infra/network/providers/ProviderItem.vue b/ui/src/views/infra/network/providers/ProviderItem.vue index ec4a84ecbd1..73931bd071c 100644 --- a/ui/src/views/infra/network/providers/ProviderItem.vue +++ b/ui/src/views/infra/network/providers/ProviderItem.vue @@ -188,8 +188,7 @@ export default { this.listData[args.title].loading = false } catch (error) { this.listData[args.title].loading = false - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message }) diff --git a/ui/src/views/infra/network/providers/ProviderListView.vue b/ui/src/views/infra/network/providers/ProviderListView.vue index a1a498b2004..ac235456352 100644 --- a/ui/src/views/infra/network/providers/ProviderListView.vue +++ b/ui/src/views/infra/network/providers/ProviderListView.vue @@ -300,8 +300,7 @@ export default { this.actionLoading = false } catch (error) { this.actionLoading = false - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message }) @@ -337,8 +336,7 @@ export default { this.actionLoading = false } catch (error) { this.actionLoading = false - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message }) diff --git a/ui/src/views/infra/zone/ZoneWizardLaunchZone.vue b/ui/src/views/infra/zone/ZoneWizardLaunchZone.vue index 9831e6d8a4e..eb18181aa88 100644 --- a/ui/src/views/infra/zone/ZoneWizardLaunchZone.vue +++ b/ui/src/views/infra/zone/ZoneWizardLaunchZone.vue @@ -1547,8 +1547,7 @@ export default { this.$emit('refresh-data') } catch (e) { this.loading = false - await this.$showNotification({ - type: 'error', + await this.$notification.error({ message: this.$t('message.request.failed'), description: e }) diff --git a/ui/src/views/network/AclListRulesTab.vue b/ui/src/views/network/AclListRulesTab.vue index e47dddf9d1a..673d33862a7 100644 --- a/ui/src/views/network/AclListRulesTab.vue +++ b/ui/src/views/network/AclListRulesTab.vue @@ -571,8 +571,7 @@ export default { data.aclid = this.resource.id api('createNetworkACL', {}, 'POST', data).then(() => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.success'), description: this.$t('message.success.add.rule') }) diff --git a/ui/src/views/network/CreateIsolatedNetworkForm.vue b/ui/src/views/network/CreateIsolatedNetworkForm.vue index 58ae0284d03..1f717710b85 100644 --- a/ui/src/views/network/CreateIsolatedNetworkForm.vue +++ b/ui/src/views/network/CreateIsolatedNetworkForm.vue @@ -442,8 +442,7 @@ export default { } } api('createNetwork', params).then(json => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: 'Network', description: this.$t('message.success.create.isolated.network') }) diff --git a/ui/src/views/network/CreateL2NetworkForm.vue b/ui/src/views/network/CreateL2NetworkForm.vue index 8243226cfa5..32c394feb95 100644 --- a/ui/src/views/network/CreateL2NetworkForm.vue +++ b/ui/src/views/network/CreateL2NetworkForm.vue @@ -393,8 +393,7 @@ export default { } } api('createNetwork', params).then(json => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: 'Network', description: this.$t('message.success.create.l2.network') }) diff --git a/ui/src/views/network/CreateSharedNetworkForm.vue b/ui/src/views/network/CreateSharedNetworkForm.vue index 554b6f67825..79af46d96a1 100644 --- a/ui/src/views/network/CreateSharedNetworkForm.vue +++ b/ui/src/views/network/CreateSharedNetworkForm.vue @@ -703,8 +703,7 @@ export default { !this.isValidTextValueForKey(values, 'ip6gateway') && !this.isValidTextValueForKey(values, 'ip6cidr') && !this.isValidTextValueForKey(values, 'startipv6') && !this.isValidTextValueForKey(values, 'endipv6')) ) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: this.$t('message.error.add.guest.network') }) @@ -789,8 +788,7 @@ export default { params.hideipaddressusage = true } api('createNetwork', params).then(json => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.network'), description: this.$t('message.success.add.guest.network') }) diff --git a/ui/src/views/network/CreateVlanIpRange.vue b/ui/src/views/network/CreateVlanIpRange.vue index 59fba3927fa..71a7f06dbb8 100644 --- a/ui/src/views/network/CreateVlanIpRange.vue +++ b/ui/src/views/network/CreateVlanIpRange.vue @@ -248,15 +248,13 @@ export default { api('createVlanIpRange', params) .then(() => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('message.success.add.iprange') }) this.closeAction() this.$emit('refresh-data') }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: `${this.$t('label.error')} ${error.response.status}`, description: error.response.data.createvlaniprangeresponse ? error.response.data.createvlaniprangeresponse.errortext : error.response.data.errorresponse.errortext, diff --git a/ui/src/views/network/InternalLBAssignVmForm.vue b/ui/src/views/network/InternalLBAssignVmForm.vue index cb07fa496e7..ff6894080de 100644 --- a/ui/src/views/network/InternalLBAssignVmForm.vue +++ b/ui/src/views/network/InternalLBAssignVmForm.vue @@ -223,8 +223,7 @@ export default { }) this.closeModal() }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: `${this.$t('label.error')} ${error.response.status}`, description: error.response.data.errorresponse.errortext, duration: 0 diff --git a/ui/src/views/network/IpAddressesTab.vue b/ui/src/views/network/IpAddressesTab.vue index ebea8d4330f..65c69336f09 100644 --- a/ui/src/views/network/IpAddressesTab.vue +++ b/ui/src/views/network/IpAddressesTab.vue @@ -359,8 +359,7 @@ export default { }) this.onCloseModal() }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: `${this.$t('label.error')} ${error.response.status}`, description: error.response.data.errorresponse.errortext, duration: 0 @@ -427,8 +426,7 @@ export default { }) }).catch(error => { this.fetchLoading = false - this.$showNotification({ - type: 'error', + this.$notification.error({ message: `${this.$t('label.error')} ${error.response.status}`, description: error.response.data.errorresponse.errortext, duration: 0 diff --git a/ui/src/views/network/VpcTiersTab.vue b/ui/src/views/network/VpcTiersTab.vue index a7881701262..25dee1260cd 100644 --- a/ui/src/views/network/VpcTiersTab.vue +++ b/ui/src/views/network/VpcTiersTab.vue @@ -664,8 +664,7 @@ export default { } api('createNetwork', params).then(() => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('message.success.add.vpc.network') }) }).catch(error => { diff --git a/ui/src/views/network/VpnDetails.vue b/ui/src/views/network/VpnDetails.vue index d0633a28dfc..7f112feaa03 100644 --- a/ui/src/views/network/VpnDetails.vue +++ b/ui/src/views/network/VpnDetails.vue @@ -132,8 +132,7 @@ export default { jobId: response.createremoteaccessvpnresponse.jobid, successMethod: result => { const res = result.jobresult.remoteaccessvpn - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.status'), description: `${this.$t('message.enabled.vpn')} ${res.publicip}. ${this.$t('message.enabled.vpn.ip.sec')} ${res.presharedkey}`, diff --git a/ui/src/views/offering/UpdateOfferingAccess.vue b/ui/src/views/offering/UpdateOfferingAccess.vue index 616231980f1..8ad7b117c31 100644 --- a/ui/src/views/offering/UpdateOfferingAccess.vue +++ b/ui/src/views/offering/UpdateOfferingAccess.vue @@ -297,8 +297,7 @@ export default { this.loading = true api('update' + this.offeringType, params).then(json => { this.$emit('refresh-data') - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.action.update.offering.access'), description: this.$t('label.action.update.offering.access') }) diff --git a/ui/src/views/plugins/quota/EditTariffValueWizard.vue b/ui/src/views/plugins/quota/EditTariffValueWizard.vue index 32a3795be4a..ef02b0c8164 100644 --- a/ui/src/views/plugins/quota/EditTariffValueWizard.vue +++ b/ui/src/views/plugins/quota/EditTariffValueWizard.vue @@ -125,8 +125,7 @@ export default { this.$message.success(`${this.$t('message.setting.updated')} ${this.resource.description}`) this.onClose() }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message }) diff --git a/ui/src/views/project/iam/ProjectRoleTab.vue b/ui/src/views/project/iam/ProjectRoleTab.vue index 001cc9de1b2..befbd69b3c3 100644 --- a/ui/src/views/project/iam/ProjectRoleTab.vue +++ b/ui/src/views/project/iam/ProjectRoleTab.vue @@ -229,8 +229,7 @@ export default { params[key] = input } api('updateProjectRole', params).then(response => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.update.project.role'), description: this.$t('label.update.project.role') }) @@ -269,8 +268,7 @@ export default { params[key] = input } api('createProjectRole', params).then(response => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.create.project.role'), description: this.$t('label.create.project.role') }) @@ -289,8 +287,7 @@ export default { projectid: this.resource.id, id: role.id }).then(response => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.delete.project.role'), description: this.$t('label.delete.project.role') }) diff --git a/ui/src/views/storage/FormSchedule.vue b/ui/src/views/storage/FormSchedule.vue index 09c5035db4d..441632860ea 100644 --- a/ui/src/views/storage/FormSchedule.vue +++ b/ui/src/views/storage/FormSchedule.vue @@ -385,8 +385,7 @@ export default { this.actionLoading = true api('createSnapshotPolicy', params).then(json => { this.$emit('refresh') - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.action.recurring.snapshot'), description: this.$t('message.success.recurring.snapshot') }) diff --git a/ui/src/views/storage/ResizeVolume.vue b/ui/src/views/storage/ResizeVolume.vue index 369067ff502..8c23fa3606b 100644 --- a/ui/src/views/storage/ResizeVolume.vue +++ b/ui/src/views/storage/ResizeVolume.vue @@ -125,8 +125,7 @@ export default { }) this.closeModal() }).catch(error => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: `${this.$t('label.error')} ${error.response.status}`, description: error.response.data.errorresponse.errortext, duration: 0 diff --git a/ui/src/views/storage/ScheduledSnapshots.vue b/ui/src/views/storage/ScheduledSnapshots.vue index ea1f429c482..fc1610fd462 100644 --- a/ui/src/views/storage/ScheduledSnapshots.vue +++ b/ui/src/views/storage/ScheduledSnapshots.vue @@ -162,8 +162,7 @@ export default { this.actionLoading = true api('deleteSnapshotPolicies', params).then(json => { if (json.deletesnapshotpoliciesresponse.success) { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('label.delete.snapshot.policy'), description: this.$t('message.success.delete.snapshot.policy') }) diff --git a/ui/src/views/storage/UploadLocalVolume.vue b/ui/src/views/storage/UploadLocalVolume.vue index 5388aca9013..c4f1d569014 100644 --- a/ui/src/views/storage/UploadLocalVolume.vue +++ b/ui/src/views/storage/UploadLocalVolume.vue @@ -191,8 +191,7 @@ export default { this.uploadParams = (json.postuploadvolumeresponse && json.postuploadvolumeresponse.getuploadparams) ? json.postuploadvolumeresponse.getuploadparams : '' const { fileList } = this if (this.fileList.length > 1) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.upload.volume.failed'), description: this.$t('message.upload.file.limit'), duration: 0 @@ -217,15 +216,13 @@ export default { }, timeout: 86400000 }).then((json) => { - this.$showNotification({ - type: 'success', + this.$notification.success({ message: this.$t('message.success.upload'), description: this.$t('message.success.upload.volume.description') }) this.closeAction() }).catch(e => { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.upload.failed'), description: `${this.$t('message.upload.iso.failed.description')} - ${e}`, duration: 0 diff --git a/ui/src/views/tools/ImportUnmanagedInstance.vue b/ui/src/views/tools/ImportUnmanagedInstance.vue index 77788c05dbf..ecde62fb4e4 100644 --- a/ui/src/views/tools/ImportUnmanagedInstance.vue +++ b/ui/src/views/tools/ImportUnmanagedInstance.vue @@ -631,8 +631,7 @@ export default { displayname: values.displayname } if (!this.computeOffering || !this.computeOffering.id) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: this.$t('message.step.2.continue') }) @@ -643,8 +642,7 @@ export default { var details = [this.cpuNumberKey, this.cpuSpeedKey, this.memoryKey] for (var detail of details) { if (!(values[detail] || this.computeOffering[detail])) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: this.$t('message.please.enter.valid.value') + ': ' + this.$t('label.' + detail.toLowerCase()) }) @@ -659,8 +657,7 @@ export default { var iopsDetails = [this.minIopsKey, this.maxIopsKey] for (var iopsDetail of iopsDetails) { if (!values[iopsDetail] || values[iopsDetail] < 0) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: this.$t('message.please.enter.valid.value') + ': ' + this.$t('label.' + iopsDetail.toLowerCase()) }) @@ -669,8 +666,7 @@ export default { params['details[0].' + iopsDetail] = values[iopsDetail] } if (values[this.minIopsKey] > values[this.maxIopsKey]) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: this.$t('error.form.message') }) @@ -688,8 +684,7 @@ export default { var diskOfferingIndex = 0 for (var diskId in this.dataDisksOfferingsMapping) { if (!this.dataDisksOfferingsMapping[diskId]) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: this.$t('message.select.disk.offering') + ': ' + diskId }) @@ -703,8 +698,7 @@ export default { var nicIpIndex = 0 for (var nicId in this.nicsNetworksMapping) { if (!this.nicsNetworksMapping[nicId].network) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: this.$t('message.select.nic.network') + ': ' + nicId }) @@ -715,8 +709,7 @@ export default { nicNetworkIndex++ if ('ipAddress' in this.nicsNetworksMapping[nicId]) { if (!this.nicsNetworksMapping[nicId].ipAddress) { - this.$showNotification({ - type: 'error', + this.$notification.error({ message: this.$t('message.request.failed'), description: this.$t('message.enter.valid.nic.ip') + ': ' + nicId }) diff --git a/ui/tests/unit/views/AutogenView.spec.js b/ui/tests/unit/views/AutogenView.spec.js index f8a67cd950d..9a20a0a3306 100644 --- a/ui/tests/unit/views/AutogenView.spec.js +++ b/ui/tests/unit/views/AutogenView.spec.js @@ -52,14 +52,20 @@ mocks = { $notifyError: jest.fn((error) => { return error }), - $showNotification: jest.fn((option) => { - return { - type: option.type, - message: option.message, - description: 'test-description', - duration: option.duration - } - }), + $notification: { + error: jest.fn((option) => { + return option + }), + info: jest.fn((option) => { + return option + }), + success: jest.fn((option) => { + return option + }), + warning: jest.fn((option) => { + return option + }) + }, $message: { success: jest.fn((obj) => { return obj @@ -1570,7 +1576,7 @@ describe('Views > AutogenView.vue', () => { }) describe('pollActionCompletion()', () => { - it('check $showNotification when pollActionCompletion() is called with action is empty', (done) => { + it('check $notification when pollActionCompletion() is called with action is empty', (done) => { const mockData = { queryasyncjobresultresponse: { jobstatus: 1, @@ -1588,7 +1594,7 @@ describe('Views > AutogenView.vue', () => { wrapper.vm.pollActionCompletion(jobId, action) setTimeout(() => { - expect(mocks.$showNotification).not.toHaveBeenCalled() + expect(mocks.$notification.info).not.toHaveBeenCalled() expect(mockAxios).toHaveBeenCalled() expect(mockAxios).toHaveBeenCalledWith({ url: '/', @@ -1605,7 +1611,7 @@ describe('Views > AutogenView.vue', () => { }) }) - it('check $showNotification when pollActionCompletion() is called with action is not empty', (done) => { + it('check $notification when pollActionCompletion() is called with action is not empty', (done) => { const mockData = { queryasyncjobresultresponse: { jobstatus: 1, @@ -1626,9 +1632,8 @@ describe('Views > AutogenView.vue', () => { wrapper.vm.pollActionCompletion(jobId, action) setTimeout(() => { - expect(mocks.$showNotification).toHaveBeenCalled() - expect(mocks.$showNotification).toHaveLastReturnedWith({ - type: 'info', + expect(mocks.$notification.info).toHaveBeenCalled() + expect(mocks.$notification.info).toHaveLastReturnedWith({ message: 'test-name-en', description: 'test-description', duration: 0 diff --git a/ui/tests/unit/views/compute/MigrateWizard.spec.js b/ui/tests/unit/views/compute/MigrateWizard.spec.js index 6a99fc675f7..2ee6b8e268c 100644 --- a/ui/tests/unit/views/compute/MigrateWizard.spec.js +++ b/ui/tests/unit/views/compute/MigrateWizard.spec.js @@ -29,7 +29,20 @@ mocks = { $message: { error: jest.fn((message) => {}) }, - $showNotification: jest.fn((obj) => {}), + $notification: { + error: jest.fn((option) => { + return option + }), + info: jest.fn((option) => { + return option + }), + success: jest.fn((option) => { + return option + }), + warning: jest.fn((option) => { + return option + }) + }, $pollJob: jest.fn((obj) => { switch (obj.jobId) { case 'test-job-id-case-1': @@ -752,9 +765,8 @@ describe('Views > compute > MigrateWizard.vue', () => { await wrapper.vm.submitForm() setTimeout(() => { - expect(mocks.$showNotification).toHaveBeenCalled() - expect(mocks.$showNotification).toHaveBeenCalledWith({ - type: 'error', + expect(mocks.$notification.error).toHaveBeenCalled() + expect(mocks.$notification.error).toHaveBeenCalledWith({ message: i18n.t('message.request.failed'), description: 'Error: throw error message', duration: 0 From e06a66ba14f720bb5768ed15e6e7721fcb807ebc Mon Sep 17 00:00:00 2001 From: dahn Date: Mon, 3 Jan 2022 16:31:51 +0100 Subject: [PATCH 2/4] ldap: truststore per domain (#5816) Co-authored-by: Daan Hoogland --- .../cloudstack/api/command/LDAPConfigCmd.java | 2 +- .../apache/cloudstack/ldap/LdapConfiguration.java | 14 +++++++------- .../apache/cloudstack/ldap/LdapContextFactory.java | 10 +++++----- .../cloudstack/ldap/LdapContextFactorySpec.groovy | 6 +++--- .../cloudstack/ldap/LdapConfigurationTest.java | 4 ++-- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LDAPConfigCmd.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LDAPConfigCmd.java index cfef21e2aff..23f71c22235 100644 --- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LDAPConfigCmd.java +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LDAPConfigCmd.java @@ -189,7 +189,7 @@ public class LDAPConfigCmd extends BaseCmd { List responses = new ArrayList(); if (result.second() > 0) { - boolean useSSlConfig = _ldapConfiguration.getSSLStatus(); + boolean useSSlConfig = _ldapConfiguration.getSSLStatus(null); String searchBaseConfig = _ldapConfiguration.getBaseDn(null); String bindDnConfig = _ldapConfiguration.getBindPrincipal(null); for (LdapConfigurationVO ldapConfigurationVO : result.first()) { diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapConfiguration.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapConfiguration.java index 259d613f6d9..11cbcbdc0a9 100644 --- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapConfiguration.java +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapConfiguration.java @@ -238,7 +238,7 @@ public class LdapConfiguration implements Configurable{ } public String getProviderUrl(final Long domainId) { - final String protocol = getSSLStatus() == true ? "ldaps://" : "ldap://"; + final String protocol = getSSLStatus(domainId) == true ? "ldaps://" : "ldap://"; final Pair, Integer> result = _ldapConfigurationDao.searchConfigurations(null, 0, domainId); final StringBuilder providerUrls = new StringBuilder(); String delim = ""; @@ -270,20 +270,20 @@ public class LdapConfiguration implements Configurable{ return ldapSearchGroupPrinciple.valueIn(domainId); } - public boolean getSSLStatus() { + public boolean getSSLStatus(Long domainId) { boolean sslStatus = false; - if (getTrustStore() != null && getTrustStorePassword() != null) { + if (getTrustStore(domainId) != null && getTrustStorePassword(domainId) != null) { sslStatus = true; } return sslStatus; } - public String getTrustStore() { - return ldapTrustStore.value(); + public String getTrustStore(Long domainId) { + return ldapTrustStore.valueIn(domainId); } - public String getTrustStorePassword() { - return ldapTrustStorePassword.value(); + public String getTrustStorePassword(Long domainId) { + return ldapTrustStorePassword.valueIn(domainId); } public String getUsernameAttribute(final Long domainId) { diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapContextFactory.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapContextFactory.java index 70f7a564111..fd7c4d634ef 100644 --- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapContextFactory.java +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapContextFactory.java @@ -66,14 +66,14 @@ public class LdapContextFactory { return createInitialDirContext(principal, password, false, domainId); } - private void enableSSL(final Hashtable environment) { - final boolean sslStatus = _ldapConfiguration.getSSLStatus(); + private void enableSSL(final Hashtable environment, Long domainId) { + final boolean sslStatus = _ldapConfiguration.getSSLStatus(domainId); if (sslStatus) { s_logger.info("LDAP SSL enabled."); environment.put(Context.SECURITY_PROTOCOL, "ssl"); - System.setProperty("javax.net.ssl.trustStore", _ldapConfiguration.getTrustStore()); - System.setProperty("javax.net.ssl.trustStorePassword", _ldapConfiguration.getTrustStorePassword()); + System.setProperty("javax.net.ssl.trustStore", _ldapConfiguration.getTrustStore(domainId)); + System.setProperty("javax.net.ssl.trustStorePassword", _ldapConfiguration.getTrustStorePassword(domainId)); } } @@ -92,7 +92,7 @@ public class LdapContextFactory { environment.put("com.sun.jndi.ldap.read.timeout", _ldapConfiguration.getReadTimeout(domainId).toString()); environment.put("com.sun.jndi.ldap.connect.pool", "true"); - enableSSL(environment); + enableSSL(environment, domainId); setAuthentication(environment, isSystemContext, domainId); if (principal != null) { diff --git a/plugins/user-authenticators/ldap/src/test/groovy/org/apache/cloudstack/ldap/LdapContextFactorySpec.groovy b/plugins/user-authenticators/ldap/src/test/groovy/org/apache/cloudstack/ldap/LdapContextFactorySpec.groovy index eead0bcd28c..6511edd5bf7 100644 --- a/plugins/user-authenticators/ldap/src/test/groovy/org/apache/cloudstack/ldap/LdapContextFactorySpec.groovy +++ b/plugins/user-authenticators/ldap/src/test/groovy/org/apache/cloudstack/ldap/LdapContextFactorySpec.groovy @@ -49,9 +49,9 @@ class LdapContextFactorySpec extends spock.lang.Specification { ldapConfiguration.getFirstnameAttribute() >> "givenname" ldapConfiguration.getLastnameAttribute() >> "sn" ldapConfiguration.getBaseDn(_) >> "dc=cloudstack,dc=org" - ldapConfiguration.getSSLStatus() >> true - ldapConfiguration.getTrustStore() >> "/tmp/ldap.ts" - ldapConfiguration.getTrustStorePassword() >> "password" + ldapConfiguration.getSSLStatus(domainId) >> true + ldapConfiguration.getTrustStore(domainId) >> "/tmp/ldap.ts" + ldapConfiguration.getTrustStorePassword(domainId) >> "password" ldapConfiguration.getReadTimeout(_) >> 1000 ldapConfiguration.getLdapPageSize() >> 1 diff --git a/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/ldap/LdapConfigurationTest.java b/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/ldap/LdapConfigurationTest.java index 2af20e79e36..5d1945215d9 100644 --- a/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/ldap/LdapConfigurationTest.java +++ b/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/ldap/LdapConfigurationTest.java @@ -78,7 +78,7 @@ public class LdapConfigurationTest { ldapTestConfigTool.overrideConfigValue(ldapConfiguration, "ldapTrustStore", "/tmp/ldap.ts"); ldapTestConfigTool.overrideConfigValue(ldapConfiguration, "ldapTrustStorePassword", "password"); - assertTrue("A request is made to get the status of SSL should result in true", ldapConfiguration.getSSLStatus()); + assertTrue("A request is made to get the status of SSL should result in true", ldapConfiguration.getSSLStatus(null)); } @Test public void getSearchGroupPrincipleReturnsSuccessfully() throws Exception { @@ -93,7 +93,7 @@ public class LdapConfigurationTest { // We have a ConfigDao with a value for truststore password ldapTestConfigTool.overrideConfigValue(ldapConfiguration, "ldapTrustStorePassword", "password"); - String result = ldapConfiguration.getTrustStorePassword(); + String result = ldapConfiguration.getTrustStorePassword(null); assertEquals("The result is password", "password", result); } From 2bd1dc1e149777ac42fb077bffb64bfa56c68ac4 Mon Sep 17 00:00:00 2001 From: Rakesh Date: Mon, 3 Jan 2022 21:55:30 +0100 Subject: [PATCH 3/4] Enable resetting config values to default value (#4230) * Enable resetting config values to default value Provide reset button to zone,cluster,domain,account, primary and secondary storage so that config values can be reset to default value * fix ui issue * Update test/integration/smoke/test_reset_configuration_settings.py * Update test/integration/smoke/test_reset_configuration_settings.py Co-authored-by: Rakesh Venkatesh Co-authored-by: dahn --- .../configuration/ConfigurationService.java | 10 + .../apache/cloudstack/api/ApiConstants.java | 1 + .../api/command/admin/config/ResetCfgCmd.java | 166 ++++++++ .../com/cloud/dc/ClusterDetailsDaoImpl.java | 28 +- .../ConfigurationManagerImpl.java | 204 +++++++++- .../cloud/server/ManagementServerImpl.java | 2 + .../vpc/MockConfigurationManagerImpl.java | 7 + .../test_reset_configuration_settings.py | 367 ++++++++++++++++++ tools/marvin/marvin/lib/base.py | 20 + ui/public/locales/en.json | 2 + ui/src/components/view/ListView.vue | 23 ++ ui/src/components/view/SettingsTab.vue | 28 ++ 12 files changed, 849 insertions(+), 9 deletions(-) create mode 100644 api/src/main/java/org/apache/cloudstack/api/command/admin/config/ResetCfgCmd.java create mode 100644 test/integration/smoke/test_reset_configuration_settings.py diff --git a/api/src/main/java/com/cloud/configuration/ConfigurationService.java b/api/src/main/java/com/cloud/configuration/ConfigurationService.java index 38d9d3243cf..87d2d2feaf1 100644 --- a/api/src/main/java/com/cloud/configuration/ConfigurationService.java +++ b/api/src/main/java/com/cloud/configuration/ConfigurationService.java @@ -18,6 +18,7 @@ package com.cloud.configuration; import java.util.List; +import org.apache.cloudstack.api.command.admin.config.ResetCfgCmd; import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; import org.apache.cloudstack.api.command.admin.network.CreateManagementNetworkIpRangeCmd; import org.apache.cloudstack.api.command.admin.network.CreateNetworkOfferingCmd; @@ -76,6 +77,15 @@ public interface ConfigurationService { */ Configuration updateConfiguration(UpdateCfgCmd cmd) throws InvalidParameterValueException; + /** + * Resets a configuration entry with default value + * + * @param cmd + * - the command wrapping name parameter + * @return updated configuration object if successful + */ + Pair resetConfiguration(ResetCfgCmd cmd) throws InvalidParameterValueException; + /** * Create a service offering through the API * diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index b19819c36f1..b9a809f9956 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -714,6 +714,7 @@ public class ApiConstants { public static final String VM_SNAPSHOT_MEMORY = "snapshotmemory"; public static final String VM_SNAPSHOT_QUIESCEVM = "quiescevm"; public static final String IMAGE_STORE_UUID = "imagestoreuuid"; + public static final String IMAGE_STORE_ID = "imagestoreid"; public static final String GUEST_VM_CIDR = "guestvmcidr"; public static final String NETWORK_CIDR = "networkcidr"; public static final String RESERVED_IP_RANGE = "reservediprange"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ResetCfgCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ResetCfgCmd.java new file mode 100644 index 00000000000..28a69cebc1e --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ResetCfgCmd.java @@ -0,0 +1,166 @@ +// 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. +package org.apache.cloudstack.api.command.admin.config; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.ImageStoreResponse; +import org.apache.cloudstack.framework.config.ConfigKey; +import org.apache.log4j.Logger; + +import org.apache.cloudstack.api.response.AccountResponse; +import org.apache.cloudstack.api.response.ClusterResponse; +import org.apache.cloudstack.api.response.ConfigurationResponse; +import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.cloudstack.config.Configuration; + +import com.cloud.user.Account; +import com.cloud.utils.Pair; + +@APICommand(name = "resetConfiguration", description = "Resets a configuration. The configuration will be set to default value for global setting, and removed from account_details or domain_details for Account/Domain settings", responseObject = ConfigurationResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.16.0") +public class ResetCfgCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(ResetCfgCmd.class.getName()); + private static final String s_name = "resetconfigurationresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "the name of the configuration", validations = {ApiArgValidator.NotNullOrEmpty}) + private String cfgName; + + @Parameter(name = ApiConstants.ZONE_ID, + type = CommandType.UUID, + entityType = ZoneResponse.class, + description = "the ID of the Zone to reset the parameter value for corresponding zone") + private Long zoneId; + + @Parameter(name = ApiConstants.CLUSTER_ID, + type = CommandType.UUID, + entityType = ClusterResponse.class, + description = "the ID of the Cluster to reset the parameter value for corresponding cluster") + private Long clusterId; + + @Parameter(name = ApiConstants.STORAGE_ID, + type = CommandType.UUID, + entityType = StoragePoolResponse.class, + description = "the ID of the Storage pool to reset the parameter value for corresponding storage pool") + private Long storagePoolId; + + @Parameter(name = ApiConstants.DOMAIN_ID, + type = CommandType.UUID, + entityType = DomainResponse.class, + description = "the ID of the Domain to reset the parameter value for corresponding domain") + private Long domainId; + + @Parameter(name = ApiConstants.ACCOUNT_ID, + type = CommandType.UUID, + entityType = AccountResponse.class, + description = "the ID of the Account to reset the parameter value for corresponding account") + private Long accountId; + + @Parameter(name = ApiConstants.IMAGE_STORE_ID, + type = CommandType.UUID, + entityType = ImageStoreResponse.class, + description = "the ID of the Image Store to reset the parameter value for corresponding image store") + private Long imageStoreId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public String getCfgName() { + return cfgName; + } + + public Long getZoneId() { + return zoneId; + } + + public Long getClusterId() { + return clusterId; + } + + public Long getStoragepoolId() { + return storagePoolId; + } + + public Long getDomainId() { + return domainId; + } + + public Long getAccountId() { + return accountId; + } + + public Long getImageStoreId() { + return imageStoreId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute() { + Pair cfg = _configService.resetConfiguration(this); + if (cfg != null) { + ConfigurationResponse response = _responseGenerator.createConfigurationResponse(cfg.first()); + response.setResponseName(getCommandName()); + if (getZoneId() != null) { + response.setScope(ConfigKey.Scope.Zone.name()); + } + if (getClusterId() != null) { + response.setScope(ConfigKey.Scope.Cluster.name()); + } + if (getStoragepoolId() != null) { + response.setScope(ConfigKey.Scope.StoragePool.name()); + } + if (getDomainId() != null) { + response.setScope(ConfigKey.Scope.Domain.name()); + } + if (getAccountId() != null) { + response.setScope(ConfigKey.Scope.Account.name()); + } + if (getImageStoreId() != null) { + response.setScope(ConfigKey.Scope.ImageStore.name()); + } + response.setValue(cfg.second()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to reset config"); + } + } +} diff --git a/engine/schema/src/main/java/com/cloud/dc/ClusterDetailsDaoImpl.java b/engine/schema/src/main/java/com/cloud/dc/ClusterDetailsDaoImpl.java index a9323229594..c2058ad5644 100644 --- a/engine/schema/src/main/java/com/cloud/dc/ClusterDetailsDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/dc/ClusterDetailsDaoImpl.java @@ -35,6 +35,11 @@ public class ClusterDetailsDaoImpl extends GenericDaoBase ClusterSearch; protected final SearchBuilder DetailSearch; + private final String CpuOverprovisioningFactor = "cpu.overprovisioning.factor"; + private final String MemoryOverprovisioningFactor = "mem.overprovisioning.factor"; + private final String CpuOverCommitRatio = "cpuOvercommitRatio"; + private final String MemoryOverCommitRatio = "memoryOvercommitRatio"; + protected ClusterDetailsDaoImpl() { ClusterSearch = createSearchBuilder(); ClusterSearch.and("clusterId", ClusterSearch.entity().getClusterId(), SearchCriteria.Op.EQ); @@ -50,12 +55,7 @@ public class ClusterDetailsDaoImpl extends GenericDaoBase sc = DetailSearch.create(); // This is temporary fix to support list/update configuration api for cpu and memory overprovisioning ratios - if (name.equalsIgnoreCase("cpu.overprovisioning.factor")) { - name = "cpuOvercommitRatio"; - } - if (name.equalsIgnoreCase("mem.overprovisioning.factor")) { - name = "memoryOvercommitRatio"; - } + name = getCpuMemoryOvercommitRatio(name); sc.setParameters("clusterId", clusterId); sc.setParameters("name", name); @@ -103,11 +103,13 @@ public class ClusterDetailsDaoImpl extends GenericDaoBase detail : details.entrySet()) { + String name = detail.getKey(); + name = getCpuMemoryOvercommitRatio(name); String value = detail.getValue(); if ("password".equals(detail.getKey())) { value = DBEncryptionUtil.encrypt(value); } - ClusterDetailsVO vo = new ClusterDetailsVO(clusterId, detail.getKey(), value); + ClusterDetailsVO vo = new ClusterDetailsVO(clusterId, name, value); persist(vo); } txn.commit(); @@ -115,6 +117,7 @@ public class ClusterDetailsDaoImpl extends GenericDaoBase sc = DetailSearch.create(); @@ -147,4 +150,15 @@ public class ClusterDetailsDaoImpl extends GenericDaoBase scopeMap) { + Long id = null; + int paramCount = 0; + String scope = ConfigKey.Scope.Global.toString(); + + for (var entry : scopeMap.entrySet()) { + if (entry.getValue() != null) { + id = entry.getValue(); + scope = entry.getKey(); + paramCount++; + } + } + + return new ParamCountPair(id, paramCount, scope); + } + + @Override + @ActionEvent(eventType = EventTypes.EVENT_CONFIGURATION_VALUE_EDIT, eventDescription = "resetting configuration") + public Pair resetConfiguration(final ResetCfgCmd cmd) throws InvalidParameterValueException { + final Long userId = CallContext.current().getCallingUserId(); + final String name = cmd.getCfgName(); + final Long zoneId = cmd.getZoneId(); + final Long clusterId = cmd.getClusterId(); + final Long storagepoolId = cmd.getStoragepoolId(); + final Long accountId = cmd.getAccountId(); + final Long domainId = cmd.getDomainId(); + final Long imageStoreId = cmd.getImageStoreId(); + Optional optionalValue; + final ConfigKey configKey = _configDepot.get(name); + if (configKey == null) { + s_logger.warn("Probably the component manager where configuration variable " + name + " is defined needs to implement Configurable interface"); + throw new InvalidParameterValueException("Config parameter with name " + name + " doesn't exist"); + } + String defaultValue = configKey.defaultValue(); + String category = configKey.category(); + String configScope = configKey.scope().toString(); + + String scope = ""; + Map scopeMap = new LinkedHashMap<>(); + + Long id = null; + int paramCountCheck = 0; + + scopeMap.put(ConfigKey.Scope.Zone.toString(), zoneId); + scopeMap.put(ConfigKey.Scope.Cluster.toString(), clusterId); + scopeMap.put(ConfigKey.Scope.Domain.toString(), domainId); + scopeMap.put(ConfigKey.Scope.Account.toString(), accountId); + scopeMap.put(ConfigKey.Scope.StoragePool.toString(), storagepoolId); + scopeMap.put(ConfigKey.Scope.ImageStore.toString(), imageStoreId); + + ParamCountPair paramCountPair = getParamCount(scopeMap); + id = paramCountPair.getId(); + paramCountCheck = paramCountPair.getParamCount(); + scope = paramCountPair.getScope(); + + if (paramCountCheck > 1) { + throw new InvalidParameterValueException("cannot handle multiple IDs, provide only one ID corresponding to the scope"); + } + + if (scope != null && !scope.equals(ConfigKey.Scope.Global.toString()) && !configScope.contains(scope)) { + throw new InvalidParameterValueException("Invalid scope id provided for the parameter " + name); + } + + String newValue = null; + switch (ConfigKey.Scope.valueOf(scope)) { + case Zone: + final DataCenterVO zone = _zoneDao.findById(id); + if (zone == null) { + throw new InvalidParameterValueException("unable to find zone by id " + id); + } + _dcDetailsDao.removeDetail(id, name); + optionalValue = Optional.ofNullable(configKey.valueIn(id)); + newValue = optionalValue.isPresent() ? optionalValue.get().toString() : defaultValue; + break; + + case Cluster: + final ClusterVO cluster = _clusterDao.findById(id); + if (cluster == null) { + throw new InvalidParameterValueException("unable to find cluster by id " + id); + } + ClusterDetailsVO clusterDetailsVO = _clusterDetailsDao.findDetail(id, name); + newValue = configKey.value().toString(); + if (name.equalsIgnoreCase("cpu.overprovisioning.factor") || name.equalsIgnoreCase("mem.overprovisioning.factor")) { + _clusterDetailsDao.persist(id, name, newValue); + } else if (clusterDetailsVO != null) { + _clusterDetailsDao.remove(clusterDetailsVO.getId()); + } + optionalValue = Optional.ofNullable(configKey.valueIn(id)); + newValue = optionalValue.isPresent() ? optionalValue.get().toString() : defaultValue; + break; + + case StoragePool: + final StoragePoolVO pool = _storagePoolDao.findById(id); + if (pool == null) { + throw new InvalidParameterValueException("unable to find storage pool by id " + id); + } + _storagePoolDetailsDao.removeDetail(id, name); + optionalValue = Optional.ofNullable(configKey.valueIn(id)); + newValue = optionalValue.isPresent() ? optionalValue.get().toString() : defaultValue; + break; + + case Domain: + final DomainVO domain = _domainDao.findById(id); + if (domain == null) { + throw new InvalidParameterValueException("unable to find domain by id " + id); + } + DomainDetailVO domainDetailVO = _domainDetailsDao.findDetail(id, name); + if (domainDetailVO != null) { + _domainDetailsDao.remove(domainDetailVO.getId()); + } + optionalValue = Optional.ofNullable(configKey.valueIn(id)); + newValue = optionalValue.isPresent() ? optionalValue.get().toString() : defaultValue; + break; + + case Account: + final AccountVO account = _accountDao.findById(id); + if (account == null) { + throw new InvalidParameterValueException("unable to find account by id " + id); + } + AccountDetailVO accountDetailVO = _accountDetailsDao.findDetail(id, name); + if (accountDetailVO != null) { + _accountDetailsDao.remove(accountDetailVO.getId()); + } + optionalValue = Optional.ofNullable(configKey.valueIn(id)); + newValue = optionalValue.isPresent() ? optionalValue.get().toString() : defaultValue; + break; + + case ImageStore: + final ImageStoreVO imageStoreVO = _imageStoreDao.findById(id); + if (imageStoreVO == null) { + throw new InvalidParameterValueException("unable to find the image store by id " + id); + } + ImageStoreDetailVO imageStoreDetailVO = _imageStoreDetailsDao.findDetail(id, name); + if (imageStoreDetailVO != null) { + _imageStoreDetailsDao.remove(imageStoreDetailVO.getId()); + } + optionalValue = Optional.ofNullable(configKey.valueIn(id)); + newValue = optionalValue.isPresent() ? optionalValue.get().toString() : defaultValue; + break; + + default: + if (!_configDao.update(name, category, defaultValue)) { + s_logger.error("Failed to reset configuration option, name: " + name + ", defaultValue:" + defaultValue); + throw new CloudRuntimeException("Failed to reset configuration value. Please contact Cloud Support."); + } + optionalValue = Optional.ofNullable(configKey.value()); + newValue = optionalValue.isPresent() ? optionalValue.get().toString() : defaultValue; + } + + CallContext.current().setEventDetails(" Name: " + name + " New Value: " + (name.toLowerCase().contains("password") ? "*****" : defaultValue == null ? "" : defaultValue)); + return new Pair(_configDao.findByName(name), newValue); + } + private String validateConfigurationValue(final String name, String value, final String scope) { final ConfigurationVO cfg = _configDao.findByName(name); @@ -7056,4 +7220,40 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati ENABLE_ACCOUNT_SETTINGS_FOR_DOMAIN, ENABLE_DOMAIN_SETTINGS_FOR_CHILD_DOMAIN }; } + + static class ParamCountPair { + private Long id; + private int paramCount; + private String scope; + + public ParamCountPair(Long id, int paramCount, String scope) { + this.id = id; + this.paramCount = paramCount; + this.scope = scope; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public int getParamCount() { + return paramCount; + } + + public void setParamCount(int paramCount) { + this.paramCount = paramCount; + } + + public String getScope() { + return scope; + } + + public void setScope(String scope) { + this.scope = scope; + } + } } diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index 2b79ff00be0..790a5709b0f 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -74,6 +74,7 @@ import org.apache.cloudstack.api.command.admin.cluster.UpdateClusterCmd; import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd; import org.apache.cloudstack.api.command.admin.config.ListDeploymentPlannersCmd; import org.apache.cloudstack.api.command.admin.config.ListHypervisorCapabilitiesCmd; +import org.apache.cloudstack.api.command.admin.config.ResetCfgCmd; import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; import org.apache.cloudstack.api.command.admin.config.UpdateHypervisorCapabilitiesCmd; import org.apache.cloudstack.api.command.admin.direct.download.RevokeTemplateDirectDownloadCertificateCmd; @@ -3009,6 +3010,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe cmdList.add(ListHypervisorCapabilitiesCmd.class); cmdList.add(UpdateCfgCmd.class); cmdList.add(UpdateHypervisorCapabilitiesCmd.class); + cmdList.add(ResetCfgCmd.class); cmdList.add(CreateDomainCmd.class); cmdList.add(DeleteDomainCmd.class); cmdList.add(ListDomainChildrenCmd.class); diff --git a/server/src/test/java/com/cloud/vpc/MockConfigurationManagerImpl.java b/server/src/test/java/com/cloud/vpc/MockConfigurationManagerImpl.java index 112d20ba847..81831e3667a 100644 --- a/server/src/test/java/com/cloud/vpc/MockConfigurationManagerImpl.java +++ b/server/src/test/java/com/cloud/vpc/MockConfigurationManagerImpl.java @@ -23,6 +23,7 @@ import java.util.Set; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.api.command.admin.config.ResetCfgCmd; import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; import org.apache.cloudstack.api.command.admin.network.CreateManagementNetworkIpRangeCmd; import org.apache.cloudstack.api.command.admin.network.CreateNetworkOfferingCmd; @@ -615,4 +616,10 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu return null; } + @Override + public Pair resetConfiguration(ResetCfgCmd cmd) throws InvalidParameterValueException { + // TODO Auto-generated method stub + return null; + } + } diff --git a/test/integration/smoke/test_reset_configuration_settings.py b/test/integration/smoke/test_reset_configuration_settings.py new file mode 100644 index 00000000000..edec6e4f511 --- /dev/null +++ b/test/integration/smoke/test_reset_configuration_settings.py @@ -0,0 +1,367 @@ +# 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 Local Modules +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import cloudstackTestCase, unittest +from marvin.lib.utils import (validateList, + cleanup_resources) +from marvin.lib.base import (Account, + Configurations, + Domain, + Cluster, + StoragePool) +from marvin.lib.common import (get_domain, + get_zone) + +class TestRestConfigurationSettings(cloudstackTestCase): + @classmethod + def setUpClass(self): + self.testClient = super( + TestRestConfigurationSettings, + self).getClsTestClient() + self.apiclient = self.testClient.getApiClient() + self.testdata = self.testClient.getParsedTestDataConfig() + + # Get Zone, Domain + self.domain = get_domain(self.apiclient) + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) + self._cleanup = [] + return + + @classmethod + def tearDownClass(cls): + super(TestRestConfigurationSettings, cls).tearDownClass() + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + + return + + def tearDown(self): + super(TestRestConfigurationSettings, self).tearDown() + return + + @attr(tags=["advanced", "advancedsg"], required_hardware="false") + def test_01_test_settings_for_domain(self): + """ + 1. Get the default value for the setting in domain scope + 2. Change the default value to new value + 3. Make sure updated value is same as new value + 4. Reset the config value + 5. Make sure that current value is same as default value + :return: + """ + config_name="ldap.basedn" + #1. Get default value + configs = Configurations.list( + self.apiclient, + name=config_name + ) + self.assertIsNotNone(configs, "Fail to get domain setting %s " % config_name) + + orig_value = str(configs[0].value) + new_value = "testing" + + #2. Update to new value + Configurations.update( + self.apiclient, + name=config_name, + value=new_value, + domainid=self.domain.id + ) + + configs = Configurations.list( + self.apiclient, + name=config_name, + domainid=self.domain.id + ) + self.assertIsNotNone(configs, "Fail to get domain setting %s " % config_name) + + #3. validate they are same + self.assertEqual(new_value, + str(configs[0].value), + "Failed to set new config value") + + #4. Reset the value + Configurations.reset( + self.apiclient, + name=config_name, + domainid=self.domain.id + ) + + #5. Make sure its same as original value + configs = Configurations.list( + self.apiclient, + name=config_name, + domainid=self.domain.id + ) + self.assertIsNotNone(configs, "Fail to get domain setting %s " % config_name) + + self.assertEqual(orig_value, + str(configs[0].value), + "Failed to reset the value") + + @attr(tags=["advanced", "advancedsg"], required_hardware="false") + def test_02_test_settings_for_account(self): + """ + 1. Get the default value for the setting in account scope + 2. Change the default value to new value + 3. Make sure updated value is same as new value + 4. Reset the config value + 5. Make sure that current value is same as default value + :return: + """ + accounts = Account.list( + self.apiclient, + domainid=self.domain.id, + listall=True + ) + + self.assertIsNotNone(accounts[0], + "There should be atleast 1 account in the zone") + + config_name = "enable.additional.vm.configuration" + #1. Get the default value + configs = Configurations.list( + self.apiclient, + name=config_name + ) + self.assertIsNotNone(configs, "Fail to get account setting %s " % config_name) + + orig_value = str(configs[0].value) + new_value = "true" + + Configurations.update( + self.apiclient, + name=config_name, + value=new_value, + accountid=accounts[0].id + ) + + configs = Configurations.list( + self.apiclient, + name=config_name, + accountid=accounts[0].id + ) + self.assertIsNotNone(configs, "Fail to get account setting %s " % config_name) + + self.assertEqual(new_value, + str(configs[0].value), + "Failed to set new config value") + + Configurations.reset( + self.apiclient, + name=config_name, + accountid=accounts[0].id + ) + + configs = Configurations.list( + self.apiclient, + name=config_name, + accountid=accounts[0].id + ) + self.assertIsNotNone(configs, "Fail to get account setting %s " % config_name) + + self.assertEqual(orig_value, + str(configs[0].value), + "Failed to reset the value") + + @attr(tags=["advanced", "advancedsg"], required_hardware="false") + def test_03_test_settings_for_cluster(self): + """ + 1. Get the default value for the setting in cluster scope + 2. Change the default value to new value + 3. Make sure updated value is same as new value + 4. Reset the config value + 5. Make sure that current value is same as default value + :return: + """ + cluster = Cluster.list( + self.apiclient + ) + + self.assertIsNotNone(cluster[0], + "There should be atleast 1 cluster in the zone") + + config_name = "cluster.storage.operations.exclude" + configs = Configurations.list( + self.apiclient, + name=config_name, + clusterid=cluster[0].id + ) + self.assertIsNotNone(configs, "Fail to get cluster setting %s " % config_name) + + orig_value = str(configs[0].value) + new_value = "true" + + Configurations.update( + self.apiclient, + name=config_name, + value=new_value, + clusterid=cluster[0].id + ) + + configs = Configurations.list( + self.apiclient, + name=config_name, + clusterid=cluster[0].id + ) + self.assertIsNotNone(configs, "Fail to get cluster setting %s " % config_name) + + self.assertEqual(new_value, + str(configs[0].value), + "Failed to set new config value") + + Configurations.reset( + self.apiclient, + name=config_name, + clusterid=cluster[0].id + ) + + configs = Configurations.list( + self.apiclient, + name=config_name, + clusterid=cluster[0].id + ) + self.assertIsNotNone(configs, "Fail to get cluster setting %s " % config_name) + + self.assertEqual(orig_value, + str(configs[0].value), + "Failed to reset the value") + + @attr(tags=["advanced", "advancedsg"], required_hardware="false") + def test_04_test_settings_for_storage(self): + """ + 1. Get the default value for the setting in storage scope + 2. Change the default value to new value + 3. Make sure updated value is same as new value + 4. Reset the config value + 5. Make sure that current value is same as default value + :return: + """ + storage = StoragePool.list( + self.apiclient + ) + + self.assertIsNotNone(storage[0], + "There should be atleast 1 primary storage pool in the zone") + + config_name = "vmware.create.full.clone" + configs = Configurations.list( + self.apiclient, + name=config_name, + storageid=storage[0].id + ) + self.assertIsNotNone(configs, "Fail to get storage pool setting %s " % config_name) + + orig_value = str(configs[0].value) + new_value = 'false' + + Configurations.update( + self.apiclient, + name=config_name, + value=new_value, + storageid=storage[0].id + ) + + configs = Configurations.list( + self.apiclient, + name=config_name, + storageid=storage[0].id + ) + self.assertIsNotNone(configs, "Fail to get storage pool setting %s " % config_name) + + self.assertEqual(new_value, + (configs[0].value), + "Failed to set new config value") + + Configurations.reset( + self.apiclient, + name=config_name, + storageid=storage[0].id + ) + + configs = Configurations.list( + self.apiclient, + name=config_name, + storage=storage[0].id + ) + self.assertIsNotNone(configs, "Fail to get storage pool setting %s " % config_name) + + self.assertEqual(orig_value, + (configs[0].value), + "Failed to reset the value for storage pool") + + @attr(tags=["advanced", "advancedsg"], required_hardware="false") + def test_05_test_settings_for_zone(self): + """ + 1. Get the default value for the setting in zone scope + 2. Change the default value to new value + 3. Make sure updated value is same as new value + 4. Reset the config value + 5. Make sure that current value is same as default value + :return: + """ + config_name = "enable.dynamic.scale.vm" + configs = Configurations.list( + self.apiclient, + name=config_name, + zoneid=self.zone.id + ) + self.assertIsNotNone(configs, "Fail to get zone setting %s " % config_name) + + orig_value = str(configs[0].value) + new_value = 'true' + + Configurations.update( + self.apiclient, + name=config_name, + value=new_value, + zoneid=self.zone.id + ) + + configs = Configurations.list( + self.apiclient, + name=config_name, + zoneid=self.zone.id + ) + self.assertIsNotNone(configs, "Fail to get ol setting %s " % config_name) + + self.assertEqual(new_value, + (configs[0].value), + "Failed to set new config value") + + Configurations.reset( + self.apiclient, + name=config_name, + zoneid=self.zone.id + ) + + configs = Configurations.list( + self.apiclient, + name=config_name, + zoneid=self.zone.id + ) + self.assertIsNotNone(configs, "Fail to get zone setting %s " % config_name) + + self.assertEqual(orig_value, + (configs[0].value), + "Failed to reset the value for zone") diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py index b8c1138e846..910e8bd7c04 100755 --- a/tools/marvin/marvin/lib/base.py +++ b/tools/marvin/marvin/lib/base.py @@ -4273,6 +4273,26 @@ class Configurations: return (apiclient.listCapabilities(cmd)) + @classmethod + def reset(cls, apiclient, name, zoneid=None, clusterid=None, storageid=None, domainid=None, accountid=None): + """Resets the specified configuration to original value""" + + cmd = resetConfiguration.resetConfigurationCmd() + cmd.name = name + + if zoneid: + cmd.zoneid = zoneid + if clusterid: + cmd.clusterid = clusterid + if storageid: + cmd.storageid = storageid + if domainid: + cmd.domainid = domainid + if accountid: + cmd.accountid = accountid + + apiclient.resetConfiguration(cmd) + class NetScaler: """Manage external netscaler device""" diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 135630e8167..9dbbd854a1d 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -1863,6 +1863,7 @@ "label.reservedsystemnetmask": "Reserved system netmask", "label.reservedsystemstartip": "Start Reserved system IP", "label.reset": "Reset", +"label.reset.config.value": "Reset to default value", "label.reset.ssh.key.pair": "Reset SSH Key Pair", "label.reset.ssh.key.pair.on.vm": "Reset SSH Key Pair on VM", "label.reset.to.default": "Reset to default", @@ -2943,6 +2944,7 @@ "message.error.rados.user": "Please enter RADOS User", "message.error.remove.nic": "There was an error", "message.error.remove.secondary.ipaddress": "There was an error removing the secondary IP Address", +"message.error.reset.config": "Unable to reset config to default value", "message.error.required.input": "Please enter input", "message.error.retrieve.kubeconfig": "Unable to retrieve Kubernetes cluster config", "message.error.s3nfs.path": "Please enter S3 NFS Path", diff --git a/ui/src/components/view/ListView.vue b/ui/src/components/view/ListView.vue index 7ea3e39a13d..2665035aa89 100644 --- a/ui/src/components/view/ListView.vue +++ b/ui/src/components/view/ListView.vue @@ -348,6 +348,12 @@ v-if="editableValueKey === record.key" iconType="check-circle" iconTwoToneColor="#52c41a" /> +