| // 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 #bodyCell="{ column, record }"> | |
| <template v-if="column.key === 'size'"> | |
| <span v-if="record.size"> | |
| {{ $bytesToHumanReadableSize(record.size) }} | |
| </span> | |
| </template> | |
| <template v-if="column.key === 'selectedstorage'"> | |
| <span>{{ record.selectedstoragename || '' }}</span> | |
| </template> | |
| <template v-if="column.key === 'select'"> | |
| <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> | |
| </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" | |
| :hostId="hostId" | |
| :autoAssignAllowed="storagePoolsClusterId != null" | |
| :isOpen="!(!selectedVolumeForStoragePoolSelection.id)" | |
| @close-action="closeVolumeStoragePoolSelector()" | |
| @select="handleVolumeStoragePoolSelection" /> | |
| </a-modal> | |
| </div> | |
| </template> | |
| <script> | |
| import { getAPI } 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 | |
| }, | |
| hostId: { | |
| type: String, | |
| required: false, | |
| default: null | |
| } | |
| }, | |
| data () { | |
| return { | |
| volumes: [], | |
| volumesLoading: false, | |
| volumeColumns: [ | |
| { | |
| key: 'name', | |
| title: this.$t('label.volumeid'), | |
| dataIndex: 'name' | |
| }, | |
| { | |
| key: 'type', | |
| title: this.$t('label.type'), | |
| dataIndex: 'type' | |
| }, | |
| { | |
| key: 'size', | |
| title: this.$t('label.size') | |
| }, | |
| { | |
| key: 'storage', | |
| title: this.$t('label.current.storage'), | |
| dataIndex: 'storage' | |
| }, | |
| { | |
| key: 'selectedstorage', | |
| title: this.$t('label.selected.storage') | |
| }, | |
| { | |
| key: 'select', | |
| title: '' | |
| } | |
| ], | |
| 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 = [] | |
| getAPI('listVolumes', { | |
| listAll: true, | |
| virtualmachineid: this.resource.id, | |
| listsystemvms: true | |
| }).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, applyToAll) { | |
| for (const volume of this.volumes) { | |
| if (applyToAll) { | |
| volume.selectedstorageid = storagePool.id | |
| volume.selectedstoragename = storagePool.name | |
| volume.selectedstorageclusterid = storagePool.clusterid | |
| } else { | |
| 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> |