| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| <template> |
| <div> |
| <a-table |
| class="top-spaced" |
| size="small" |
| style="max-height: 250px; overflow-y: auto" |
| :loading="volumesLoading" |
| :columns="volumeColumns" |
| :dataSource="volumes" |
| :pagination="false" |
| :rowKey="record => record.id"> |
| <template #size="{ record }"> |
| <span v-if="record.size"> |
| {{ $bytesToHumanReadableSize(record.size) }} |
| </span> |
| </template> |
| <template #selectedstorage="{ record }"> |
| <span>{{ record.selectedstoragename || '' }}</span> |
| </template> |
| <template #select="{ record }"> |
| <div style="display: flex; justify-content: flex-end;"><a-button @click="openVolumeStoragePoolSelector(record)">{{ record.selectedstorageid ? $t('label.change') : $t('label.select') }}</a-button></div> |
| </template> |
| </a-table> |
| |
| <a-modal |
| :visible="!(!selectedVolumeForStoragePoolSelection.id)" |
| :title="$t('label.select.ps')" |
| :closable="true" |
| :maskClosable="false" |
| :footer="null" |
| :cancelText="$t('label.cancel')" |
| @cancel="closeVolumeStoragePoolSelector()" |
| centered |
| width="auto"> |
| <volume-storage-pool-select-form |
| :resource="selectedVolumeForStoragePoolSelection" |
| :clusterId="storagePoolsClusterId" |
| :autoAssignAllowed="storagePoolsClusterId != null" |
| :isOpen="!(!selectedVolumeForStoragePoolSelection.id)" |
| @close-action="closeVolumeStoragePoolSelector()" |
| @select="handleVolumeStoragePoolSelection" /> |
| </a-modal> |
| </div> |
| </template> |
| |
| <script> |
| import { api } from '@/api' |
| import VolumeStoragePoolSelectForm from '@/components/view/VolumeStoragePoolSelectForm' |
| |
| export default { |
| name: 'InstanceVolumesStoragePoolSelectListView', |
| components: { |
| VolumeStoragePoolSelectForm |
| }, |
| props: { |
| resource: { |
| type: Object, |
| required: true |
| }, |
| clusterId: { |
| type: String, |
| required: false, |
| default: null |
| } |
| }, |
| data () { |
| return { |
| volumes: [], |
| volumesLoading: false, |
| volumeColumns: [ |
| { |
| title: this.$t('label.volumeid'), |
| dataIndex: 'name' |
| }, |
| { |
| title: this.$t('label.type'), |
| dataIndex: 'type' |
| }, |
| { |
| title: this.$t('label.size'), |
| slots: { customRender: 'size' } |
| }, |
| { |
| title: this.$t('label.storage'), |
| slots: { customRender: 'selectedstorage' } |
| }, |
| { |
| title: '', |
| slots: { customRender: 'select' } |
| } |
| ], |
| selectedVolumeForStoragePoolSelection: {}, |
| selectedClusterId: null, |
| volumesWithClusterStoragePool: [] |
| } |
| }, |
| beforeCreate () { |
| this.apiParams = {} |
| if (this.$route.meta.name === 'vm') { |
| this.apiConfig = this.$store.getters.apis.migrateVirtualMachineWithVolume || {} |
| this.apiConfig.params.forEach(param => { |
| this.apiParams[param.name] = param |
| }) |
| this.apiConfig = this.$store.getters.apis.migrateVirtualMachine || {} |
| this.apiConfig.params.forEach(param => { |
| if (!(param.name in this.apiParams)) { |
| this.apiParams[param.name] = param |
| } |
| }) |
| } else { |
| this.apiConfig = this.$store.getters.apis.migrateSystemVm || {} |
| this.apiConfig.params.forEach(param => { |
| if (!(param.name in this.apiParams)) { |
| this.apiParams[param.name] = param |
| } |
| }) |
| } |
| }, |
| created () { |
| this.fetchVolumes() |
| }, |
| computed: { |
| isSelectedVolumeOnlyClusterStoragePoolVolume () { |
| if (this.volumesWithClusterStoragePool.length !== 1) { |
| return false |
| } |
| for (const volume of this.volumesWithClusterStoragePool) { |
| if (volume.id === this.selectedVolumeForStoragePoolSelection.id) { |
| return true |
| } |
| } |
| return false |
| }, |
| storagePoolsClusterId () { |
| if (this.clusterId) { |
| return this.clusterId |
| } |
| return this.isSelectedVolumeOnlyClusterStoragePoolVolume ? null : this.selectedClusterId |
| } |
| }, |
| methods: { |
| fetchVolumes () { |
| this.volumesLoading = true |
| this.volumes = [] |
| api('listVolumes', { |
| listAll: true, |
| virtualmachineid: this.resource.id |
| }).then(response => { |
| var volumes = response.listvolumesresponse.volume |
| if (volumes && volumes.length > 0) { |
| volumes.sort((a, b) => { |
| return b.type.localeCompare(a.type) |
| }) |
| this.volumes = volumes |
| } |
| }).finally(() => { |
| this.resetSelection() |
| this.volumesLoading = false |
| }) |
| }, |
| resetSelection () { |
| var volumes = this.volumes |
| this.volumes = [] |
| for (var volume of volumes) { |
| if (this.clusterId) { |
| volume.selectedstorageid = -1 |
| volume.selectedstoragename = this.$t('label.auto.assign') |
| } else { |
| volume.selectedstorageid = null |
| volume.selectedstoragename = '' |
| } |
| delete volume.selectedstorageclusterid |
| } |
| this.volumes = volumes |
| this.updateVolumeToStoragePoolSelection() |
| }, |
| openVolumeStoragePoolSelector (volume) { |
| this.selectedVolumeForStoragePoolSelection = volume |
| }, |
| closeVolumeStoragePoolSelector () { |
| this.selectedVolumeForStoragePoolSelection = {} |
| }, |
| handleVolumeStoragePoolSelection (volumeId, storagePool) { |
| for (const volume of this.volumes) { |
| if (volume.id === volumeId) { |
| volume.selectedstorageid = storagePool.id |
| volume.selectedstoragename = storagePool.name |
| volume.selectedstorageclusterid = storagePool.clusterid |
| break |
| } |
| } |
| this.updateVolumeToStoragePoolSelection() |
| }, |
| updateVolumeToStoragePoolSelection () { |
| var clusterId = null |
| this.volumeToPoolSelection = [] |
| this.volumesWithClusterStoragePool = [] |
| for (const volume of this.volumes) { |
| if (volume.selectedstorageid && volume.selectedstorageid !== -1) { |
| this.volumeToPoolSelection.push({ volume: volume.id, pool: volume.selectedstorageid }) |
| } |
| if (!this.clusterId && volume.selectedstorageclusterid) { |
| clusterId = volume.selectedstorageclusterid |
| this.volumesWithClusterStoragePool.push(volume) |
| } |
| } |
| if (!this.clusterId) { |
| this.selectedClusterId = clusterId |
| for (const volume of this.volumes) { |
| if (this.selectedClusterId == null && volume.selectedstorageid === -1) { |
| volume.selectedstorageid = null |
| volume.selectedstoragename = '' |
| } |
| if (this.selectedClusterId && volume.selectedstorageid == null) { |
| volume.selectedstorageid = -1 |
| volume.selectedstoragename = this.$t('label.auto.assign') |
| } |
| } |
| } |
| this.$emit('select', this.volumeToPoolSelection) |
| } |
| } |
| } |
| </script> |
| |
| <style scoped lang="less"> |
| .top-spaced { |
| margin-top: 20px; |
| } |
| </style> |