From d0e71adbbf53bcaca51c42ec07ed4f2b716a673d Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 24 Feb 2021 17:46:01 +0530 Subject: [PATCH 1/8] packaging: update Requirements in README (#4725) Signed-off-by: Abhishek Kumar --- packaging/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/README.md b/packaging/README.md index 9c54ea61fc7..634b1cf98a2 100644 --- a/packaging/README.md +++ b/packaging/README.md @@ -6,9 +6,9 @@ These scripts are also used by the CloudStack team to build packages for the off # Requirements The RPM and DEB packages have dependencies on versions of specific libraries. Due to these dependencies the following distributions and their versions are supported by the packages. -* CentOS / RHEL: 7 +* CentOS / RHEL: 7 and 8 * Debian 7 (Wheezy) and 8 (Jessy) (untested!) -* Ubuntu: 16.04 (Xenial) and 18.04 (Bionic) +* Ubuntu: 16.04 (Xenial), 18.04 (Bionic) and 20.04 (Focal) # Building Using the scripts in the *packaging* directory the RPM and DEB packages can be build. From 1545bf8dac878e99613d71b0f5de19668a5d398e Mon Sep 17 00:00:00 2001 From: Hoang Nguyen Date: Thu, 25 Feb 2021 23:28:42 +0700 Subject: [PATCH 2/8] ui: add missing antd component use (#4728) Fixes #4724 --- ui/src/core/lazy_lib/components_use.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ui/src/core/lazy_lib/components_use.js b/ui/src/core/lazy_lib/components_use.js index b99af3c1874..e9b7c83e5d5 100644 --- a/ui/src/core/lazy_lib/components_use.js +++ b/ui/src/core/lazy_lib/components_use.js @@ -63,7 +63,9 @@ import { Pagination, Comment, Tree, - Calendar + Calendar, + Slider, + AutoComplete } from 'ant-design-vue' Vue.use(ConfigProvider) @@ -110,6 +112,8 @@ Vue.use(Pagination) Vue.use(Comment) Vue.use(Tree) Vue.use(Calendar) +Vue.use(Slider) +Vue.use(AutoComplete) Vue.prototype.$confirm = Modal.confirm Vue.prototype.$message = message From a234501172a7948c13a50eb0ae87e8f1d1e68d0b Mon Sep 17 00:00:00 2001 From: Hoang Nguyen Date: Thu, 25 Feb 2021 23:31:40 +0700 Subject: [PATCH 3/8] ui: Add guest IP ranges (#4716) Fixes #4697 --- ui/src/config/section/network.js | 4 + .../views/infra/network/IpRangesTabGuest.vue | 8 +- .../views/infra/network/TrafficTypesTab.vue | 4 +- ui/src/views/network/CreateVlanIpRange.vue | 285 ++++++++++++++++++ ui/src/views/network/GuestIpRanges.vue | 196 ++++++++++++ 5 files changed, 495 insertions(+), 2 deletions(-) create mode 100644 ui/src/views/network/CreateVlanIpRange.vue create mode 100644 ui/src/views/network/GuestIpRanges.vue diff --git a/ui/src/config/section/network.js b/ui/src/config/section/network.js index 29b57e2f3f5..e3fc40f9b31 100644 --- a/ui/src/config/section/network.js +++ b/ui/src/config/section/network.js @@ -53,6 +53,10 @@ export default { name: 'virtual.routers', component: () => import('@/views/network/RoutersTab.vue'), show: (record) => { return (record.type === 'Isolated' || record.type === 'Shared') && 'listRouters' in store.getters.apis } + }, { + name: 'guest.ip.range', + component: () => import('@/views/network/GuestIpRanges.vue'), + show: (record) => { return 'listVlanIpRanges' in store.getters.apis && (record.type === 'Shared' || (record.service && record.service.filter(x => x.name === 'SourceNat').count === 0)) } }], actions: [ { diff --git a/ui/src/views/infra/network/IpRangesTabGuest.vue b/ui/src/views/infra/network/IpRangesTabGuest.vue index f70d7a574f7..49d63f7cbf1 100644 --- a/ui/src/views/infra/network/IpRangesTabGuest.vue +++ b/ui/src/views/infra/network/IpRangesTabGuest.vue @@ -34,6 +34,11 @@ :rowKey="record => record.id" :pagination="false" > + + +
+
+ + + + {{ $t('label.gateway') }} + + + + + + + + + {{ $t('label.netmask') }} + + + + + + + + + + + {{ $t('label.startipv4') }} + + + + + + + + + + + {{ $t('label.endipv4') }} + + + + + + + + + + + {{ $t('label.ip6cidr') }} + + + + + + + + + {{ $t('label.ip6gateway') }} + + + + + + + + + + + {{ $t('label.startipv6') }} + + + + + + + + + + + {{ $t('label.endipv6') }} + + + + + + + + +
+ + {{ this.$t('label.cancel') }} + + + {{ this.$t('label.ok') }} + +
+
+
+
+
+ + + + + diff --git a/ui/src/views/network/GuestIpRanges.vue b/ui/src/views/network/GuestIpRanges.vue new file mode 100644 index 00000000000..a2e364af7a6 --- /dev/null +++ b/ui/src/views/network/GuestIpRanges.vue @@ -0,0 +1,196 @@ +// 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. + + + From fef0e66764faaa75a18f533af1b7b31fefc5974f Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 25 Feb 2021 22:04:00 +0530 Subject: [PATCH 4/8] ui: fix add Vmware cluster (#4663) When adding a cluster from existing host-datacenter UI shoudl list and autofill host, DC name while making addCluster API call. Signed-off-by: Abhishek Kumar --- ui/src/views/infra/ClusterAdd.vue | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/ui/src/views/infra/ClusterAdd.vue b/ui/src/views/infra/ClusterAdd.vue index a0665fe92d3..f4c03fe96a0 100644 --- a/ui/src/views/infra/ClusterAdd.vue +++ b/ui/src/views/infra/ClusterAdd.vue @@ -216,11 +216,35 @@ export default { if (this.hypervisor === 'VMware') { this.clustertype = 'ExternalManaged' + if ((this.host === null || this.host.length === 0) && + (this.dataCenter === null || this.dataCenter.length === 0)) { + api('listVmwareDcs', { + zoneid: this.zoneId + }).then(response => { + var vmwaredcs = response.listvmwaredcsresponse.VMwareDC + if (vmwaredcs !== null) { + this.host = vmwaredcs[0].vcenter + this.dataCenter = vmwaredcs[0].name + } + this.addCluster() + }).catch(error => { + this.$notification.error({ + message: `${this.$t('label.error')} ${error.response.status}`, + description: error.response.data.listvmwaredcsresponse.errortext, + duration: 0 + }) + }) + return + } + } + this.addCluster() + }, + addCluster () { + if (this.hypervisor === 'VMware') { const clusternameVal = this.clustername this.url = `http://${this.host}/${this.dataCenter}/${clusternameVal}` this.clustername = `${this.host}/${this.dataCenter}/${clusternameVal}` } - this.loading = true this.parentToggleLoading() api('addCluster', {}, 'POST', { From 787491871a9a1580b95003220965d0be885f11bf Mon Sep 17 00:00:00 2001 From: Rakesh Date: Thu, 25 Feb 2021 17:35:31 +0100 Subject: [PATCH 5/8] server: Look for active templates for VR deployment (#4047) If the template from which VR is created got deleted, the state is set to inactive and removed to null. Since the template is already deleted, the VR can't be created using this template again. If someone restarts network with cleanup then it will try to deploy the vr from the old non existing template again. So search only for active template which are not yet deleted. --- .../src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java index 6caef20b2d7..a3bebfa332f 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java @@ -376,6 +376,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem tmpltTypeHyperSearch2.and("templateType", tmpltTypeHyperSearch2.entity().getTemplateType(), SearchCriteria.Op.EQ); tmpltTypeHyperSearch2.and("hypervisorType", tmpltTypeHyperSearch2.entity().getHypervisorType(), SearchCriteria.Op.EQ); tmpltTypeHyperSearch2.and("templateName", tmpltTypeHyperSearch2.entity().getName(), SearchCriteria.Op.EQ); + tmpltTypeHyperSearch2.and("state", tmpltTypeHyperSearch2.entity().getState(), SearchCriteria.Op.EQ); tmpltTypeSearch = createSearchBuilder(); tmpltTypeSearch.and("state", tmpltTypeSearch.entity().getState(), SearchCriteria.Op.EQ); @@ -897,6 +898,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem SearchCriteria sc = tmpltTypeHyperSearch2.create(); sc.setParameters("templateType", TemplateType.ROUTING); sc.setParameters("hypervisorType", hType); + sc.setParameters("state", VirtualMachineTemplate.State.Active.toString()); if (templateName != null) { sc.setParameters("templateName", templateName); } @@ -911,6 +913,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem sc = tmpltTypeHyperSearch2.create(); sc.setParameters("templateType", TemplateType.SYSTEM); sc.setParameters("hypervisorType", hType); + sc.setParameters("state", VirtualMachineTemplate.State.Active.toString()); if (templateName != null) { sc.setParameters("templateName", templateName); } From af0f6422ec512a5c0c8d570e14f11327e82efd96 Mon Sep 17 00:00:00 2001 From: Greg Goodrich <54906463+ggoodrich-ipp@users.noreply.github.com> Date: Thu, 25 Feb 2021 10:41:00 -0600 Subject: [PATCH 6/8] =?UTF-8?q?kvm:=20Suspending=20the=20VM=20prior=20to?= =?UTF-8?q?=20deleting=20snapshots=20to=20avoid=20corruption,=20th?= =?UTF-8?q?=E2=80=A6=20(#4032)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These changes are related to PR #3194, but include suspending/resuming the VM when doing a VM snapshot as well, when deleting a VM snapshot, as it is performing the same operations via Libvirt. Also, there was an issue with the UI/localization changes in the prior PR, as that PR was altering the Volume snapshot behavior, but was altering the VM snapshot wording. Both have been altered in this PR. Issuing this in response to the work happening in PR #4029. --- ...LibvirtDeleteVMSnapshotCommandWrapper.java | 36 ++++++++++++++----- .../kvm/storage/KVMStorageProcessor.java | 2 +- ui/legacy/l10n/ar.js | 1 + ui/legacy/l10n/ca.js | 1 + ui/legacy/l10n/de_DE.js | 1 + ui/legacy/l10n/en.js | 3 +- ui/legacy/l10n/es.js | 1 + ui/legacy/l10n/fr_FR.js | 1 + ui/legacy/l10n/hu.js | 1 + ui/legacy/l10n/it_IT.js | 1 + ui/legacy/l10n/ja_JP.js | 1 + ui/legacy/l10n/ko_KR.js | 1 + ui/legacy/l10n/nb_NO.js | 1 + ui/legacy/l10n/nl_NL.js | 1 + ui/legacy/l10n/pl.js | 1 + ui/legacy/l10n/pt_BR.js | 1 + ui/legacy/l10n/ru_RU.js | 1 + ui/legacy/l10n/zh_CN.js | 1 + ui/legacy/scripts/storage.js | 2 +- 19 files changed, 47 insertions(+), 11 deletions(-) diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtDeleteVMSnapshotCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtDeleteVMSnapshotCommandWrapper.java index a0faa37ac12..5b55db24f4d 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtDeleteVMSnapshotCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtDeleteVMSnapshotCommandWrapper.java @@ -24,7 +24,7 @@ import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.log4j.Logger; import org.libvirt.Connect; import org.libvirt.Domain; -import org.libvirt.DomainInfo.DomainState; +import org.libvirt.DomainInfo; import org.libvirt.DomainSnapshot; import org.libvirt.LibvirtException; @@ -52,18 +52,33 @@ public final class LibvirtDeleteVMSnapshotCommandWrapper extends CommandWrapper< final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr(); Domain dm = null; DomainSnapshot snapshot = null; + DomainInfo.DomainState oldState = null; + boolean tryingResume = false; + Connect conn = null; try { final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper(); - Connect conn = libvirtUtilitiesHelper.getConnection(); + conn = libvirtUtilitiesHelper.getConnection(); dm = libvirtComputingResource.getDomain(conn, vmName); snapshot = dm.snapshotLookupByName(cmd.getTarget().getSnapshotName()); - s_logger.debug("Suspending domain " + vmName); - dm.suspend(); // suspend the vm to avoid image corruption + oldState = dm.getInfo().state; + if (oldState == DomainInfo.DomainState.VIR_DOMAIN_RUNNING) { + s_logger.debug("Suspending domain " + vmName); + dm.suspend(); // suspend the vm to avoid image corruption + } snapshot.delete(0); // only remove this snapshot, not children + if (oldState == DomainInfo.DomainState.VIR_DOMAIN_RUNNING) { + // Resume the VM + tryingResume = true; + dm = libvirtComputingResource.getDomain(conn, vmName); + if (dm.getInfo().state == DomainInfo.DomainState.VIR_DOMAIN_PAUSED) { + dm.resume(); + } + } + return new DeleteVMSnapshotAnswer(cmd, cmd.getVolumeTOs()); } catch (LibvirtException e) { String msg = " Delete VM snapshot failed due to " + e.toString(); @@ -97,21 +112,26 @@ public final class LibvirtDeleteVMSnapshotCommandWrapper extends CommandWrapper< } else if (snapshot == null) { s_logger.debug("Can not find vm snapshot " + cmd.getTarget().getSnapshotName() + " on vm: " + vmName + ", return true"); return new DeleteVMSnapshotAnswer(cmd, cmd.getVolumeTOs()); + } else if (tryingResume) { + s_logger.error("Failed to resume vm after delete snapshot " + cmd.getTarget().getSnapshotName() + " on vm: " + vmName + " return true : " + e); + return new DeleteVMSnapshotAnswer(cmd, cmd.getVolumeTOs()); } s_logger.warn(msg, e); return new DeleteVMSnapshotAnswer(cmd, false, msg); } finally { if (dm != null) { + // Make sure if the VM is paused, then resume it, in case we got an exception during our delete() and didn't have the chance before try { - if (dm.getInfo().state == DomainState.VIR_DOMAIN_PAUSED) { + dm = libvirtComputingResource.getDomain(conn, vmName); + if (oldState == DomainInfo.DomainState.VIR_DOMAIN_RUNNING && dm.getInfo().state == DomainInfo.DomainState.VIR_DOMAIN_PAUSED) { s_logger.debug("Resuming domain " + vmName); dm.resume(); } dm.free(); - } catch (LibvirtException l) { - s_logger.trace("Ignoring libvirt error.", l); - }; + } catch (LibvirtException e) { + s_logger.error("Failed to resume vm after delete snapshot " + cmd.getTarget().getSnapshotName() + " on vm: " + vmName + " return true : " + e); + } } } } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java index cc47c553283..016a13e95c2 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java @@ -1031,7 +1031,7 @@ public class KVMStorageProcessor implements StorageProcessor { } } } catch (final Exception ex) { - s_logger.debug("Failed to delete snapshots on primary", ex); + s_logger.error("Failed to delete snapshots on primary", ex); } } diff --git a/ui/legacy/l10n/ar.js b/ui/legacy/l10n/ar.js index acfc5539c2a..d45f6dc93c1 100644 --- a/ui/legacy/l10n/ar.js +++ b/ui/legacy/l10n/ar.js @@ -1888,6 +1888,7 @@ var dictionary = { "message.action.stop.router": "All services provided by this virtual router will be interrupted. Please confirm that you want to stop this router.", "message.action.stop.systemvm": "Please confirm that you want to stop this system VM.", "message.action.take.snapshot": "Please confirm that you want to take a snapshot of this volume.", + "message.action.snapshot.fromsnapshot":"Please confirm that you want to take a snapshot of this VM snapshot.", "message.action.unmanage.cluster": "Please confirm that you want to unmanage the cluster.", "message.action.vmsnapshot.create": "Please confirm that you want to take a snapshot of this instance.
Please notice that the instance will be paused during the snapshoting, and resumed after snapshotting, if it runs on KVM.", "message.action.vmsnapshot.delete": "Please confirm that you want to delete this VM snapshot.", diff --git a/ui/legacy/l10n/ca.js b/ui/legacy/l10n/ca.js index 3a7c0459402..19920407f47 100644 --- a/ui/legacy/l10n/ca.js +++ b/ui/legacy/l10n/ca.js @@ -1888,6 +1888,7 @@ var dictionary = { "message.action.stop.router": "All services provided by this virtual router will be interrupted. Please confirm that you want to stop this router.", "message.action.stop.systemvm": "Please confirm that you want to stop this system VM.", "message.action.take.snapshot": "Please confirm that you want to take a snapshot of this volume.", + "message.action.snapshot.fromsnapshot":"Please confirm that you want to take a snapshot of this VM snapshot.", "message.action.unmanage.cluster": "Please confirm that you want to unmanage the cluster.", "message.action.vmsnapshot.create": "Please confirm that you want to take a snapshot of this instance.
Please notice that the instance will be paused during the snapshoting, and resumed after snapshotting, if it runs on KVM.", "message.action.vmsnapshot.delete": "Please confirm that you want to delete this VM snapshot.", diff --git a/ui/legacy/l10n/de_DE.js b/ui/legacy/l10n/de_DE.js index 4fbc827c013..cfa28116aae 100644 --- a/ui/legacy/l10n/de_DE.js +++ b/ui/legacy/l10n/de_DE.js @@ -1890,6 +1890,7 @@ var dictionary = { "message.action.stop.router": "Alle von diesem Router angebotenen Dienste werden unterbrochen. Bitte bestätigen Sie, dass Sie diesen Router stoppen möchten.", "message.action.stop.systemvm": "Bitte bestätigen Sie, dass Sie diese System-VM stoppen möchten.", "message.action.take.snapshot": "Bitte bestätigen Sie, dass Sie einen Schnappschuss von diesem Volumen sichern möchten.", + "message.action.snapshot.fromsnapshot":"Bitte bestätigen Sie, dass Sie einen Schnappschuss von diesem VM Schnappschuss sichern möchten.", "message.action.unmanage.cluster": "Bitte bestätigen Sie, dass Sie das Cluster vernachlässigen möchten.", "message.action.vmsnapshot.create": "Please confirm that you want to take a snapshot of this instance.
Please notice that the instance will be paused during the snapshoting, and resumed after snapshotting, if it runs on KVM.", "message.action.vmsnapshot.delete": "Bitte bestätigen Sie, dass Sie diesen VM Schnappschuss löschen wollen.", diff --git a/ui/legacy/l10n/en.js b/ui/legacy/l10n/en.js index 8e25c54b04c..866b0674f21 100644 --- a/ui/legacy/l10n/en.js +++ b/ui/legacy/l10n/en.js @@ -2048,7 +2048,8 @@ var dictionary = { "message.action.stop.router":"All services provided by this virtual router will be interrupted. Please confirm that you want to stop this router.", "message.action.router.health.checks":"Health checks result will be fetched from router.", "message.action.stop.systemvm":"Please confirm that you want to stop this system VM.", -"message.action.take.snapshot":"Please confirm that you want to take a snapshot of this volume.", +"message.action.take.snapshot":"Please confirm that you want to take a snapshot of this volume.
Note that if this volume is in use by an instance running on KVM, the instance will be paused prior to, and resumed after creation of the snapshot", +"message.action.snapshot.fromsnapshot":"Please confirm that you want to take a snapshot of this VM snapshot.", "message.action.unmanage.cluster":"Please confirm that you want to unmanage the cluster.", "message.action.vmsnapshot.create":"Please confirm that you want to take a snapshot of this instance.
Please notice that the instance will be paused during the snapshoting, and resumed after snapshotting, if it runs on KVM.", "message.action.vmsnapshot.delete":"Please confirm that you want to delete this VM snapshot.
Please notice that the instance will be paused before the snapshot deletion, and resumed after deletion, if it runs on KVM.", diff --git a/ui/legacy/l10n/es.js b/ui/legacy/l10n/es.js index 875b7a16d32..7772cdbc46c 100644 --- a/ui/legacy/l10n/es.js +++ b/ui/legacy/l10n/es.js @@ -1889,6 +1889,7 @@ var dictionary = { "message.action.stop.router": "Todos los servicios provistos por este router virtual serán interrumpidos. Por favor confirmar que desea apagarlo.", "message.action.stop.systemvm": "Por favor, confirme que desea detener esta MV de Sistema. ", "message.action.take.snapshot": "Por favor, confirme que desea tomar una instantánea de este volúmen.", + "message.action.snapshot.fromsnapshot":"Por favor, confirme que desea tomar una instantánea de este instantánea VM.", "message.action.unmanage.cluster": "Por favor, confirme que desea dejar de gestionar el Clúster.", "message.action.vmsnapshot.create": "Please confirm that you want to take a snapshot of this instance.
Please notice that the instance will be paused during the snapshoting, and resumed after snapshotting, if it runs on KVM.", "message.action.vmsnapshot.delete": "Por favor confirme que desea borrar esta instantánea de la MV.", diff --git a/ui/legacy/l10n/fr_FR.js b/ui/legacy/l10n/fr_FR.js index 92eb8de3e8b..988f6a4a950 100644 --- a/ui/legacy/l10n/fr_FR.js +++ b/ui/legacy/l10n/fr_FR.js @@ -1890,6 +1890,7 @@ var dictionary = { "message.action.stop.router": "Tous les services fournit par ce routeur virtuel vont être interrompus. Confirmer l'arrêt de ce routeur.", "message.action.stop.systemvm": "Arrêter cette VM ?", "message.action.take.snapshot": "Confirmer la prise d'un instantané pour ce volume.", + "message.action.snapshot.fromsnapshot":"Confirmer la prise d'un instantané pour ce instantané VM.", "message.action.unmanage.cluster": "Confirmez que vous ne voulez plus gérer le cluster", "message.action.vmsnapshot.create": "Veuillez confirmer que vous souhaitez prendre un instantané de cette instance.
Notez que l'instance sera mise en pause durant la prise de l'instantané puis remise en route une fois terminée, si elle fonctionne sur KVM.", "message.action.vmsnapshot.delete": "Confirmez que vous souhaitez supprimer cet instantané VM.", diff --git a/ui/legacy/l10n/hu.js b/ui/legacy/l10n/hu.js index 6912c1ab624..ad165193187 100644 --- a/ui/legacy/l10n/hu.js +++ b/ui/legacy/l10n/hu.js @@ -1888,6 +1888,7 @@ var dictionary = { "message.action.stop.router": "Minden ezzel a routerrel kapcsolatos szolgáltatás megszakad. Erősítsd meg, hogy le akarod állítani ezt a routert!", "message.action.stop.systemvm": "Erősítsd meg, hogy le akarod állítani ezt a rendszer VM-et!", "message.action.take.snapshot": "Erősítsd meg, hogy pillanatfelvételt kérsz erről a kötetről!", + "message.action.snapshot.fromsnapshot":"Erősítsd meg, hogy pillanatfelvételt kérsz erről a VM pillanatfelvételt!", "message.action.unmanage.cluster": "Erősítsd meg, hogy megszakítod a fürt vezérlését!", "message.action.vmsnapshot.create": "Please confirm that you want to take a snapshot of this instance.
Please notice that the instance will be paused during the snapshoting, and resumed after snapshotting, if it runs on KVM.", "message.action.vmsnapshot.delete": "Erősítsd meg, hogy törölni akarod ezt a VM pillanatfelvételt!", diff --git a/ui/legacy/l10n/it_IT.js b/ui/legacy/l10n/it_IT.js index 4c3ed120887..37da3f99f36 100644 --- a/ui/legacy/l10n/it_IT.js +++ b/ui/legacy/l10n/it_IT.js @@ -1888,6 +1888,7 @@ var dictionary = { "message.action.stop.router": "Tutti i servizi forniti da questo router virtuale saranno interrotti. Si prega di confermare di voler arrestare questo router.", "message.action.stop.systemvm": "Please confirm that you want to stop this system VM.", "message.action.take.snapshot": "Please confirm that you want to take a snapshot of this volume.", + "message.action.snapshot.fromsnapshot":"Please confirm that you want to take a snapshot of this VM snapshot.", "message.action.unmanage.cluster": "Please confirm that you want to unmanage the cluster.", "message.action.vmsnapshot.create": "Please confirm that you want to take a snapshot of this instance.
Please notice that the instance will be paused during the snapshoting, and resumed after snapshotting, if it runs on KVM.", "message.action.vmsnapshot.delete": "Please confirm that you want to delete this VM snapshot.", diff --git a/ui/legacy/l10n/ja_JP.js b/ui/legacy/l10n/ja_JP.js index b876d334629..b3d114b64b9 100644 --- a/ui/legacy/l10n/ja_JP.js +++ b/ui/legacy/l10n/ja_JP.js @@ -1890,6 +1890,7 @@ var dictionary = { "message.action.stop.router": "この仮想ルーターで提供するすべてのサービスが中断されます。このルーターを停止してもよろしいですか?", "message.action.stop.systemvm": "このシステム VM を停止してもよろしいですか?", "message.action.take.snapshot": "このボリュームのスナップショットを作成してもよろしいですか?", + "message.action.snapshot.fromsnapshot":"このVMスナップショットのスナップショットを作成してもよろしいですか?", "message.action.unmanage.cluster": "クラスターを非管理対象にしてもよろしいですか?", "message.action.vmsnapshot.create": "Please confirm that you want to take a snapshot of this instance.
Please notice that the instance will be paused during the snapshoting, and resumed after snapshotting, if it runs on KVM.", "message.action.vmsnapshot.delete": "この VM スナップショットを削除してもよろしいですか?", diff --git a/ui/legacy/l10n/ko_KR.js b/ui/legacy/l10n/ko_KR.js index bdcae7d5a0e..e2f66c6cc74 100644 --- a/ui/legacy/l10n/ko_KR.js +++ b/ui/legacy/l10n/ko_KR.js @@ -1888,6 +1888,7 @@ var dictionary = { "message.action.stop.router": "현재 가상 라우터로 제공하는 모든 서비스가 중단됩니다. 이 라우터를 정지하시겠습니까?", "message.action.stop.systemvm": "현재 시스템 VM을 정지하시겠습니까?", "message.action.take.snapshot": "현재 볼륨 스냅샷을 만드시겠습니까?", + "message.action.snapshot.fromsnapshot":"이 VM 스냅 샷의 스냅 샷을 만들려는지 확인하십시오.", "message.action.unmanage.cluster": "클러스터를 비관리 대상으로 하시겠습니까?", "message.action.vmsnapshot.create": "Please confirm that you want to take a snapshot of this instance.
Please notice that the instance will be paused during the snapshoting, and resumed after snapshotting, if it runs on KVM.", "message.action.vmsnapshot.delete": "Please confirm that you want to delete this VM snapshot.", diff --git a/ui/legacy/l10n/nb_NO.js b/ui/legacy/l10n/nb_NO.js index 364a3fc14a7..ce3a2571ba0 100644 --- a/ui/legacy/l10n/nb_NO.js +++ b/ui/legacy/l10n/nb_NO.js @@ -1888,6 +1888,7 @@ var dictionary = { "message.action.stop.router": "Alle tjenester levert fra denne virtuelle ruter vil bli avbrutt. Vennligst bekreft at du ønsker å stoppe denne ruteren.", "message.action.stop.systemvm": "Vennligst bekreft at du vil stoppe denne system VM.", "message.action.take.snapshot": "Vennligst bekreft at du vil ta et øyeblikksbilde av dette volumet.", + "message.action.snapshot.fromsnapshot":"Bekreft at du vil ta et øyeblikksbilde av dette virtuelle maskinbildet.", "message.action.unmanage.cluster": "Vennligst bekreft at du ikke ønsker å administere klyngen.", "message.action.vmsnapshot.create": "Please confirm that you want to take a snapshot of this instance.
Please notice that the instance will be paused during the snapshoting, and resumed after snapshotting, if it runs on KVM.", "message.action.vmsnapshot.delete": "Vennligst bekreft at du ønsker å slette dette VM øyeblikksbildet.", diff --git a/ui/legacy/l10n/nl_NL.js b/ui/legacy/l10n/nl_NL.js index ffb1f1e5030..b3f37335d29 100644 --- a/ui/legacy/l10n/nl_NL.js +++ b/ui/legacy/l10n/nl_NL.js @@ -1888,6 +1888,7 @@ var dictionary = { "message.action.stop.router": "Als u deze router stopt zullen de diensten die gebruik maken van de router verstoord worden. Weet u zeker dat u deze actie wil uitvoeren?", "message.action.stop.systemvm": "Bevestig dat u deze systeem VM wilt stoppen.", "message.action.take.snapshot": "Bevestig dat u een snapshot wilt maken van dit volume.", + "message.action.snapshot.fromsnapshot":"Bevestig dat u een snapshot wilt maken van dit VM snapshot.", "message.action.unmanage.cluster": "Bevestig dat u dit cluster niet langer wilt laten beheren door CloudStack.", "message.action.vmsnapshot.create": "Please confirm that you want to take a snapshot of this instance.
Please notice that the instance will be paused during the snapshoting, and resumed after snapshotting, if it runs on KVM.", "message.action.vmsnapshot.delete": "Bevestig dat u deze VM snapshot wilt verwijderen.", diff --git a/ui/legacy/l10n/pl.js b/ui/legacy/l10n/pl.js index 7f993c66803..7262ced6a7c 100644 --- a/ui/legacy/l10n/pl.js +++ b/ui/legacy/l10n/pl.js @@ -1888,6 +1888,7 @@ var dictionary = { "message.action.stop.router": "All services provided by this virtual router will be interrupted. Please confirm that you want to stop this router.", "message.action.stop.systemvm": "Please confirm that you want to stop this system VM.", "message.action.take.snapshot": "Please confirm that you want to take a snapshot of this volume.", + "message.action.snapshot.fromsnapshot":"Please confirm that you want to take a snapshot of this VM snapshot.", "message.action.unmanage.cluster": "Please confirm that you want to unmanage the cluster.", "message.action.vmsnapshot.create": "Please confirm that you want to take a snapshot of this instance.
Please notice that the instance will be paused during the snapshoting, and resumed after snapshotting, if it runs on KVM.", "message.action.vmsnapshot.delete": "Please confirm that you want to delete this VM snapshot.", diff --git a/ui/legacy/l10n/pt_BR.js b/ui/legacy/l10n/pt_BR.js index eb5a290014a..13ca563da56 100644 --- a/ui/legacy/l10n/pt_BR.js +++ b/ui/legacy/l10n/pt_BR.js @@ -1888,6 +1888,7 @@ var dictionary = { "message.action.stop.router": "Confirme que você deseja parar este roteador.", "message.action.stop.systemvm": "Confirme que você deseja parar esta VM de Sistema.", "message.action.take.snapshot": "Por favor confirme que você deseja criar um snapshot deste volume.", + "message.action.snapshot.fromsnapshot":"Por favor confirme que você deseja criar um snapshot deste VM snapshot.", "message.action.unmanage.cluster": "Confirma a desvinculação do cluster.", "message.action.vmsnapshot.create": "Please confirm that you want to take a snapshot of this instance.
Please notice that the instance will be paused during the snapshoting, and resumed after snapshotting, if it runs on KVM.", "message.action.vmsnapshot.delete": "Por favor, confirme que você deseja excluir este snapshot da VM.", diff --git a/ui/legacy/l10n/ru_RU.js b/ui/legacy/l10n/ru_RU.js index 49f4d8ae47b..a3485a512e9 100644 --- a/ui/legacy/l10n/ru_RU.js +++ b/ui/legacy/l10n/ru_RU.js @@ -1888,6 +1888,7 @@ var dictionary = { "message.action.stop.router": "Подтвердите, что вы действительно хотите остановить этот роутер.", "message.action.stop.systemvm": "Пожалуйста подтвердите желание остановить эту служебную машину.", "message.action.take.snapshot": "Подтвердите, что вы действительно хотите получить снимок этого диска.", + "message.action.snapshot.fromsnapshot":"Пожалуйста, подтвердите, что вы хотите сделать снимок этого снимка виртуальной машины.", "message.action.unmanage.cluster": "Подтвердите, что вы действительно хотите перевести кластер в обычный режим.", "message.action.vmsnapshot.create": "Please confirm that you want to take a snapshot of this instance.
Please notice that the instance will be paused during the snapshoting, and resumed after snapshotting, if it runs on KVM.", "message.action.vmsnapshot.delete": "Пожалуйста подтвердите, что Вы хотите удалить этот снимок ВМ.", diff --git a/ui/legacy/l10n/zh_CN.js b/ui/legacy/l10n/zh_CN.js index 26cb7081869..f78083c2188 100644 --- a/ui/legacy/l10n/zh_CN.js +++ b/ui/legacy/l10n/zh_CN.js @@ -1890,6 +1890,7 @@ var dictionary = { "message.action.stop.router": "此虚拟路由器提供的所有服务都将中断。请确认您确实要停止此路由器。", "message.action.stop.systemvm": "请确认您确实要停止此系统 VM。", "message.action.take.snapshot": "请确认您确实要创建此卷的快照。", + "message.action.snapshot.fromsnapshot":"请确认您要对此虚拟机快照制作快照。", "message.action.unmanage.cluster": "请确认您确实要取消托管此群集。", "message.action.vmsnapshot.create": "Please confirm that you want to take a snapshot of this instance.
Please notice that the instance will be paused during the snapshoting, and resumed after snapshotting, if it runs on KVM.", "message.action.vmsnapshot.delete": "请确认您确实要删除此 VM 快照。", diff --git a/ui/legacy/scripts/storage.js b/ui/legacy/scripts/storage.js index aa355ef5afa..65ae293d7cd 100644 --- a/ui/legacy/scripts/storage.js +++ b/ui/legacy/scripts/storage.js @@ -2705,7 +2705,7 @@ }, createForm: { title: 'label.action.take.snapshot', - desc: 'message.action.take.snapshot', + desc: 'message.action.snapshot.fromsnapshot', fields: { name: { label: 'label.name', From 88337bdea4ff68ba86fe0a02a707e5265273283a Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 25 Feb 2021 22:13:50 +0530 Subject: [PATCH 7/8] server: fix finding pools for volume migration (#4693) While finding pools for volume migration list following compatible storages: - all zone-wide storages of the same hypervisor. - when the volume is attached to a VM, then all storages from the same cluster as that of VM. - for detached volume, all storages that belong to clusters of the same hypervisor. Fixes #4692 Fixes #4400 --- .../api/storage/StoragePoolAllocator.java | 10 +- .../datastore/db/PrimaryDataStoreDao.java | 2 + .../datastore/db/PrimaryDataStoreDaoImpl.java | 13 ++ .../AbstractStoragePoolAllocator.java | 18 +-- .../ClusterScopeStoragePoolAllocator.java | 6 +- ...GarbageCollectingStoragePoolAllocator.java | 4 +- .../allocator/LocalStoragePoolAllocator.java | 4 +- .../allocator/UseLocalForRootAllocator.java | 7 +- .../ZoneWideStoragePoolAllocator.java | 4 +- .../allocator/RandomStoragePoolAllocator.java | 2 +- .../cloud/server/ManagementServerImpl.java | 118 +++++++++++++----- 11 files changed, 139 insertions(+), 49 deletions(-) diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/StoragePoolAllocator.java b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/StoragePoolAllocator.java index 46f8f5e0429..c8fcf5f3df5 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/StoragePoolAllocator.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/StoragePoolAllocator.java @@ -28,6 +28,12 @@ import com.cloud.vm.VirtualMachineProfile; /** */ public interface StoragePoolAllocator extends Adapter { + /** + * Overloaded method calls allocateToPool with bypassStorageTypeCheck = false + * and returns a list of pools suitable. + **/ + List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo); + /** * Determines which storage pools are suitable for the guest virtual machine * and returns a list of pools suitable. @@ -45,10 +51,12 @@ public interface StoragePoolAllocator extends Adapter { * @param ExcludeList * avoid * @param int returnUpTo (use -1 to return all possible pools) + * @param boolean bypassStorageTypeCheck allows bypassing useLocalStorage check for provided DiskProfile when true * @return List List of storage pools that are suitable for the * VM **/ - List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo); + List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck); + static int RETURN_UPTO_ALL = -1; diff --git a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java index 59fe3f14d39..3375c6ff207 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java @@ -122,6 +122,8 @@ public interface PrimaryDataStoreDao extends GenericDao { List listLocalStoragePoolByPath(long datacenterId, String path); + List findPoolsInClusters(List clusterIds); + void deletePoolTags(long poolId); List listChildStoragePoolsInDatastoreCluster(long poolId); diff --git a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java index 7830df57204..dfe1a6994d5 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java @@ -56,6 +56,7 @@ public class PrimaryDataStoreDaoImpl extends GenericDaoBase private final SearchBuilder DeleteLvmSearch; private final SearchBuilder DcLocalStorageSearch; private final GenericSearchBuilder StatusCountSearch; + private final SearchBuilder ClustersSearch; @Inject private StoragePoolDetailsDao _detailsDao; @@ -133,6 +134,10 @@ public class PrimaryDataStoreDaoImpl extends GenericDaoBase DcLocalStorageSearch.and("scope", DcLocalStorageSearch.entity().getScope(), SearchCriteria.Op.EQ); DcLocalStorageSearch.done(); + ClustersSearch = createSearchBuilder(); + ClustersSearch.and("clusterIds", ClustersSearch.entity().getClusterId(), Op.IN); + ClustersSearch.and("status", ClustersSearch.entity().getStatus(), Op.EQ); + } @Override @@ -568,4 +573,12 @@ public class PrimaryDataStoreDaoImpl extends GenericDaoBase sc.addAnd("removed", SearchCriteria.Op.NULL); return getCount(sc); } + + @Override + public List findPoolsInClusters(List clusterIds) { + SearchCriteria sc = ClustersSearch.create(); + sc.setParameters("clusterIds", clusterIds.toArray()); + sc.setParameters("status", StoragePoolStatus.Up); + return listBy(sc); + } } diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java index cfe32c2bd07..82649b9f717 100644 --- a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java @@ -26,15 +26,12 @@ import java.util.Map; import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.exception.StorageUnavailableException; -import com.cloud.storage.StoragePoolStatus; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.log4j.Logger; - import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.log4j.Logger; import com.cloud.capacity.Capacity; import com.cloud.capacity.dao.CapacityDao; @@ -42,10 +39,12 @@ import com.cloud.dc.ClusterVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner.ExcludeList; +import com.cloud.exception.StorageUnavailableException; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.Storage; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; +import com.cloud.storage.StoragePoolStatus; import com.cloud.storage.StorageUtil; import com.cloud.storage.Volume; import com.cloud.storage.dao.VolumeDao; @@ -87,11 +86,16 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement return false; } - protected abstract List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo); + protected abstract List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck); @Override public List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { - List pools = select(dskCh, vmProfile, plan, avoid, returnUpTo); + return allocateToPool(dskCh, vmProfile, plan, avoid, returnUpTo, false); + } + + @Override + public List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) { + List pools = select(dskCh, vmProfile, plan, avoid, returnUpTo, bypassStorageTypeCheck); return reorderPools(pools, vmProfile, plan); } diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/ClusterScopeStoragePoolAllocator.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/ClusterScopeStoragePoolAllocator.java index 12884d5d62e..9967a2caff9 100644 --- a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/ClusterScopeStoragePoolAllocator.java +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/ClusterScopeStoragePoolAllocator.java @@ -45,9 +45,13 @@ public class ClusterScopeStoragePoolAllocator extends AbstractStoragePoolAllocat DiskOfferingDao _diskOfferingDao; @Override - protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { + protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) { s_logger.debug("ClusterScopeStoragePoolAllocator looking for storage pool"); + if (!bypassStorageTypeCheck && dskCh.useLocalStorage()) { + return null; + } + List suitablePools = new ArrayList(); long dcId = plan.getDataCenterId(); diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/GarbageCollectingStoragePoolAllocator.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/GarbageCollectingStoragePoolAllocator.java index b3a1c0d4b10..f02a89811b0 100644 --- a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/GarbageCollectingStoragePoolAllocator.java +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/GarbageCollectingStoragePoolAllocator.java @@ -47,7 +47,7 @@ public class GarbageCollectingStoragePoolAllocator extends AbstractStoragePoolAl boolean _storagePoolCleanupEnabled; @Override - public List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { + public List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) { s_logger.debug("GarbageCollectingStoragePoolAllocator looking for storage pool"); if (!_storagePoolCleanupEnabled) { s_logger.debug("Storage pool cleanup is not enabled, so GarbageCollectingStoragePoolAllocator is being skipped."); @@ -68,7 +68,7 @@ public class GarbageCollectingStoragePoolAllocator extends AbstractStoragePoolAl ExcludeList myAvoids = new ExcludeList(avoid.getDataCentersToAvoid(), avoid.getPodsToAvoid(), avoid.getClustersToAvoid(), avoid.getHostsToAvoid(), avoid.getPoolsToAvoid()); - return allocator.allocateToPool(dskCh, vmProfile, plan, myAvoids, returnUpTo); + return allocator.allocateToPool(dskCh, vmProfile, plan, myAvoids, returnUpTo, bypassStorageTypeCheck); } @Override diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java index 390272ea697..6fc4adaad0e 100644 --- a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java @@ -60,10 +60,10 @@ public class LocalStoragePoolAllocator extends AbstractStoragePoolAllocator { ConfigurationDao _configDao; @Override - protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { + protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) { s_logger.debug("LocalStoragePoolAllocator trying to find storage pool to fit the vm"); - if (!dskCh.useLocalStorage()) { + if (!bypassStorageTypeCheck && !dskCh.useLocalStorage()) { return null; } diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/UseLocalForRootAllocator.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/UseLocalForRootAllocator.java index e552a1bf2ca..4b150b26dc4 100644 --- a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/UseLocalForRootAllocator.java +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/UseLocalForRootAllocator.java @@ -39,12 +39,17 @@ public class UseLocalForRootAllocator extends LocalStoragePoolAllocator implemen @Override public List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { + return allocateToPool(dskCh, vmProfile, plan, avoid, returnUpTo, false); + } + + @Override + public List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) { DataCenterVO dc = _dcDao.findById(plan.getDataCenterId()); if (!dc.isLocalStorageEnabled()) { return null; } - return super.allocateToPool(dskCh, vmProfile, plan, avoid, returnUpTo); + return super.allocateToPool(dskCh, vmProfile, plan, avoid, returnUpTo, bypassStorageTypeCheck); } @Override diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java index 301704a75a6..e3b29912477 100644 --- a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java @@ -50,10 +50,10 @@ public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator { @Override - protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { + protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) { LOGGER.debug("ZoneWideStoragePoolAllocator to find storage pool"); - if (dskCh.useLocalStorage()) { + if (!bypassStorageTypeCheck && dskCh.useLocalStorage()) { return null; } diff --git a/plugins/storage-allocators/random/src/main/java/org/apache/cloudstack/storage/allocator/RandomStoragePoolAllocator.java b/plugins/storage-allocators/random/src/main/java/org/apache/cloudstack/storage/allocator/RandomStoragePoolAllocator.java index 6b912fb74aa..eed623a9ed0 100644 --- a/plugins/storage-allocators/random/src/main/java/org/apache/cloudstack/storage/allocator/RandomStoragePoolAllocator.java +++ b/plugins/storage-allocators/random/src/main/java/org/apache/cloudstack/storage/allocator/RandomStoragePoolAllocator.java @@ -35,7 +35,7 @@ public class RandomStoragePoolAllocator extends AbstractStoragePoolAllocator { private static final Logger s_logger = Logger.getLogger(RandomStoragePoolAllocator.class); @Override - public List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { + public List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) { List suitablePools = new ArrayList(); diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index 8df118dcbc7..8f0007aca0c 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -27,6 +27,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.TimeZone; import java.util.concurrent.Executors; @@ -40,7 +41,6 @@ import javax.crypto.spec.SecretKeySpec; import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.storage.Storage; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.affinity.AffinityGroupProcessor; import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; @@ -573,6 +573,8 @@ import com.cloud.alert.AlertManager; import com.cloud.alert.AlertVO; import com.cloud.alert.dao.AlertDao; import com.cloud.api.ApiDBUtils; +import com.cloud.api.query.dao.StoragePoolJoinDao; +import com.cloud.api.query.vo.StoragePoolJoinVO; import com.cloud.capacity.Capacity; import com.cloud.capacity.CapacityVO; import com.cloud.capacity.dao.CapacityDao; @@ -657,8 +659,10 @@ import com.cloud.storage.GuestOSHypervisorVO; import com.cloud.storage.GuestOSVO; import com.cloud.storage.GuestOsCategory; import com.cloud.storage.ScopeType; +import com.cloud.storage.Storage; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; +import com.cloud.storage.StoragePoolStatus; import com.cloud.storage.Volume; import com.cloud.storage.VolumeApiServiceImpl; import com.cloud.storage.VolumeVO; @@ -789,6 +793,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe @Inject private PrimaryDataStoreDao _poolDao; @Inject + private StoragePoolJoinDao _poolJoinDao; + @Inject private NetworkDao _networkDao; @Inject private StorageManager _storageMgr; @@ -1145,7 +1151,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe return new Pair, Integer>(result.first(), result.second()); } - private HypervisorType getHypervisorType(VMInstanceVO vm, StoragePool srcVolumePool, VirtualMachineProfile profile) { + private HypervisorType getHypervisorType(VMInstanceVO vm, StoragePool srcVolumePool) { HypervisorType type = null; if (vm == null) { StoragePoolVO poolVo = _poolDao.findById(srcVolumePool.getId()); @@ -1155,18 +1161,13 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe ClusterVO cluster = _clusterDao.findById(clusterId); type = cluster.getHypervisorType(); } - } else if (ScopeType.ZONE.equals(poolVo.getScope())) { - Long zoneId = poolVo.getDataCenterId(); - if (zoneId != null) { - DataCenterVO dc = _dcDao.findById(zoneId); - } } if (null == type) { type = srcVolumePool.getHypervisor(); } } else { - type = profile.getHypervisorType(); + type = vm.getHypervisorType(); } return type; } @@ -1488,12 +1489,17 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } StoragePool srcVolumePool = _poolDao.findById(volume.getPoolId()); - allPools = getAllStoragePoolCompatileWithVolumeSourceStoragePool(srcVolumePool); + HypervisorType hypervisorType = getHypervisorType(vm, srcVolumePool); + Pair> hostClusterPair = getVolumeVmHostClusters(srcVolumePool, vm, hypervisorType); + Host vmHost = hostClusterPair.first(); + List clusters = hostClusterPair.second(); + allPools = getAllStoragePoolCompatibleWithVolumeSourceStoragePool(srcVolumePool, hypervisorType, clusters); allPools.remove(srcVolumePool); if (vm != null) { - suitablePools = findAllSuitableStoragePoolsForVm(volume, vm, srcVolumePool); + suitablePools = findAllSuitableStoragePoolsForVm(volume, vm, vmHost, srcVolumePool, + CollectionUtils.isNotEmpty(clusters) ? clusters.get(0) : null, hypervisorType); } else { - suitablePools = allPools; + suitablePools = findAllSuitableStoragePoolsForDetachedVolume(volume, allPools); } List avoidPools = new ArrayList<>(); if (srcVolumePool.getParent() != 0L) { @@ -1520,6 +1526,30 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } } + private Pair> getVolumeVmHostClusters(StoragePool srcVolumePool, VirtualMachine vm, HypervisorType hypervisorType) { + Host host = null; + List clusters = new ArrayList<>(); + Long clusterId = srcVolumePool.getClusterId(); + if (vm != null) { + Long hostId = vm.getHostId(); + if (hostId == null) { + hostId = vm.getLastHostId(); + } + if (hostId != null) { + host = _hostDao.findById(hostId); + } + } + if (clusterId == null && host != null) { + clusterId = host.getClusterId(); + } + if (clusterId != null && vm != null) { + clusters.add(_clusterDao.findById(clusterId)); + } else { + clusters.addAll(_clusterDao.listByDcHyType(srcVolumePool.getDataCenterId(), hypervisorType.toString())); + } + return new Pair<>(host, clusters); + } + /** * This method looks for all storage pools that are compatible with the given volume. *
    @@ -1527,15 +1557,18 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe *
  • We also all storage available filtering by data center, pod and cluster as the current storage pool used by the given volume.
  • *
*/ - private List getAllStoragePoolCompatileWithVolumeSourceStoragePool(StoragePool srcVolumePool) { + private List getAllStoragePoolCompatibleWithVolumeSourceStoragePool(StoragePool srcVolumePool, HypervisorType hypervisorType, List clusters) { List storagePools = new ArrayList<>(); - List zoneWideStoragePools = _poolDao.findZoneWideStoragePoolsByTags(srcVolumePool.getDataCenterId(), null); + List zoneWideStoragePools = _poolDao.findZoneWideStoragePoolsByHypervisor(srcVolumePool.getDataCenterId(), hypervisorType); if (CollectionUtils.isNotEmpty(zoneWideStoragePools)) { storagePools.addAll(zoneWideStoragePools); } - List clusterAndLocalStoragePools = _poolDao.listBy(srcVolumePool.getDataCenterId(), srcVolumePool.getPodId(), srcVolumePool.getClusterId(), null); - if (CollectionUtils.isNotEmpty(clusterAndLocalStoragePools)) { - storagePools.addAll(clusterAndLocalStoragePools); + if (CollectionUtils.isNotEmpty(clusters)) { + List clusterIds = clusters.stream().map(Cluster::getId).collect(Collectors.toList()); + List clusterAndLocalStoragePools = _poolDao.findPoolsInClusters(clusterIds); + if (CollectionUtils.isNotEmpty(clusterAndLocalStoragePools)) { + storagePools.addAll(clusterAndLocalStoragePools); + } } return storagePools; } @@ -1547,35 +1580,33 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe * * Side note: the idea behind this method is to provide power for administrators of manually overriding deployments defined by CloudStack. */ - private List findAllSuitableStoragePoolsForVm(final VolumeVO volume, VMInstanceVO vm, StoragePool srcVolumePool) { + private List findAllSuitableStoragePoolsForVm(final VolumeVO volume, VMInstanceVO vm, Host vmHost, StoragePool srcVolumePool, Cluster srcCluster, HypervisorType hypervisorType) { List suitablePools = new ArrayList<>(); - - HostVO host = _hostDao.findById(vm.getHostId()); - if (host == null) { - host = _hostDao.findById(vm.getLastHostId()); - } - ExcludeList avoid = new ExcludeList(); avoid.addPool(srcVolumePool.getId()); - - DataCenterDeployment plan = new DataCenterDeployment(volume.getDataCenterId(), srcVolumePool.getPodId(), srcVolumePool.getClusterId(), null, null, null); + Long clusterId = null; + Long podId = null; + if (srcCluster != null) { + clusterId = srcCluster.getId(); + podId = srcCluster.getPodId(); + } + DataCenterDeployment plan = new DataCenterDeployment(volume.getDataCenterId(), podId, clusterId, + null, null, null, null); VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); // OfflineVmwareMigration: vm might be null here; deal! - HypervisorType type = getHypervisorType(vm, srcVolumePool, profile); DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); - //This is an override mechanism so we can list the possible local storage pools that a volume in a shared pool might be able to be migrated to - DiskProfile diskProfile = new DiskProfile(volume, diskOffering, type); - diskProfile.setUseLocalStorage(true); + DiskProfile diskProfile = new DiskProfile(volume, diskOffering, hypervisorType); for (StoragePoolAllocator allocator : _storagePoolAllocators) { - List pools = allocator.allocateToPool(diskProfile, profile, plan, avoid, StoragePoolAllocator.RETURN_UPTO_ALL); + List pools = allocator.allocateToPool(diskProfile, profile, plan, avoid, StoragePoolAllocator.RETURN_UPTO_ALL, true); if (CollectionUtils.isEmpty(pools)) { continue; } for (StoragePool pool : pools) { - boolean isLocalPoolSameHostAsSourcePool = pool.isLocal() && StringUtils.equals(host.getPrivateIpAddress(), pool.getHostAddress()); - if (isLocalPoolSameHostAsSourcePool || pool.isShared()) { + boolean isLocalPoolSameHostAsVmHost = pool.isLocal() && + (vmHost == null || StringUtils.equals(vmHost.getPrivateIpAddress(), pool.getHostAddress())); + if (isLocalPoolSameHostAsVmHost || pool.isShared()) { suitablePools.add(pool); } @@ -1584,6 +1615,29 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe return suitablePools; } + private List findAllSuitableStoragePoolsForDetachedVolume(Volume volume, List allPools) { + List suitablePools = new ArrayList<>(); + if (CollectionUtils.isEmpty(allPools)) { + return suitablePools; + } + DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); + List tags = new ArrayList<>(); + String[] tagsArray = diskOffering.getTagsArray(); + if (tagsArray != null && tagsArray.length > 0) { + tags = Arrays.asList(tagsArray); + } + Long[] poolIds = allPools.stream().map(StoragePool::getId).toArray(Long[]::new); + List pools = _poolJoinDao.searchByIds(poolIds); + for (StoragePoolJoinVO storagePool : pools) { + if (StoragePoolStatus.Up.equals(storagePool.getStatus()) && + (CollectionUtils.isEmpty(tags) || tags.contains(storagePool.getTag()))) { + Optional match = allPools.stream().filter(x -> x.getId() == storagePool.getId()).findFirst(); + match.ifPresent(suitablePools::add); + } + } + return suitablePools; + } + private Pair, Integer> searchForServers(final Long startIndex, final Long pageSize, final Object name, final Object type, final Object state, final Object zone, final Object pod, final Object cluster, final Object id, final Object keyword, final Object resourceState, final Object haHosts, final Object hypervisorType, final Object hypervisorVersion, final Object... excludes) { From e1f3179446529da3683154c044b15f277d0d7eab Mon Sep 17 00:00:00 2001 From: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com> Date: Thu, 25 Feb 2021 20:28:11 -0300 Subject: [PATCH 8/8] Adjust tests to fix a problem with the container builders (https://github.com/khos2ow/cloudstack-deb-builder) (#4668) * Changes to allow builders containers to build ACS Co-authored-by: Daniel Augusto Veronezi Salvador --- .../ca/provider/RootCAProviderTest.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/plugins/ca/root-ca/src/test/java/org/apache/cloudstack/ca/provider/RootCAProviderTest.java b/plugins/ca/root-ca/src/test/java/org/apache/cloudstack/ca/provider/RootCAProviderTest.java index d5d64289da2..1f16360786c 100644 --- a/plugins/ca/root-ca/src/test/java/org/apache/cloudstack/ca/provider/RootCAProviderTest.java +++ b/plugins/ca/root-ca/src/test/java/org/apache/cloudstack/ca/provider/RootCAProviderTest.java @@ -41,6 +41,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) @@ -57,12 +58,6 @@ public class RootCAProviderTest { f.set(provider, o); } - private void overrideDefaultConfigValue(final ConfigKey configKey, final String name, final Object o) throws IllegalAccessException, NoSuchFieldException { - Field f = ConfigKey.class.getDeclaredField(name); - f.setAccessible(true); - f.set(configKey, o); - } - @Before public void setUp() throws Exception { caKeyPair = CertUtils.generateRandomKeyPair(1024); @@ -133,17 +128,17 @@ public class RootCAProviderTest { @Test public void testCreateSSLEngineWithoutAuthStrictness() throws Exception { - overrideDefaultConfigValue(RootCAProvider.rootCAAuthStrictness, "_defaultValue", "false"); + provider.rootCAAuthStrictness = Mockito.mock(ConfigKey.class); + Mockito.when(provider.rootCAAuthStrictness.value()).thenReturn(Boolean.FALSE); final SSLEngine e = provider.createSSLEngine(SSLUtils.getSSLContext(), "/1.2.3.4:5678", null); - Assert.assertFalse(e.getUseClientMode()); Assert.assertFalse(e.getNeedClientAuth()); } @Test public void testCreateSSLEngineWithAuthStrictness() throws Exception { - overrideDefaultConfigValue(RootCAProvider.rootCAAuthStrictness, "_defaultValue", "true"); + provider.rootCAAuthStrictness = Mockito.mock(ConfigKey.class); + Mockito.when(provider.rootCAAuthStrictness.value()).thenReturn(Boolean.TRUE); final SSLEngine e = provider.createSSLEngine(SSLUtils.getSSLContext(), "/1.2.3.4:5678", null); - Assert.assertFalse(e.getUseClientMode()); Assert.assertTrue(e.getNeedClientAuth()); }