diff --git a/src/locales/en.json b/src/locales/en.json index 55fbc031..8a811447 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -539,6 +539,7 @@ "Created": "Created", "Created At": "Created At", "Created Time": "Created Time", + "Created Volumes": "Created Volumes", "Creating": "Creating", "Creating From Snapshot": "Creating From Snapshot", "Creation Timeout (Minutes)": "Creation Timeout (Minutes)", diff --git a/src/locales/zh.json b/src/locales/zh.json index 359c9db1..e74cca2b 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -539,6 +539,7 @@ "Created": "已创建", "Created At": "创建于", "Created Time": "创建时间", + "Created Volumes": "创建的云硬盘", "Creating": "创建中", "Creating From Snapshot": "正在从快照创建共享", "Creation Timeout (Minutes)": "创建超时(分钟)", diff --git a/src/pages/storage/containers/Snapshot/Detail/index.jsx b/src/pages/storage/containers/Snapshot/Detail/index.jsx index 953be6d9..b20eec6c 100644 --- a/src/pages/storage/containers/Snapshot/Detail/index.jsx +++ b/src/pages/storage/containers/Snapshot/Detail/index.jsx @@ -16,6 +16,7 @@ import { inject, observer } from 'mobx-react'; import { SnapshotStore } from 'stores/cinder/snapshot'; import Base from 'containers/TabDetail'; import { volumeStatus } from 'resources/cinder/volume'; +import Volumes from 'pages/storage/containers/Volume'; import BaseDetail from './BaseDetail'; import actionConfigs from '../actions'; @@ -68,6 +69,7 @@ export class Detail extends Base { } get tabs() { + const { child_volumes = [] } = this.detailData || {}; const tabs = [ { title: t('Detail'), @@ -75,6 +77,13 @@ export class Detail extends Base { component: BaseDetail, }, ]; + if (child_volumes && child_volumes.length) { + tabs.push({ + title: t('Created Volumes'), + key: 'volumes', + component: Volumes, + }); + } return tabs; } diff --git a/src/pages/storage/containers/Volume/index.jsx b/src/pages/storage/containers/Volume/index.jsx index 0eddfaf1..fd0c4c05 100644 --- a/src/pages/storage/containers/Volume/index.jsx +++ b/src/pages/storage/containers/Volume/index.jsx @@ -20,13 +20,16 @@ import { getVolumeColumnsList, } from 'resources/cinder/volume'; import globalVolumeStore, { VolumeStore } from 'stores/cinder/volume'; +import { SnapshotVolumeStore } from 'stores/cinder/snapshot-volume'; import { InstanceVolumeStore } from 'stores/nova/instance-volume'; import { emptyActionConfig } from 'utils/constants'; import actionConfigs from './actions'; export class Volume extends Base { init() { - if (this.inDetailPage) { + if (this.isVolumeSnapshotDetail) { + this.store = new SnapshotVolumeStore(); + } else if (this.inDetailPage) { this.store = new InstanceVolumeStore(); this.downloadStore = this.store; } else { @@ -47,12 +50,16 @@ export class Volume extends Base { return this.inDetailPage && this.path.includes('recycle-bin'); } + get isVolumeSnapshotDetail() { + return this.inDetailPage && this.path.includes('storage/snapshot'); + } + get actionConfigs() { if (this.isRecycleBinDetail) { return emptyActionConfig; } if (this.isAdminPage) { - return this.inDetailPage + return this.inDetailPage && !this.isVolumeSnapshotDetail ? actionConfigs.instanceDetailAdminConfig : actionConfigs.adminConfig; } @@ -90,6 +97,15 @@ export class Volume extends Base { } updateFetchParams = (params) => { + if (this.isVolumeSnapshotDetail) { + const { child_volumes = [] } = this.props.detail || {}; + const volumeIds = child_volumes.map((it) => it.volume_id); + const { id, ...rest } = params; + return { + ...rest, + volumeIds, + }; + } if (this.inDetailPage) { const { id, ...rest } = params; return { diff --git a/src/stores/cinder/snapshot-volume.js b/src/stores/cinder/snapshot-volume.js new file mode 100644 index 00000000..fe5e1871 --- /dev/null +++ b/src/stores/cinder/snapshot-volume.js @@ -0,0 +1,46 @@ +// Copyright 2021 99cloud +// +// Licensed 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 Base from 'stores/base'; +import { groupArray } from 'utils/index'; +import { updateVolume } from 'resources/cinder/volume'; + +export class SnapshotVolumeStore extends Base { + get mapper() { + return (volume) => updateVolume(volume); + } + + get groupArraySize() { + return 10; + } + + async requestList(params, filters) { + const { volumeIds = [] } = filters; + const idArray = groupArray(volumeIds, this.groupArraySize); + const results = await Promise.all( + idArray.map((it) => { + const newParams = { uuid: it, ...params }; + return this.skylineClient.extension.volumes(newParams); + }) + ); + const resultVolumes = []; + results.forEach((result) => { + resultVolumes.push(...result.volumes); + }); + return resultVolumes; + } +} + +const globalSnapshotVolumeStore = new SnapshotVolumeStore(); +export default globalSnapshotVolumeStore;