From e16951bde059ac94d4133c7c1ceb22a582d24a93 Mon Sep 17 00:00:00 2001 From: xusongfu Date: Fri, 22 Jul 2022 12:41:43 +0800 Subject: [PATCH] feat: support trove quota 1. support trove quota in manage project quota 2. support trove quota in overview page Change-Id: Iac2ea282744239fc043df2bdc456b7daba05de9b --- src/client/trove/index.js | 5 ++ src/locales/en.json | 2 + src/locales/zh.json | 2 + .../Overview/components/QuotaOverview.jsx | 26 +++++++- .../Project/actions/ManageQuota.jsx | 14 +++++ src/stores/keystone/project.js | 59 ++++++++++++++++++- src/stores/root.js | 4 ++ 7 files changed, 110 insertions(+), 2 deletions(-) diff --git a/src/client/trove/index.js b/src/client/trove/index.js index ccf23ea0..e1fa0cc7 100644 --- a/src/client/trove/index.js +++ b/src/client/trove/index.js @@ -108,6 +108,11 @@ export class TroveClient extends Base { }, ], }, + { + name: 'quotas', + key: 'mgmt/quotas', + responseKey: 'quota', + }, ]; } } diff --git a/src/locales/en.json b/src/locales/en.json index 0897d9f2..fbc78728 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -433,6 +433,7 @@ "Container Stopping": "Container Stopping", "Container Version": "Container Version", "Containers": "Containers", + "Containers Disk (GiB)": "Containers Disk (GiB)", "Containers Info": "Containers Info", "Containers Management": "Containers Management", "Content": "Content", @@ -593,6 +594,7 @@ "Data Source Type": "Data Source Type", "Database": "Database", "Database Backup Detail": "Database Backup Detail", + "Database Disk (GiB)": "Database Disk (GiB)", "Database Flavor": "Database Flavor", "Database Instance": "Database Instance", "Database Instance Detail": "Database Instance Detail", diff --git a/src/locales/zh.json b/src/locales/zh.json index ec98d9aa..137ea496 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -433,6 +433,7 @@ "Container Stopping": "容器关闭中", "Container Version": "容器版本", "Containers": "容器", + "Containers Disk (GiB)": "容器硬盘 (GiB)", "Containers Info": "容器信息", "Containers Management": "容器管理", "Content": "内容", @@ -593,6 +594,7 @@ "Data Source Type": "数据源类型", "Database": "数据库", "Database Backup Detail": "数据库备份详情", + "Database Disk (GiB)": "数据库硬盘 (GiB)", "Database Flavor": "数据库实例类型", "Database Instance": "数据库实例", "Database Instance Detail": "数据库实例详情", diff --git a/src/pages/base/containers/Overview/components/QuotaOverview.jsx b/src/pages/base/containers/Overview/components/QuotaOverview.jsx index fa6a256c..285d631f 100644 --- a/src/pages/base/containers/Overview/components/QuotaOverview.jsx +++ b/src/pages/base/containers/Overview/components/QuotaOverview.jsx @@ -114,7 +114,22 @@ export const zunQuotaCard = { }, { text: t('CPUs'), key: 'zun_cpu' }, { text: t('Memory (MiB)'), key: 'zun_memory' }, - { text: t('Disk (GiB)'), key: 'zun_disk' }, + { text: t('Containers Disk (GiB)'), key: 'zun_disk' }, + ], +}; + +export const troveQuotaCard = { + text: t('Database'), + type: 'trove', + value: [ + { + text: t('Database Instance'), + key: 'trove_instances', + }, + { + text: t('Database Disk (GiB)'), + key: 'trove_volumes', + }, ], }; @@ -195,6 +210,12 @@ export class QuotaOverview extends Component { return globalRootStore.checkEndpoint('zun'); } + get enableTrove() { + return ( + globalRootStore.checkEndpoint('trove') && globalRootStore.hasAdminOnlyRole + ); + } + get volumeTypeData() { const { volumeTypeData } = this.props; return volumeTypeData || this.volumeTypeStore.list.data; @@ -216,6 +237,9 @@ export class QuotaOverview extends Component { if (this.enableZun) { newList.push(zunQuotaCard); } + if (this.enableTrove) { + newList.push(troveQuotaCard); + } return newList; } diff --git a/src/pages/identity/containers/Project/actions/ManageQuota.jsx b/src/pages/identity/containers/Project/actions/ManageQuota.jsx index 7f11ea20..02029085 100644 --- a/src/pages/identity/containers/Project/actions/ManageQuota.jsx +++ b/src/pages/identity/containers/Project/actions/ManageQuota.jsx @@ -22,6 +22,7 @@ import { getVolumeTypeCards, shareQuotaCard, zunQuotaCard, + troveQuotaCard, } from 'pages/base/containers/Overview/components/QuotaOverview'; export class ManageQuota extends ModalAction { @@ -52,6 +53,13 @@ export class ManageQuota extends ModalAction { return this.props.rootStore.checkEndpoint('zun'); } + get enableTrove() { + return ( + this.props.rootStore.checkEndpoint('trove') && + this.props.rootStore.hasAdminOnlyRole + ); + } + async getData() { const { id: project_id } = this.item; const promiseArr = [ @@ -142,6 +150,9 @@ export class ManageQuota extends ModalAction { if (this.enableZun) { newQuotaCardList.push(zunQuotaCard); } + if (this.enableTrove) { + newQuotaCardList.push(troveQuotaCard); + } return newQuotaCardList; } @@ -196,6 +207,9 @@ export class ManageQuota extends ModalAction { if (this.enableZun) { form.push(...this.getFormItemsByCards('zun')); } + if (this.enableTrove) { + form.push(...this.getFormItemsByCards('trove')); + } if (this.enableCinder) { const cinderFormItems = this.getFormItemsByCards('storage'); const volumeTypeFormItems = this.getVolumeTypeFormItems(); diff --git a/src/stores/keystone/project.js b/src/stores/keystone/project.js index eb47f5c5..1b5c1ead 100644 --- a/src/stores/keystone/project.js +++ b/src/stores/keystone/project.js @@ -39,6 +39,9 @@ export class ProjectStore extends Base { @observable zunQuota = {}; + @observable + troveQuota = {}; + @observable groupRoleList = []; @@ -82,6 +85,10 @@ export class ProjectStore extends Base { return client.zun.quotas; } + get troveQuotaClient() { + return client.trove.quotas; + } + listFetchByClient(params, originParams) { const { userId } = originParams; if (userId) { @@ -213,6 +220,12 @@ export class ProjectStore extends Base { return globalRootStore.checkEndpoint('zun'); } + get enableTrove() { + return ( + globalRootStore.checkEndpoint('trove') && globalRootStore.hasAdminOnlyRole + ); + } + @action async enable({ id }) { const reqBody = { @@ -266,6 +279,9 @@ export class ProjectStore extends Base { }) : null ); + promiseArr.push( + this.enableTrove ? this.troveQuotaClient.show(project_id) : null + ); promiseArr.push(withKeyPair ? globalKeypairStore.fetchList() : null); const [ novaResult, @@ -273,6 +289,7 @@ export class ProjectStore extends Base { cinderResult, shareResult, zunResult, + troveResult, keyPairResult, ] = await Promise.all(promiseArr); this.isSubmitting = false; @@ -281,6 +298,7 @@ export class ProjectStore extends Base { const { quota: neutronQuota } = neutronResult; const { quota_set: shareQuota = {} } = shareResult || {}; const zunQuota = zunResult || {}; + const { quotas: troveQuota = [] } = troveResult || {}; this.updateNovaQuota(novaQuota); const renameShareQuota = Object.keys(shareQuota).reduce((pre, cur) => { const key = !cur.includes('share') ? `share_${cur}` : cur; @@ -292,12 +310,18 @@ export class ProjectStore extends Base { pre[key] = zunQuota[cur]; return pre; }, {}); + const renameTroveQuota = troveQuota.reduce((pre, cur) => { + const key = `trove_${cur.resource}`; + pre[key] = cur; + return pre; + }, {}); const quota = { ...novaQuota, ...cinderQuota, ...neutronQuota, ...renameShareQuota, ...renameZunQuota, + ...renameTroveQuota, }; if (withKeyPair) { const keyPairCount = (keyPairResult || []).length; @@ -353,7 +377,8 @@ export class ProjectStore extends Base { (key.includes('volumes') || key.includes('gigabytes') || key.includes('snapshots')) && - !key.includes('share') + !key.includes('share') && + !key.includes('trove') ) { rest[key] = others[key]; } @@ -421,12 +446,27 @@ export class ProjectStore extends Base { return zunReqBody; } + getTroveQuotaBody(data) { + if (!this.enableTrove) { + return {}; + } + const { trove_instances, trove_volumes } = data; + const troveReqBody = this.omitNil({ + quotas: { + instances: trove_instances, + volumes: trove_volumes, + }, + }); + return troveReqBody; + } + async updateQuota(project_id, data) { const novaReqBody = this.getNovaQuotaBody(data); const cinderReqBody = this.getCinderQuotaBody(data); const neutronReqBody = this.getNeutronQuotaBody(data); const shareReqBody = this.getShareQuotaBody(data); const zunReqBody = this.getZunQuotaBody(data); + const troveReqBody = this.getTroveQuotaBody(data); const reqs = []; if (!isEmpty(novaReqBody.quota_set)) { reqs.push(client.nova.quotaSets.update(project_id, novaReqBody)); @@ -443,6 +483,9 @@ export class ProjectStore extends Base { if (!isEmpty(zunReqBody)) { reqs.push(client.zun.quotas.update(project_id, zunReqBody)); } + if (!isEmpty(troveReqBody)) { + reqs.push(client.trove.quotas.update(project_id, troveReqBody)); + } const result = await Promise.all(reqs); return result; } @@ -581,6 +624,20 @@ export class ProjectStore extends Base { this.zunQuota = zunQuota; return zunQuota; } + + @action + async fetchProjectTroveQuota(projectId) { + const { quotas = [] } = await this.troveQuotaClient.show( + projectId || this.currentProjectId + ); + const quotasObject = quotas.reduce((pre, cur) => { + pre[cur.resource] = cur; + return pre; + }, {}); + const troveQuota = this.updateQuotaData(quotasObject); + this.troveQuota = troveQuota; + return troveQuota; + } } const globalProjectStore = new ProjectStore(); diff --git a/src/stores/root.js b/src/stores/root.js index aad2144b..4adeac52 100644 --- a/src/stores/root.js +++ b/src/stores/root.js @@ -48,6 +48,9 @@ export class RootStore { @observable hasAdminPageRole = false; + @observable + hasAdminOnlyRole = false; + @observable openKeys = []; @@ -135,6 +138,7 @@ export class RootStore { this.baseDomains = base_domains; this.hasAdminPageRole = await this.getUserSystemRoles(userInfo); this.hasAdminRole = this.hasAdminPageRole; + this.hasAdminOnlyRole = roles.some((it) => it.name === 'admin'); } @action