From 59e054396a8f23ed003ff276c784adc2ab1e1a92 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 12 Feb 2025 11:18:14 -0500 Subject: [PATCH 01/21] UI: Fix all list items appearing twice in search view (#10365) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * UI: Fix all list items appearing twice in search view * Revert "UI: Fix all list items appearing twice in search view" This reverts commit 2739c0112c519406cc46394948fcad6020bcdb62. * fix duplicate option names on list filters --------- Co-authored-by: Bernardo De Marco Gonçalves --- ui/src/components/view/SearchView.vue | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/ui/src/components/view/SearchView.vue b/ui/src/components/view/SearchView.vue index d8cdf078e5c..d0e962c58e5 100644 --- a/ui/src/components/view/SearchView.vue +++ b/ui/src/components/view/SearchView.vue @@ -80,7 +80,7 @@ - + @@ -90,13 +90,6 @@ {{ $t((['storageid'].includes(field.name) || !opt.path) ? opt.name : opt.path) }} - - - - - - - {{ $t(opt.path || opt.name) }} From 8c4a085a16d50f13222dd4c6d60731e7bd1e57e0 Mon Sep 17 00:00:00 2001 From: Suresh Kumar Anaparti Date: Thu, 13 Feb 2025 12:08:57 +0530 Subject: [PATCH 02/21] Validate the direct downloaded template file format (QCOW2) if the template file exists (#10332) * Validate the direct downloaded template file format (QCOW2) if the template file exists * string format not required --- .../hypervisor/kvm/storage/KVMStorageProcessor.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) 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 5e62671dd22..0a2621b7bd4 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 @@ -2472,8 +2472,15 @@ public class KVMStorageProcessor implements StorageProcessor { template = storagePoolMgr.createPhysicalDiskFromDirectDownloadTemplate(tempFilePath, destTemplatePath, destPool, cmd.getFormat(), cmd.getWaitInMillSeconds()); - String templatePath = template.getPath(); - if (templatePath != null) { + String templatePath = null; + if (template != null) { + templatePath = template.getPath(); + } + if (StringUtils.isEmpty(templatePath)) { + logger.warn("Skipped validation whether downloaded file is QCOW2 for template {}, due to downloaded template path is empty", template.getName()); + } else if (!new File(templatePath).exists()) { + logger.warn("Skipped validation whether downloaded file is QCOW2 for template {}, due to downloaded template path is not valid: {}", template.getName(), templatePath); + } else { try { Qcow2Inspector.validateQcow2File(templatePath); } catch (RuntimeException e) { From 42a77c764613c98f1174bb36df714cd24c029a02 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Thu, 13 Feb 2025 09:12:05 +0100 Subject: [PATCH 03/21] LinstorStorageAdaptor: fix lint error (#10378) This is found in some PRs plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java:510: poperties ==> properties --- .../com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java index ab8e5f4ee7b..ba4a7b14787 100644 --- a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java +++ b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java @@ -507,7 +507,7 @@ public class LinstorStorageAdaptor implements StorageAdaptor { // if there is only one template-for property left for templates, the template isn't needed anymore // or if it isn't a template anyway, it will not have this Aux property - // _cs-template-for- poperties work like a ref-count. + // _cs-template-for- properties work like a ref-count. if (rd.getProps().keySet().stream() .filter(key -> key.startsWith("Aux/" + LinstorUtil.CS_TEMPLATE_FOR_PREFIX)) .count() == expectedProps) { From 8e1f5b1e49b767374953db824d7819c2d57e9421 Mon Sep 17 00:00:00 2001 From: Vishesh Date: Thu, 13 Feb 2025 19:07:08 +0530 Subject: [PATCH 04/21] Fill fields in login, forgotPassword and resetPassword from url (#10291) --- ui/src/views/auth/ForgotPassword.vue | 4 +++- ui/src/views/auth/Login.vue | 4 +++- ui/src/views/auth/ResetPassword.vue | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ui/src/views/auth/ForgotPassword.vue b/ui/src/views/auth/ForgotPassword.vue index 2d45938417f..87f2d1d0c33 100644 --- a/ui/src/views/auth/ForgotPassword.vue +++ b/ui/src/views/auth/ForgotPassword.vue @@ -129,7 +129,9 @@ export default { initForm () { this.formRef = ref() this.form = reactive({ - server: (this.server.apiHost || '') + this.server.apiBase + server: (this.server.apiHost || '') + this.server.apiBase, + username: this.$route.query?.username || '', + domain: this.$route.query?.domain || '' }) this.rules = { username: [{ diff --git a/ui/src/views/auth/Login.vue b/ui/src/views/auth/Login.vue index 10963073c18..47e2f34c57e 100644 --- a/ui/src/views/auth/Login.vue +++ b/ui/src/views/auth/Login.vue @@ -253,7 +253,9 @@ export default { initForm () { this.formRef = ref() this.form = reactive({ - server: (this.server.apiHost || '') + this.server.apiBase + server: (this.server.apiHost || '') + this.server.apiBase, + username: this.$route.query?.username || '', + domain: this.$route.query?.domain || '' }) this.rules = reactive({}) this.setRules() diff --git a/ui/src/views/auth/ResetPassword.vue b/ui/src/views/auth/ResetPassword.vue index 8a9047c5d3e..0250e60008a 100644 --- a/ui/src/views/auth/ResetPassword.vue +++ b/ui/src/views/auth/ResetPassword.vue @@ -157,6 +157,7 @@ export default { this.form = reactive({ server: (this.server.apiHost || '') + this.server.apiBase, username: this.$route.query?.username || '', + domain: this.$route.query?.domain || '', token: this.$route.query?.token || '' }) this.rules = { From 07564b7933ee800265059f2ddc22ad8887f44755 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Fri, 14 Feb 2025 02:46:43 -0500 Subject: [PATCH 05/21] Enable multiple services on configdrive network service provider (#10372) --- .../com/cloud/network/element/ConfigDriveNetworkElement.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/com/cloud/network/element/ConfigDriveNetworkElement.java b/server/src/main/java/com/cloud/network/element/ConfigDriveNetworkElement.java index e1f850978d5..47c9979c2f6 100644 --- a/server/src/main/java/com/cloud/network/element/ConfigDriveNetworkElement.java +++ b/server/src/main/java/com/cloud/network/element/ConfigDriveNetworkElement.java @@ -220,7 +220,7 @@ public class ConfigDriveNetworkElement extends AdapterBase implements NetworkEle @Override public boolean canEnableIndividualServices() { - return false; + return true; } private String getSshKey(VirtualMachineProfile profile) { From 69285a62c949d52a97b4c23e11afeeabd60da883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernardo=20De=20Marco=20Gon=C3=A7alves?= Date: Fri, 14 Feb 2025 05:13:42 -0300 Subject: [PATCH 06/21] UI: Fix selection of domain filters in the `SearchView` component (#10386) --- ui/src/components/view/SearchView.vue | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/ui/src/components/view/SearchView.vue b/ui/src/components/view/SearchView.vue index d0e962c58e5..912c4d1be7b 100644 --- a/ui/src/components/view/SearchView.vue +++ b/ui/src/components/view/SearchView.vue @@ -249,7 +249,8 @@ export default { this.fetchDynamicFieldData(fieldname, event.target.value) }, onSelectFieldChange (fieldname) { - if (fieldname === 'domainid') { + const fetchAccountOptions = fieldname === 'domainid' && this.fields.some((field) => field.name === 'account') + if (fetchAccountOptions) { this.fetchDynamicFieldData('account') } }, @@ -711,10 +712,6 @@ export default { if (Array.isArray(arrayField)) { this.fillFormFieldValues() } - if (networkIndex > -1) { - this.fields[networkIndex].loading = false - } - this.fillFormFieldValues() }) }, initFormFieldData () { @@ -782,7 +779,7 @@ export default { params.domainid = this.form.domainid } api('listAccounts', params).then(json => { - var account = json.listaccountsresponse.account + let account = json?.listaccountsresponse?.account || [] if (this.form.domainid) { account = account.filter(a => a.domainid === this.form.domainid) } @@ -1323,7 +1320,7 @@ export default { this.searchQuery = value this.$emit('search', { searchQuery: this.searchQuery }) }, - onClear () { + async onClear () { this.formRef.value.resetFields() this.form = reactive({}) this.isFiltered = false @@ -1331,6 +1328,14 @@ export default { this.inputValue = null this.searchQuery = null this.paramsFilter = {} + + const refreshAccountOptions = ['account', 'domainid'].every((field) => { + return this.fields.some((searchViewField) => searchViewField.name === field) + }) + if (refreshAccountOptions) { + await this.fetchDynamicFieldData('account') + } + this.$emit('search', this.paramsFilter) }, handleSubmit () { From 5204960bac890e40153403728e33b95a79cd3188 Mon Sep 17 00:00:00 2001 From: erik-bock-silva Date: Fri, 14 Feb 2025 08:32:23 -0300 Subject: [PATCH 07/21] made id parameter required (#10338) --- .../offering/IsAccountAllowedToCreateOfferingsWithTagsCmd.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/IsAccountAllowedToCreateOfferingsWithTagsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/IsAccountAllowedToCreateOfferingsWithTagsCmd.java index e94bff1fce8..fcd6b03d3e5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/IsAccountAllowedToCreateOfferingsWithTagsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/IsAccountAllowedToCreateOfferingsWithTagsCmd.java @@ -29,7 +29,7 @@ import org.apache.cloudstack.api.response.IsAccountAllowedToCreateOfferingsWithT responseObject = IsAccountAllowedToCreateOfferingsWithTagsResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class IsAccountAllowedToCreateOfferingsWithTagsCmd extends BaseCmd { - @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AccountResponse.class, description = "Account UUID") + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AccountResponse.class, description = "Account UUID", required = true) private Long id; @Override From 789f94b664a62a9e5729dec6ba60849ed0e90964 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Fri, 14 Feb 2025 14:57:48 +0100 Subject: [PATCH 08/21] VR: fix duplicated lines in .htaccess (#10254) --- systemvm/debian/opt/cloud/bin/configure.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/systemvm/debian/opt/cloud/bin/configure.py b/systemvm/debian/opt/cloud/bin/configure.py index c68e4fde16b..cf0b71ab436 100755 --- a/systemvm/debian/opt/cloud/bin/configure.py +++ b/systemvm/debian/opt/cloud/bin/configure.py @@ -932,6 +932,7 @@ class CsVmMetadata(CsDataBag): if os.path.exists(htaccessFile): fh = open(htaccessFile, "a+") self.__exflock(fh) + fh.seek(0) if entry not in fh.read(): fh.write(entry + '\n') self.__unflock(fh) @@ -969,6 +970,7 @@ class CsVmMetadata(CsDataBag): fh = open(htaccessFile, "a+") self.__exflock(fh) + fh.seek(0) if entry not in fh.read(): fh.write(entry + '\n') From 7bef25666fd61ee2caa8d5135ce825ff04928d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernardo=20De=20Marco=20Gon=C3=A7alves?= Date: Mon, 17 Feb 2025 05:17:57 -0300 Subject: [PATCH 09/21] UI: Fix Apache CloudStack description on the onboarding page (#10373) * remove sentence from en.json * remove sentence from ar.json * remove sentence from ca.json * remove sentence from de_DE.json * remove sentence from el_GR.json * remove sentence from es.json * remove sentence from fr_FR.json * remove sentence from hu.json * remove sentence from it_IT.json * remove sentence from ko_KR.json * remove sentence from nb_NO.json * remove sentence from ja_JP.json * remove sentence from nl_NL.json * remove sentence from pl.json * remove sentence from pt_BR.json * remove sentence from ru_RU.json * remove sentence from zh_CN.json --- ui/public/locales/ar.json | 2 +- ui/public/locales/ca.json | 2 +- ui/public/locales/de_DE.json | 2 +- ui/public/locales/el_GR.json | 2 +- ui/public/locales/en.json | 2 +- ui/public/locales/es.json | 2 +- ui/public/locales/fr_FR.json | 2 +- ui/public/locales/hu.json | 2 +- ui/public/locales/it_IT.json | 2 +- ui/public/locales/ja_JP.json | 2 +- ui/public/locales/ko_KR.json | 2 +- ui/public/locales/nb_NO.json | 2 +- ui/public/locales/nl_NL.json | 2 +- ui/public/locales/pl.json | 2 +- ui/public/locales/pt_BR.json | 2 +- ui/public/locales/ru_RU.json | 2 +- ui/public/locales/zh_CN.json | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ui/public/locales/ar.json b/ui/public/locales/ar.json index 2cf51c2c385..20499c63e04 100644 --- a/ui/public/locales/ar.json +++ b/ui/public/locales/ar.json @@ -1405,7 +1405,7 @@ "message.guest.traffic.in.basic.zone": "Guest network traffic is communication between end-user virtual machines. Specify a range of IP addresses that CloudStack can assign to guest VMs. Make sure this range does not overlap the reserved system IP range.", "message.host.dedicated": "Host Dedicated", "message.host.dedication.released": "Host dedication released", -"message.installwizard.copy.whatiscloudstack": "CloudStack™ is a software platform that pools computing resources to build public, private, and hybrid Infrastructure as a Service (IaaS) clouds. CloudStack™ manages the network, storage, and compute nodes that make up a cloud infrastructure. Use CloudStack™ to deploy, manage, and configure cloud computing environments.

Extending beyond individual virtual machine images running on commodity hardware, CloudStack™ provides a turnkey cloud infrastructure software stack for delivering virtual datacenters as a service - delivering all of the essential components to build, deploy, and manage multi-tier and multi-tenant cloud applications. Both open-source and Premium versions are available, with the open-source version offering nearly identical features.", +"message.installwizard.copy.whatiscloudstack": "CloudStack™ is a software platform that pools computing resources to build public, private, and hybrid Infrastructure as a Service (IaaS) clouds. CloudStack™ manages the network, storage, and compute nodes that make up a cloud infrastructure. Use CloudStack™ to deploy, manage, and configure cloud computing environments.

Extending beyond individual virtual machine images running on commodity hardware, CloudStack™ provides a turnkey cloud infrastructure software stack for delivering virtual datacenters as a service - delivering all of the essential components to build, deploy, and manage multi-tier and multi-tenant cloud applications.", "message.installwizard.tooltip.addpod.name": "A name for the pod", "message.installwizard.tooltip.addpod.reservedsystemendip": "This is the IP range in the private network that the CloudStack uses to manage Secondary Storage VMs and Console Proxy VMs. These IP addresses are taken from the same subnet as computing servers.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "The gateway for the hosts in that pod.", diff --git a/ui/public/locales/ca.json b/ui/public/locales/ca.json index e97d11d101f..30ed3161448 100644 --- a/ui/public/locales/ca.json +++ b/ui/public/locales/ca.json @@ -1405,7 +1405,7 @@ "message.guest.traffic.in.basic.zone": "Guest network traffic is communication between end-user virtual machines. Specify a range of IP addresses that CloudStack can assign to guest VMs. Make sure this range does not overlap the reserved system IP range.", "message.host.dedicated": "Host Dedicated", "message.host.dedication.released": "Host dedication released", -"message.installwizard.copy.whatiscloudstack": "CloudStack™ is a software platform that pools computing resources to build public, private, and hybrid Infrastructure as a Service (IaaS) clouds. CloudStack™ manages the network, storage, and compute nodes that make up a cloud infrastructure. Use CloudStack™ to deploy, manage, and configure cloud computing environments.

Extending beyond individual virtual machine images running on commodity hardware, CloudStack™ provides a turnkey cloud infrastructure software stack for delivering virtual datacenters as a service - delivering all of the essential components to build, deploy, and manage multi-tier and multi-tenant cloud applications. Both open-source and Premium versions are available, with the open-source version offering nearly identical features.", +"message.installwizard.copy.whatiscloudstack": "CloudStack™ is a software platform that pools computing resources to build public, private, and hybrid Infrastructure as a Service (IaaS) clouds. CloudStack™ manages the network, storage, and compute nodes that make up a cloud infrastructure. Use CloudStack™ to deploy, manage, and configure cloud computing environments.

Extending beyond individual virtual machine images running on commodity hardware, CloudStack™ provides a turnkey cloud infrastructure software stack for delivering virtual datacenters as a service - delivering all of the essential components to build, deploy, and manage multi-tier and multi-tenant cloud applications.", "message.installwizard.tooltip.addpod.name": "Un nom per al pod", "message.installwizard.tooltip.addpod.reservedsystemendip": "Aquest \u00e9s el rang IP a la xarxa privada que el CloudStack fa servir per administrar MVs per al Secondary Storage i Proxy de consoles. Aquestes IP es prenen de la mateixa sub-xarxa que els servidors de virtualitzaci\u00f3.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "La passarel\u00b7la per als amfitrions en aquest pot.", diff --git a/ui/public/locales/de_DE.json b/ui/public/locales/de_DE.json index d9adc43469e..78bbfe05915 100644 --- a/ui/public/locales/de_DE.json +++ b/ui/public/locales/de_DE.json @@ -1955,7 +1955,7 @@ "message.host.dedicated": "Host dediziert", "message.host.dedication.released": "Host-Dedizierung freigegeben", "message.info.cloudian.console": "Cloudian Management Konsole sollte ein anderes Fenster öffnen", -"message.installwizard.copy.whatiscloudstack": "CloudStack™ ist eine Software-Plattform welche Rechenressourcen zusammenfasst, um öffentliche, private oder hybride \"Infrastructure as a Service\" (IaaS) Clouds zu bauen. CloudStack™ verwaltet das Netzwerk-, Speicher- und Computingknoten was eine Cloud-Infrastruktur ausmacht. Benutzen Sie CloudStack™ um Computing-Umgebungen zu erstellen, verwalten und zu konfigurieren.

Neben dem Erweitern von individuellen virtuellen Maschinenabbilder auf auf Standardhardware bietet CloudStack™ einen schlüsselfertigen Cloud Infrastruktur-Software-Stack für die Bereitstellung von virtueller Rechenzentren as a Service – Liefert alle wesentlichen Komponenten für das Bauen, Bereitstellen und Verwalten von multi-tier- und mandantenfähigen Cloud-Anwendungen. Open-Source sowie Premium-Versionen sind verfügbar, mit nahezu identischen Features.", +"message.installwizard.copy.whatiscloudstack": "CloudStack™ ist eine Software-Plattform welche Rechenressourcen zusammenfasst, um öffentliche, private oder hybride \"Infrastructure as a Service\" (IaaS) Clouds zu bauen. CloudStack™ verwaltet das Netzwerk-, Speicher- und Computingknoten was eine Cloud-Infrastruktur ausmacht. Benutzen Sie CloudStack™ um Computing-Umgebungen zu erstellen, verwalten und zu konfigurieren.

Neben dem Erweitern von individuellen virtuellen Maschinenabbilder auf auf Standardhardware bietet CloudStack™ einen schlüsselfertigen Cloud Infrastruktur-Software-Stack für die Bereitstellung von virtueller Rechenzentren as a Service – Liefert alle wesentlichen Komponenten für das Bauen, Bereitstellen und Verwalten von multi-tier- und mandantenfähigen Cloud-Anwendungen.", "message.installwizard.tooltip.addpod.name": "Der Name für den pod", "message.installwizard.tooltip.addpod.reservedsystemendip": "Dies ist der IP-Bereich im privaten Netzwerk, welches CloudStack verwendet um Sekundärspeicher-VMs und Konsolen-Proxies zu verwalten. Diese IP-Adressen werden vom selben Subnetz genommen wie Computing-Server.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "Das Gateways für die Hosts des pod", diff --git a/ui/public/locales/el_GR.json b/ui/public/locales/el_GR.json index 754cde89542..150ef68f5b0 100644 --- a/ui/public/locales/el_GR.json +++ b/ui/public/locales/el_GR.json @@ -2386,7 +2386,7 @@ "message.installwizard.cloudstack.helptext.releasenotes": " * Σημειώσης εκδόσεων:\t ", "message.installwizard.cloudstack.helptext.survey": " * Απαντήστε στην συλλογή στοιχείων:\t ", "message.installwizard.cloudstack.helptext.website": " * Σελίδα έργου:\t ", -"message.installwizard.copy.whatiscloudstack": "Το CloudStack™ είναι μια πλατφόρμα λογισμικού που συγκεντρώνει υπολογιστικούς πόρους για τη δημιουργία δημόσιων, ιδιωτικών και υβριδικών υποδομων ως υπηρεσίας (IaaS) cloud. Το CloudStack™ διαχειρίζεται τους κόμβους δικτύου, αποθήκευσης και υπολογισμού που αποτελούν μια υποδομή cloud. Χρησιμοποιήστε το CloudStack™ για να αναπτύξετε, να διαχειριστείτε και να ρυθμίσετε τις παραμέτρους περιβαλλόντων Cloud.\n\nΤο CloudStack™ παρέχει μια στοίβα λογισμικού υποδομής cloud για την παροχή εικονικών κέντρων δεδομένων ως υπηρεσία - παρέχοντας όλα τα βασικά στοιχεία για τη δημιουργία, την ανάπτυξη και τη διαχείριση εφαρμογών cloud πολλαπλών επιπέδων και πολλών tenants. Και οι εκδόσεις ανοιχτού κώδικα και Premium είναι διαθέσιμες, με την έκδοση ανοιχτού κώδικα να προσφέρει σχεδόν πανομοιότυπα χαρακτηριστικά.", +"message.installwizard.copy.whatiscloudstack": "Το CloudStack™ είναι μια πλατφόρμα λογισμικού που συγκεντρώνει υπολογιστικούς πόρους για τη δημιουργία δημόσιων, ιδιωτικών και υβριδικών υποδομων ως υπηρεσίας (IaaS) cloud. Το CloudStack™ διαχειρίζεται τους κόμβους δικτύου, αποθήκευσης και υπολογισμού που αποτελούν μια υποδομή cloud. Χρησιμοποιήστε το CloudStack™ για να αναπτύξετε, να διαχειριστείτε και να ρυθμίσετε τις παραμέτρους περιβαλλόντων Cloud.\n\nΤο CloudStack™ παρέχει μια στοίβα λογισμικού υποδομής cloud για την παροχή εικονικών κέντρων δεδομένων ως υπηρεσία - παρέχοντας όλα τα βασικά στοιχεία για τη δημιουργία, την ανάπτυξη και τη διαχείριση εφαρμογών cloud πολλαπλών επιπέδων και πολλών tenants.", "message.installwizard.tooltip.addpod.name": "Ένα όνομα για το pod", "message.installwizard.tooltip.addpod.reservedsystemendip": "Αυτή είναι η περιοχή IP στο ιδιωτικό δίκτυο που χρησιμοποιεί το CloudStack για τη διαχείριση των εικονικής μηχανής δευτερεύουσας αποθήκευσης και των εικονικής μηχανής διακομιστή μεσολάβησης κονσόλας. Αυτές οι διευθύνσεις IP λαμβάνονται από το ίδιο υποδίκτυο με τους διακομιστές υπολογιστών.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "Η πύλη για τους κεντρικους υπολογιστές σε αυτό το pod.", diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 78179cb8108..944a24f4219 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -2971,7 +2971,7 @@ "message.installwizard.cloudstack.helptext.mailinglists": " * Join mailing lists:\t ", "message.installwizard.cloudstack.helptext.releasenotes": " * Release notes:\t ", "message.installwizard.cloudstack.helptext.survey": " * Take the survey:\t ", -"message.installwizard.copy.whatiscloudstack": "CloudStack™ is a software platform that pools computing resources to build public, private, and hybrid Infrastructure as a Service (IaaS) clouds. CloudStack™ manages the Network, storage, and compute nodes that make up a cloud infrastructure. Use CloudStack™ to deploy, manage, and configure cloud computing environments.\n\nExtending beyond individual Instance images running on commodity hardware, CloudStack™ provides a turnkey cloud infrastructure software stack for delivering virtual datacenters as a service - delivering all of the essential components to build, deploy, and manage multi-tier and multi-tenant cloud applications. Both open-source and Premium versions are available, with the open-source version offering nearly identical features.", +"message.installwizard.copy.whatiscloudstack": "CloudStack™ is a software platform that pools computing resources to build public, private, and hybrid Infrastructure as a Service (IaaS) clouds. CloudStack™ manages the Network, storage, and compute nodes that make up a cloud infrastructure. Use CloudStack™ to deploy, manage, and configure cloud computing environments.\n\nExtending beyond individual Instance images running on commodity hardware, CloudStack™ provides a turnkey cloud infrastructure software stack for delivering virtual datacenters as a service - delivering all of the essential components to build, deploy, and manage multi-tier and multi-tenant cloud applications.", "message.installwizard.tooltip.addpod.name": "A name for the pod.", "message.installwizard.tooltip.addpod.reservedsystemendip": "This is the IP range in the private Network that the CloudStack uses to manage Secondary Storage VMs and Console Proxy VMs. These IP addresses are taken from the same subnet as computing servers.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "The gateway for the hosts in that pod.", diff --git a/ui/public/locales/es.json b/ui/public/locales/es.json index 76488937574..ae4fa19f033 100644 --- a/ui/public/locales/es.json +++ b/ui/public/locales/es.json @@ -1437,7 +1437,7 @@ "message.guest.traffic.in.basic.zone": "El tr\u00e1fico de las redes invitado es el generado entre las m\u00e1quina virtuales del usuario final. Especifique un rango de direcciones IP para que CloudStack pueda asignar a las MVs Invitado. Asegures\u00e9 que este rango no se solape con el rango IP reservado para el sistema.", "message.host.dedicated": "Servidor Dedicado", "message.host.dedication.released": "Dedicaci\u00f3n de Servidor liberada", -"message.installwizard.copy.whatiscloudstack": "CloudStack™ es una plataforma de software que aglutina recursos c\u00f3mputo para construir Infraestructuras como Servicio (IaaS), tanto de cloud p\u00fablico como privado e h\u00edbrido.\nCloudStack™ gestiona la red, el almacenamiento y los nodos de c\u00f3mputo que conforma la infraestructura de cloud. Se puede usar CloudStack™ para desplegar, gestionar y configurar entornos de computaci\u00f3n en la nube.

Cloudstack™ vam\u00e1s all\u00e1 del manejo individual de m\u00e1quinas virtuales en hardware de prop\u00f3sito general, ya que proporciona una soluci\u00f3n llave en mano para desplegar datacenters como servicio - proporcionando todos los componentes esenciales para construir, desplegar y gestionar aplicaciones cloud multi-tier y multi-tenant. Se ofrecen dos versiones, la open source y la Premium, brindando la primera caracter\u00edsticas casi id\u00e9nticas.", +"message.installwizard.copy.whatiscloudstack": "CloudStack™ es una plataforma de software que aglutina recursos c\u00f3mputo para construir Infraestructuras como Servicio (IaaS), tanto de cloud p\u00fablico como privado e h\u00edbrido.\nCloudStack™ gestiona la red, el almacenamiento y los nodos de c\u00f3mputo que conforma la infraestructura de cloud. Se puede usar CloudStack™ para desplegar, gestionar y configurar entornos de computaci\u00f3n en la nube.

Cloudstack™ vam\u00e1s all\u00e1 del manejo individual de m\u00e1quinas virtuales en hardware de prop\u00f3sito general, ya que proporciona una soluci\u00f3n llave en mano para desplegar datacenters como servicio - proporcionando todos los componentes esenciales para construir, desplegar y gestionar aplicaciones cloud multi-tier y multi-tenant.", "message.installwizard.tooltip.addpod.name": "Nombre del POD", "message.installwizard.tooltip.addpod.reservedsystemendip": "Este es el rango de direcciones IP en la red privada que CloudStack utiliza para administrar las MVs del Almacenamiento Secundario y proxy de consolas. Estas direcciones IP se han tomado de la misma subred que los servidores inform\u00e1ticos.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "La puerta de enlace para los host en ese pod.", diff --git a/ui/public/locales/fr_FR.json b/ui/public/locales/fr_FR.json index f11f4ac5c94..48a0560f176 100644 --- a/ui/public/locales/fr_FR.json +++ b/ui/public/locales/fr_FR.json @@ -1407,7 +1407,7 @@ "message.guest.traffic.in.basic.zone": "Le trafic r\u00e9seau d'invit\u00e9 est la communication entre les machines virtuelles utilisateur. Sp\u00e9cifier une plage d'adresses IP que CloudStack peut assigner aux machines virtuelles Invit\u00e9. S'assurer que cette plage n'empi\u00e8te pas sur la plage r\u00e9serv\u00e9e aux adresses IP Syst\u00e8me.", "message.host.dedicated": "H\u00f4te d\u00e9di\u00e9e", "message.host.dedication.released": "Lib\u00e9ration de l'h\u00f4te d\u00e9di\u00e9", -"message.installwizard.copy.whatiscloudstack": "CloudStack™ est une plate-forme logicielle de pools de ressources informatiques pour construire des infrastructures publiques, priv\u00e9es et hybrides en tant que services (IaaS) dans les nuages. CloudStack™ g\u00e8re le r\u00e9seau, le stockage et les noeuds de calcul qui composent une infrastructure dans les nuages. Utilisez CloudStack™ pour d\u00e9ployer, g\u00e9rer et configurer les environnements d'informatiques dans les nuages.

S'\u00e9tendant au-del\u00e0 des machines virtuelles individuelles fonctionnant sur du mat\u00e9riel standard, CloudStack™ offre une solution d'informatique en nuage cl\u00e9 en main pour fournir des centres de donn\u00e9es virtuels comme service - fournissant tous les composants essentiels pour construire, d\u00e9ployer et g\u00e9rer des applications 'cloud' multi-niveaux et multi-locataire. Les versions libre et Premium sont disponibles, la version Libre offrant des caract\u00e9ristiques presque identiques.", +"message.installwizard.copy.whatiscloudstack": "CloudStack™ est une plate-forme logicielle de pools de ressources informatiques pour construire des infrastructures publiques, priv\u00e9es et hybrides en tant que services (IaaS) dans les nuages. CloudStack™ g\u00e8re le r\u00e9seau, le stockage et les noeuds de calcul qui composent une infrastructure dans les nuages. Utilisez CloudStack™ pour d\u00e9ployer, g\u00e9rer et configurer les environnements d'informatiques dans les nuages.

S'\u00e9tendant au-del\u00e0 des machines virtuelles individuelles fonctionnant sur du mat\u00e9riel standard, CloudStack™ offre une solution d'informatique en nuage cl\u00e9 en main pour fournir des centres de donn\u00e9es virtuels comme service - fournissant tous les composants essentiels pour construire, d\u00e9ployer et g\u00e9rer des applications 'cloud' multi-niveaux et multi-locataire.", "message.installwizard.tooltip.addpod.name": "Nom pour le pod", "message.installwizard.tooltip.addpod.reservedsystemendip": "Ceci est la plage d'adresses IP dans le r\u00e9seau priv\u00e9 que CloudStack utilise la gestion des VMs du stockage secondaire et les VMs Console Proxy. Ces adresses IP sont prises dans le m\u00eame sous-r\u00e9seau que les serveurs h\u00f4tes.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "Passerelle pour les serveurs dans ce pod", diff --git a/ui/public/locales/hu.json b/ui/public/locales/hu.json index 445d3a1d5f5..48275ce81fc 100644 --- a/ui/public/locales/hu.json +++ b/ui/public/locales/hu.json @@ -1405,7 +1405,7 @@ "message.guest.traffic.in.basic.zone": "A vend\u00e9g h\u00e1l\u00f3zat forgalma kommunik\u00f3ci\u00f3 v\u00e9gfelhaszn\u00e1l\u00f3i virtu\u00e1lis g\u00e9pek k\u00f6z\u00f6tt. Hat\u00e1rozz meg egy IP c\u00edmtartom\u00e1nyt, amelyb\u0151l a CloudStack a virtu\u00e1lis g\u00e9pekhez rendelhet c\u00edmet. Gy\u0151z\u0151dj meg r\u00f3la, hogy ez a tartom\u00e1ny nincs \u00e1tfed\u00e9sben az elk\u00fcl\u00f6n\u00edtett rendszer IP tartom\u00e1nnyal!", "message.host.dedicated": "Dedik\u00e1lt kiszolg\u00e1l\u00f3", "message.host.dedication.released": "Kiszolg\u00e1l\u00f3 elengedve", -"message.installwizard.copy.whatiscloudstack": "A CloudStack™ egy szoftver, amely sz\u00e1m\u00edt\u00e1si er\u0151forr\u00e1sokat fel\u00fcgyel \u00e9s alkalmas publikus, priv\u00e1t, vagy hibrid infrastrukt\u00fara szolg\u00e1ltat\u00e1s (IaaS) felh\u0151k \u00e9p\u00edt\u00e9s\u00e9re. A CloudStack™ ir\u00e1ny\u00edtja a h\u00e1l\u00f3zatokat, az adatt\u00e1rol\u00f3kat \u00e9s kiszolg\u00e1l\u00f3kat, amelyek a felh\u0151 infrastrukt\u00far\u00e1t alkotj\u00e1k.

A k\u00fcl\u00f6n\u00e1ll\u00f3 virtu\u00e1lis g\u00e9peken t\u00fal a CloudStack™ teljes felh\u0151 insfrastrukt\u00far\u00e1t szolg\u00e1ltat. Ny\u00edlt forr\u00e1sk\u00f3d\u00fa \u00e9s pr\u00e9mium verzi\u00f3k egyar\u00e1nt el\u00e9rhet\u0151ek, a ny\u00edlt forr\u00e1sk\u00f3d\u00fa verzi\u00f3k k\u00f6zel azonos k\u00e9pess\u00e9gekkel rendelkeznek.", +"message.installwizard.copy.whatiscloudstack": "A CloudStack™ egy szoftver, amely sz\u00e1m\u00edt\u00e1si er\u0151forr\u00e1sokat fel\u00fcgyel \u00e9s alkalmas publikus, priv\u00e1t, vagy hibrid infrastrukt\u00fara szolg\u00e1ltat\u00e1s (IaaS) felh\u0151k \u00e9p\u00edt\u00e9s\u00e9re. A CloudStack™ ir\u00e1ny\u00edtja a h\u00e1l\u00f3zatokat, az adatt\u00e1rol\u00f3kat \u00e9s kiszolg\u00e1l\u00f3kat, amelyek a felh\u0151 infrastrukt\u00far\u00e1t alkotj\u00e1k.

A k\u00fcl\u00f6n\u00e1ll\u00f3 virtu\u00e1lis g\u00e9peken t\u00fal a CloudStack™ teljes felh\u0151 insfrastrukt\u00far\u00e1t szolg\u00e1ltat.", "message.installwizard.tooltip.addpod.name": "A pod neve", "message.installwizard.tooltip.addpod.reservedsystemendip": "This is the IP range in the private network that the CloudStack uses to manage Secondary Storage VMs and Console Proxy VMs. These IP addresses are taken from the same subnet as computing servers.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "\u00c1tj\u00e1r\u00f3 a pod kiszolg\u00e1l\u00f3inak.", diff --git a/ui/public/locales/it_IT.json b/ui/public/locales/it_IT.json index fa09e189d98..844763eba3a 100644 --- a/ui/public/locales/it_IT.json +++ b/ui/public/locales/it_IT.json @@ -1405,7 +1405,7 @@ "message.guest.traffic.in.basic.zone": "Guest network traffic is communication between end-user virtual machines. Specify a range of IP addresses that CloudStack can assign to guest VMs. Make sure this range does not overlap the reserved system IP range.", "message.host.dedicated": "Host Dedicated", "message.host.dedication.released": "Host dedication released", -"message.installwizard.copy.whatiscloudstack": "CloudStack™ is a software platform that pools computing resources to build public, private, and hybrid Infrastructure as a Service (IaaS) clouds. CloudStack™ manages the network, storage, and compute nodes that make up a cloud infrastructure. Use CloudStack™ to deploy, manage, and configure cloud computing environments.

Extending beyond individual virtual machine images running on commodity hardware, CloudStack™ provides a turnkey cloud infrastructure software stack for delivering virtual datacenters as a service - delivering all of the essential components to build, deploy, and manage multi-tier and multi-tenant cloud applications. Both open-source and Premium versions are available, with the open-source version offering nearly identical features.", +"message.installwizard.copy.whatiscloudstack": "CloudStack™ is a software platform that pools computing resources to build public, private, and hybrid Infrastructure as a Service (IaaS) clouds. CloudStack™ manages the network, storage, and compute nodes that make up a cloud infrastructure. Use CloudStack™ to deploy, manage, and configure cloud computing environments.

Extending beyond individual virtual machine images running on commodity hardware, CloudStack™ provides a turnkey cloud infrastructure software stack for delivering virtual datacenters as a service - delivering all of the essential components to build, deploy, and manage multi-tier and multi-tenant cloud applications.", "message.installwizard.tooltip.addpod.name": "Un nome per il pod", "message.installwizard.tooltip.addpod.reservedsystemendip": "Questo \u00e8 l'intervallo di indirizzi IP nella rete privata che CloudStack utilizza per la gestione delle VM del Secondary Storage e le VM della Console Proxy. Questi indirizzi IP sono ricavati dalla stessa subnet dei server computazionali.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "Il gateway per gli host appartenenti al pod.", diff --git a/ui/public/locales/ja_JP.json b/ui/public/locales/ja_JP.json index f1518286f80..8157c2e6021 100644 --- a/ui/public/locales/ja_JP.json +++ b/ui/public/locales/ja_JP.json @@ -3064,7 +3064,7 @@ "message.installwizard.copy.whatisahost": "ホストは単一のコンピューターで、ゲスト仮想マシンを実行するコンピューティング リソースをオファリングします。ベア メタル ホストを除いて、各ホストにはゲスト仮想マシンを管理するためのハイパーバイザー ソフトウェアをインストールします。ベア メタル ホストについては、『インストールガイド上級編』で特殊例として説明します。たとえば、KVM が有効な Linux サーバー、Citrix XenServer が動作するサーバー、および ESXi サーバーがホストです。基本インストールでは、XenServer または KVM を実行する単一のホストを使用します。

ホストは CloudStack™ 環境内の最小の組織単位です。ホストはクラスターに含まれ、クラスターはポッドに含まれ、ポッドはゾーンに含まれます。", "message.installwizard.copy.whatisapod": "通常、1つのポッドは単一のラックを表します。同じポッド内のホストは同じサブネットに含まれます。

ポッドはCloudStack™環境内の2番目に大きな組織単位です。ポッドはゾーンに含まれます。各ゾーンは1つ以上のポッドを含むことができます。基本インストールでは、ゾーン内のポッドは1つです。", "message.installwizard.copy.whatisazone": "ゾーンはCloudStack™環境内の最大の組織単位です。1つのデータセンター内に複数のゾーンを設定できますが、通常、ゾーンは単一のデータセンターに相当します。インフラストラクチャをゾーンに組織化すると、ゾーンを物理的に分離して冗長化することができます。たとえば、各ゾーンに電源とネットワークアップリンクを配備します。必須ではありませんが、ゾーンは遠隔地に分散することができます。", - "message.installwizard.copy.whatiscloudstack": "CloudStack™はコンピューティングリソースをプールするソフトウェアプラットフォームで、パブリック、プライベート、およびハイブリッドのInfrastructure as a Service(IaaS)クラウドを構築することができます。CloudStack™を使用して、クラウドインフラストラクチャを構成するネットワーク、ストレージ、およびコンピューティングノードを管理し、クラウドコンピューティング環境を展開、管理、および構成します。

CloudStack™はコモディティ化したハードウェア上で動作する個別の仮想マシンイメージを超えて拡張することができ、簡単な設定で動作するクラウドインフラストラクチャのソフトウェアスタックによって、仮想データセンターつまり多層型のマルチテナントクラウドアプリケーションをサービスとして構築し、展開し、管理するために不可欠なコンポーネントがすべてオファリングされます。オープンソースバージョンとプレミアムバージョンの両方がオファリングされますが、オープンソースバージョンでもほとんどの機能を使用できます。", + "message.installwizard.copy.whatiscloudstack": "CloudStack™はコンピューティングリソースをプールするソフトウェアプラットフォームで、パブリック、プライベート、およびハイブリッドのInfrastructure as a Service(IaaS)クラウドを構築することができます。CloudStack™を使用して、クラウドインフラストラクチャを構成するネットワーク、ストレージ、およびコンピューティングノードを管理し、クラウドコンピューティング環境を展開、管理、および構成します。

CloudStack™はコモディティ化したハードウェア上で動作する個別の仮想マシンイメージを超えて拡張することができ、簡単な設定で動作するクラウドインフラストラクチャのソフトウェアスタックによって、仮想データセンターつまり多層型のマルチテナントクラウドアプリケーションをサービスとして構築し、展開し、管理するために不可欠なコンポーネントがすべてオファリングされます。", "message.installwizard.copy.whatisprimarystorage": "CloudStack™のクラウドインフラストラクチャでは、プライマリストレージとセカンダリストレージの2種類のストレージを使用します。どちらのストレージにも、iSCSI、NFSサーバー、またはローカルディスクを使用できます。

プライマリストレージはクラスターに関連付けられ、そのクラスター内のホストで動作するすべてのVMの各ゲストVMのディスクボリュームを格納します。通常、プライマリストレージサーバーはホストの近くに設置します。", "message.installwizard.copy.whatissecondarystorage": "セカンダリストレージはゾーンと関連付けられ、次の項目を格納します。
  • テンプレート - VMの起動に使用できるOSイメージで、アプリケーションのインストールなど追加の構成を含めることができます。
  • ISOイメージ - 起動可能または起動不可のOSイメージです。
  • ディスクボリュームのスナップショット - VMデータの保存コピーです。データの復元または新しいテンプレートの作成に使用できます。
", "message.installwizard.now.building": "クラウドを構築しています...", diff --git a/ui/public/locales/ko_KR.json b/ui/public/locales/ko_KR.json index a34cdea767f..e524f72ebc1 100644 --- a/ui/public/locales/ko_KR.json +++ b/ui/public/locales/ko_KR.json @@ -2053,7 +2053,7 @@ "message.host.dedicated": "\uc804\uc6a9 \ud638\uc2a4\ud2b8", "message.host.dedication.released": "\uc804\uc6a9 \ud638\uc2a4\ud2b8 \ucd9c\uc2dc", "message.info.cloudian.console": "Cloudian \uad00\ub9ac \ucf58\uc194\uc774 \ub2e4\ub978 \ucc3d\uc5d0\uc11c \uc5f4\ub9bd\ub2c8\ub2e4.", -"message.installwizard.copy.whatiscloudstack": "CloudStack\u2122\uc740 \ucef4\ud4e8\ud305 \ub9ac\uc18c\uc2a4\ub97c \ud3ec\ud568\ud558\uc5ec \uacf5\uac1c, \uc0ac\uc124, \ubc0f \ud558\uc774\ube0c\ub9ac\ub4dc\uc758 Infrastructure as a Service (IaaS) \ud074\ub77c\uc6b0\ub4dc\ub97c \uad6c\ucd95\ud560 \uc218 \uc788\ub294 \uc18c\ud504\ud2b8\uc6e8\uc5b4 \ud50c\ub7ab\ud3fc\uc785\ub2c8\ub2e4. CloudStack \u2122\uc740 \ud074\ub77c\uc6b0\ub4dc \uc778\ud504\ub77c\ub97c \uad6c\uc131\ud558\ub294 \ub124\ud2b8\uc6cc\ud06c, \uc2a4\ud1a0\ub9ac\uc9c0 \ubc0f \ucef4\ud4e8\ud305 \ub178\ub4dc\ub97c \uad00\ub9ac\ud569\ub2c8\ub2e4. CloudStack \u2122\uc744 \uc0ac\uc6a9\ud558\uc5ec \ud074\ub77c\uc6b0\ub4dc \ucef4\ud4e8\ud305 \ud658\uacbd\uc744 \ubc30\ud3ec, \uad00\ub9ac \ubc0f \uad6c\uc131\ud558\uc2ed\uc2dc\uc624. \n\nCloudStack \u2122 \uc77c\ubc18 \ud558\ub4dc\uc6e8\uc5b4\uc5d0\uc11c \uc2e4\ud589\ub418\ub294 \uac1c\ubcc4 \uac00\uc0c1\uba38\uc2e0 \uc774\ubbf8\uc9c0\ub97c \ub118\uc5b4 \ud655\uc7a5\ub418\uc5b4 \uac00\uc0c1 \ub370\uc774\ud130 \uc13c\ud130\ub97c \uc11c\ube44\uc2a4\ub85c \uc81c\uacf5\ud558\uae30\uc704\ud55c \ud134\ud0a4 \ud074\ub77c\uc6b0\ub4dc \uc778\ud504\ub77c \uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc2a4\ud0dd\uc744 \uc81c\uacf5\ud558\uc5ec \ubaa8\ub4e0 \ud544\uc218 \uae30\ub2a5\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4. \ub2e4\uc911 \uacc4\uce35 \ubc0f \ub2e4\uc911 \ud14c\ub10c\ud2b8 \ud074\ub77c\uc6b0\ub4dc \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ube4c\ub4dc, \ubc30\ud3ec \ubc0f \uad00\ub9ac\ud558\uae30\uc704\ud55c \uad6c\uc131 \uc694\uc18c\uc785\ub2c8\ub2e4. \uc624\ud508 \uc18c\uc2a4 \ubc0f \ud504\ub9ac\ubbf8\uc5c4 \ubc84\uc804\uc744 \ubaa8\ub450 \uc0ac\uc6a9\ud560 \uc218 \uc788\uc73c\uba70 \uc624\ud508 \uc18c\uc2a4 \ubc84\uc804\uc740 \uac70\uc758 \ub3d9\uc77c\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4.", +"message.installwizard.copy.whatiscloudstack": "CloudStack\u2122\uc740 \ucef4\ud4e8\ud305 \ub9ac\uc18c\uc2a4\ub97c \ud3ec\ud568\ud558\uc5ec \uacf5\uac1c, \uc0ac\uc124, \ubc0f \ud558\uc774\ube0c\ub9ac\ub4dc\uc758 Infrastructure as a Service (IaaS) \ud074\ub77c\uc6b0\ub4dc\ub97c \uad6c\ucd95\ud560 \uc218 \uc788\ub294 \uc18c\ud504\ud2b8\uc6e8\uc5b4 \ud50c\ub7ab\ud3fc\uc785\ub2c8\ub2e4. CloudStack \u2122\uc740 \ud074\ub77c\uc6b0\ub4dc \uc778\ud504\ub77c\ub97c \uad6c\uc131\ud558\ub294 \ub124\ud2b8\uc6cc\ud06c, \uc2a4\ud1a0\ub9ac\uc9c0 \ubc0f \ucef4\ud4e8\ud305 \ub178\ub4dc\ub97c \uad00\ub9ac\ud569\ub2c8\ub2e4. CloudStack \u2122\uc744 \uc0ac\uc6a9\ud558\uc5ec \ud074\ub77c\uc6b0\ub4dc \ucef4\ud4e8\ud305 \ud658\uacbd\uc744 \ubc30\ud3ec, \uad00\ub9ac \ubc0f \uad6c\uc131\ud558\uc2ed\uc2dc\uc624. \n\nCloudStack \u2122 \uc77c\ubc18 \ud558\ub4dc\uc6e8\uc5b4\uc5d0\uc11c \uc2e4\ud589\ub418\ub294 \uac1c\ubcc4 \uac00\uc0c1\uba38\uc2e0 \uc774\ubbf8\uc9c0\ub97c \ub118\uc5b4 \ud655\uc7a5\ub418\uc5b4 \uac00\uc0c1 \ub370\uc774\ud130 \uc13c\ud130\ub97c \uc11c\ube44\uc2a4\ub85c \uc81c\uacf5\ud558\uae30\uc704\ud55c \ud134\ud0a4 \ud074\ub77c\uc6b0\ub4dc \uc778\ud504\ub77c \uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc2a4\ud0dd\uc744 \uc81c\uacf5\ud558\uc5ec \ubaa8\ub4e0 \ud544\uc218 \uae30\ub2a5\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4. \ub2e4\uc911 \uacc4\uce35 \ubc0f \ub2e4\uc911 \ud14c\ub10c\ud2b8 \ud074\ub77c\uc6b0\ub4dc \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ube4c\ub4dc, \ubc30\ud3ec \ubc0f \uad00\ub9ac\ud558\uae30\uc704\ud55c \uad6c\uc131 \uc694\uc18c\uc785\ub2c8\ub2e4.", "message.installwizard.tooltip.addpod.name": "Pod \uc774\ub984\uc785\ub2c8\ub2e4.", "message.installwizard.tooltip.addpod.reservedsystemendip": "\uc774\uac83\uc740 2\ucc28 \uc2a4\ud1a0\ub9ac\uc9c0 VM \ubc0f \ucf58\uc194 \ud504\ub85d\uc2dc VM\ub97c \uad00\ub9ac\ud558\uae30 \uc704\ud574\uc11c CloudStack\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \uc0ac\uc124 \ub124\ud2b8\uc6cc\ud06c\ub0b4 IP \uc8fc\uc18c \ubc94\uc704\uc785\ub2c8\ub2e4. \uc774\ub7ec\ud55c IP \uc8fc\uc18c\ub294 \ucef4\ud4e8\ud305 \uc11c\ubc84\uc640 \uac19\uc740 \uc11c\ube0c\ub124\ud2b8\uc6cc\ud06c\uc5d0\uc11c \ud560\ub2f9\ud569\ub2c8\ub2e4.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "\ud604\uc7ac Pod\ub0b4 \ud638\uc2a4\ud2b8 \uac8c\uc774\ud2b8\uc6e8\uc774\uc785\ub2c8\ub2e4.", diff --git a/ui/public/locales/nb_NO.json b/ui/public/locales/nb_NO.json index a0fbd8927df..ec51f7415d3 100644 --- a/ui/public/locales/nb_NO.json +++ b/ui/public/locales/nb_NO.json @@ -1405,7 +1405,7 @@ "message.guest.traffic.in.basic.zone": "Gjestetrafikk er kommunikasjon mellom sluttbrukers virtuelle gjester. Spesifiser en rekke med IP-adresser som CloudStack kan tildele virtuelle gjester. S\u00f8rg for at denne rekken ikke overlapper IP-rekken(e) som er reservert systemmaskiner.", "message.host.dedicated": "Dedikert Vert", "message.host.dedication.released": "Vert dedikering frigitt", -"message.installwizard.copy.whatiscloudstack": "CloudStack™ er en programvare-plattform som grupperer dataressurser for \u00e5 bygge offentlige, private og hybride infrastruktur som en tjeneste (IaaS) skyer. CloudStack™ administrerer nettverk, lagring og regnekraft-verter som til sammen blir en sky-infrastruktur. Bruk CloudStack™ til \u00e5 distribuere, administrerre og konfigurere dine skyressurser og milj\u00f8er.

Utvid forbi individuelle virtuelle gjester som kj\u00f8rer p\u00e5 typisk maskinvare, CloudStack™ gir en skybasert infrastruktur-programvare for levering av virtuelle datasentre som en tjeneste - lever alle de essensielle komponenente for \u00e5 bygge, distribuere og administrere multi-tier og multi-tenant sky-applikasjoner. B\u00e5de fri kildekode- og premium-versjoner er tilgjengelig, hvor den fri kildekode-basert gir tiln\u00e6rmet samme funksjonalitet.", +"message.installwizard.copy.whatiscloudstack": "CloudStack™ er en programvare-plattform som grupperer dataressurser for \u00e5 bygge offentlige, private og hybride infrastruktur som en tjeneste (IaaS) skyer. CloudStack™ administrerer nettverk, lagring og regnekraft-verter som til sammen blir en sky-infrastruktur. Bruk CloudStack™ til \u00e5 distribuere, administrerre og konfigurere dine skyressurser og milj\u00f8er.

Utvid forbi individuelle virtuelle gjester som kj\u00f8rer p\u00e5 typisk maskinvare, CloudStack™ gir en skybasert infrastruktur-programvare for levering av virtuelle datasentre som en tjeneste - lever alle de essensielle komponenente for \u00e5 bygge, distribuere og administrere multi-tier og multi-tenant sky-applikasjoner.", "message.installwizard.tooltip.addpod.name": "Et navn for poden", "message.installwizard.tooltip.addpod.reservedsystemendip": "Dette er IP-rekken i det private nettverket som CloudStack bruker for \u00e5 administrere Sekund\u00e6rlagrins-servere og Konsollproxy-servere. Disse IP-adressene tas fra samme subnett som regnekraft-serverne.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "Gatewayen til vertene i poden.", diff --git a/ui/public/locales/nl_NL.json b/ui/public/locales/nl_NL.json index 8e637f190b3..6bd1bf67159 100644 --- a/ui/public/locales/nl_NL.json +++ b/ui/public/locales/nl_NL.json @@ -1406,7 +1406,7 @@ "message.guest.traffic.in.basic.zone": "Gast netwerk verkeer is communicatie tussen virtuele machines van de eindgebruiker. Specificeer een range van IP adressen welke CloudStack kan uitdelen aan gast VMs. Let erop dat deze range niet overlapt met de gereserveerde systeem IP range.", "message.host.dedicated": "Host toegewijd", "message.host.dedication.released": "Toegewijde host losgekoppeld", -"message.installwizard.copy.whatiscloudstack": "CloudStack™ is een software platform welke computer capaciteit herenigd om public, private en hybrid infrastructure as a Service (IaaS) clouds te bouwen. CloudStack™ beheert het netwerk, de opslag en de computer nodes welke de cloud infrastructuur vertegenwoordigen. Gebruik CloudStack™ om cloud computing omgevingen uit te rollen, te beheren en te configureren.

CloudStack™ gaat veel verder dan het draaien van virtuele machine bestanden op commodity hardware, het is een turnkey oplossing om virtuele datacenters (as a service) te realiseren. Daarbij levert het alle essenti\u00eble componenten om multi-tier en multi-tentant cloud applicaties te bouwen en te beheren. Er is een zowel een open-source als Premium versie beschikbaar, waarbij de open-source versie nagenoeg dezelfde functionaliteit biedt als de Premium versie.", +"message.installwizard.copy.whatiscloudstack": "CloudStack™ is een software platform welke computer capaciteit herenigd om public, private en hybrid infrastructure as a Service (IaaS) clouds te bouwen. CloudStack™ beheert het netwerk, de opslag en de computer nodes welke de cloud infrastructuur vertegenwoordigen. Gebruik CloudStack™ om cloud computing omgevingen uit te rollen, te beheren en te configureren.

CloudStack™ gaat veel verder dan het draaien van virtuele machine bestanden op commodity hardware, het is een turnkey oplossing om virtuele datacenters (as a service) te realiseren. Daarbij levert het alle essenti\u00eble componenten om multi-tier en multi-tentant cloud applicaties te bouwen en te beheren.", "message.installwizard.tooltip.addpod.name": "Een naam voor de pod", "message.installwizard.tooltip.addpod.reservedsystemendip": "Dit is de IP range van het private netwerk dat CloudStack gebruikt om met Secundaire Opslag VMs en Console Proxy VMs te communiceren. Deze IP adressen komen uit hetzelfde subnet als de gast VMs.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "De gateway voor de hosts in die pod.", diff --git a/ui/public/locales/pl.json b/ui/public/locales/pl.json index 6838b5e2a59..6077da5928e 100644 --- a/ui/public/locales/pl.json +++ b/ui/public/locales/pl.json @@ -1406,7 +1406,7 @@ "message.guest.traffic.in.basic.zone": "Guest network traffic is communication between end-user virtual machines. Specify a range of IP addresses that CloudStack can assign to guest VMs. Make sure this range does not overlap the reserved system IP range.", "message.host.dedicated": "Host Dedicated", "message.host.dedication.released": "Host dedication released", -"message.installwizard.copy.whatiscloudstack": "CloudStack™ is a software platform that pools computing resources to build public, private, and hybrid Infrastructure as a Service (IaaS) clouds. CloudStack™ manages the network, storage, and compute nodes that make up a cloud infrastructure. Use CloudStack™ to deploy, manage, and configure cloud computing environments.

Extending beyond individual virtual machine images running on commodity hardware, CloudStack™ provides a turnkey cloud infrastructure software stack for delivering virtual datacenters as a service - delivering all of the essential components to build, deploy, and manage multi-tier and multi-tenant cloud applications. Both open-source and Premium versions are available, with the open-source version offering nearly identical features.", +"message.installwizard.copy.whatiscloudstack": "CloudStack™ is a software platform that pools computing resources to build public, private, and hybrid Infrastructure as a Service (IaaS) clouds. CloudStack™ manages the network, storage, and compute nodes that make up a cloud infrastructure. Use CloudStack™ to deploy, manage, and configure cloud computing environments.

Extending beyond individual virtual machine images running on commodity hardware, CloudStack™ provides a turnkey cloud infrastructure software stack for delivering virtual datacenters as a service - delivering all of the essential components to build, deploy, and manage multi-tier and multi-tenant cloud applications.", "message.installwizard.tooltip.addpod.name": "A name for the pod", "message.installwizard.tooltip.addpod.reservedsystemendip": "This is the IP range in the private network that the CloudStack uses to manage Secondary Storage VMs and Console Proxy VMs. These IP addresses are taken from the same subnet as computing servers.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "The gateway for the hosts in that pod.", diff --git a/ui/public/locales/pt_BR.json b/ui/public/locales/pt_BR.json index 937caa69a59..66684ca4bc3 100644 --- a/ui/public/locales/pt_BR.json +++ b/ui/public/locales/pt_BR.json @@ -2197,7 +2197,7 @@ "message.host.dedicated": "Host dedicado", "message.host.dedication.released": "Host dedicado liberado", "message.info.cloudian.console": "O Cloudian management console deve abrir em outra janela", -"message.installwizard.copy.whatiscloudstack": "O CloudStack™ \u00e9 uma plataforma de software que agrega recursos computacionais para construir uma Cloud de infraestrutura como servi\u00e7o (IaaS) p\u00fablica, privada ou h\u00edbrida. O CloudStack™ ger\u00eancia a rede, o armazenamento e os recursos computacionais que comp\u00f5em a infraestrutura de cloud. utilize o CloudStack™ para instalar, gerenciar e configurar os ambientes de cloud computing.

Indo al\u00e9m de imagens de m\u00e1quinas virtuais individuais rodando em hardware commodity, CloudStack™ prov\u00ea uma solu\u00e7\u00e3o completa de software de infraestrutura de cloud para entregar datacenters virtuais como um servi\u00e7o - possuindo todos os componentes essenciais para contruir, instalar e gerenciar aplica\u00e7\u00f5es na cloud multi-camadas e multi-tenant. Ambas as vers\u00f5es open-source e premium est\u00e3o dispon\u00edveis, com a vers\u00e3o opensource oferecendo praticamente os mesmos recursos.", +"message.installwizard.copy.whatiscloudstack": "O CloudStack™ \u00e9 uma plataforma de software que agrega recursos computacionais para construir uma Cloud de infraestrutura como servi\u00e7o (IaaS) p\u00fablica, privada ou h\u00edbrida. O CloudStack™ ger\u00eancia a rede, o armazenamento e os recursos computacionais que comp\u00f5em a infraestrutura de cloud. utilize o CloudStack™ para instalar, gerenciar e configurar os ambientes de cloud computing.

Indo al\u00e9m de imagens de m\u00e1quinas virtuais individuais rodando em hardware commodity, CloudStack™ prov\u00ea uma solu\u00e7\u00e3o completa de software de infraestrutura de cloud para entregar datacenters virtuais como um servi\u00e7o - possuindo todos os componentes essenciais para contruir, instalar e gerenciar aplica\u00e7\u00f5es na cloud multi-camadas e multi-tenant.", "message.installwizard.tooltip.addpod.name": "O nome para o pod", "message.installwizard.tooltip.addpod.reservedsystemendip": "Este \u00e9 o range de IP na rede privada que o CloudStack utiliza para gerenciar o armazenamento secund\u00e1rio das VMs e proxy console das VMs. estes endere\u00e7os IP s\u00e3o obtidos da mesma subrede dos servidores hosts.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "O gateway para os hosts neste pod.", diff --git a/ui/public/locales/ru_RU.json b/ui/public/locales/ru_RU.json index f68d767d762..46d70081f1b 100644 --- a/ui/public/locales/ru_RU.json +++ b/ui/public/locales/ru_RU.json @@ -1404,7 +1404,7 @@ "message.guest.traffic.in.basic.zone": "\u0413\u043e\u0441\u0442\u0435\u0432\u043e\u0439 \u0442\u0440\u0430\u0444\u0438\u043a \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043e\u0431\u0449\u0435\u043d\u0438\u0438 \u043c\u0435\u0436\u0434\u0443 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u043c\u0430\u0448\u0438\u043d\u0430\u043c\u0438. \u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u0430\u0434\u0440\u0435\u0441\u043e\u0432 IP, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 CloudStack \u0441\u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u0434\u043b\u044f \u0412\u041c. \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u043d\u0435 \u043f\u0435\u0440\u0435\u043a\u0440\u0435\u0449\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u043e\u043c \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u044b\u0445 \u0430\u0434\u0440\u0435\u0441\u043e\u0432.", "message.host.dedicated": "Host Dedicated", "message.host.dedication.released": "Host dedication released", -"message.installwizard.copy.whatiscloudstack": "CloudStack™ - \u044d\u0442\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u0430\u044f \u043f\u043b\u0430\u0444\u0442\u043e\u0440\u043c\u0430 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445, \u0447\u0430\u0441\u0442\u043d\u044b\u0445 \u0438 \u0433\u0438\u0431\u0440\u0438\u0434\u043d\u044b\u0445 \u043e\u0431\u043b\u0430\u043a\u043e\u0432 \u043f\u043e \u0441\u0445\u0435\u043c\u0435 \u00ab\u0418\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043a\u0430\u043a \u0441\u0435\u0440\u0432\u0438\u0441\u00bb (IaaS). CloudStack™ \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u0435\u0442\u044c\u044e, \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c \u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0443\u0437\u043b\u0430\u043c\u0438, \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0432 \u043e\u0431\u043b\u0430\u0447\u043d\u0443\u044e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443. \u0413\u043b\u0430\u0432\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, CloudStack™ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439.

CloudStack™ \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0438 \u0446\u0435\u043b\u043e\u0433\u043e \u0446\u0435\u043d\u0442\u0440\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043e\u0431\u043b\u0430\u043a\u0430. \u041c\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043c\u0435\u0436\u0434\u0443 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0439 \u0438 \u0411\u0435\u0437\u043d\u0435\u0441-\u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0447\u0442\u0438 \u043d\u0438\u0447\u0435\u043c \u043d\u0435 \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f.", +"message.installwizard.copy.whatiscloudstack": "CloudStack™ - \u044d\u0442\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u0430\u044f \u043f\u043b\u0430\u0444\u0442\u043e\u0440\u043c\u0430 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445, \u0447\u0430\u0441\u0442\u043d\u044b\u0445 \u0438 \u0433\u0438\u0431\u0440\u0438\u0434\u043d\u044b\u0445 \u043e\u0431\u043b\u0430\u043a\u043e\u0432 \u043f\u043e \u0441\u0445\u0435\u043c\u0435 \u00ab\u0418\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043a\u0430\u043a \u0441\u0435\u0440\u0432\u0438\u0441\u00bb (IaaS). CloudStack™ \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u0435\u0442\u044c\u044e, \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c \u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0443\u0437\u043b\u0430\u043c\u0438, \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0432 \u043e\u0431\u043b\u0430\u0447\u043d\u0443\u044e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443. \u0413\u043b\u0430\u0432\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, CloudStack™ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439.

CloudStack™ \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0438 \u0446\u0435\u043b\u043e\u0433\u043e \u0446\u0435\u043d\u0442\u0440\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043e\u0431\u043b\u0430\u043a\u0430.", "message.installwizard.tooltip.addpod.name": "\u0418\u043c\u044f \u0441\u0442\u0435\u043d\u0434\u0430", "message.installwizard.tooltip.addpod.reservedsystemendip": "\u042d\u0442\u043e \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d IP \u0447\u0430\u0441\u0442\u043d\u043e\u0439 \u0441\u0435\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f CloudStack \u0434\u043b\u044f \u0412\u041c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0438 \u043a\u043e\u043d\u0441\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u043a\u0441\u0438. \u042d\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442\u0441\u044f \u0438\u0437 \u0441\u0435\u0442\u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "\u0428\u043b\u044e\u0437 \u0434\u043b\u044f \u0443\u0437\u043b\u043e\u0432 \u044d\u0442\u043e\u0433\u043e \u0441\u0442\u0435\u043d\u0434\u0430.", diff --git a/ui/public/locales/zh_CN.json b/ui/public/locales/zh_CN.json index 91353d2f81a..5d46d0cc840 100644 --- a/ui/public/locales/zh_CN.json +++ b/ui/public/locales/zh_CN.json @@ -3499,7 +3499,7 @@ "message.installwizard.copy.whatisahost": "\u4E3B\u673A\u662F\u6307\u4E00\u53F0\u8BA1\u7B97\u673A\u3002\u4E3B\u673A\u63D0\u4F9B\u8FD0\u884C\u6765\u5BBE\u865A\u62DF\u673A\u7684\u8BA1\u7B97\u8D44\u6E90\u3002\u6BCF\u53F0\u4E3B\u673A\u4E0A\u90FD\u5B89\u88C5\u6709\u865A\u62DF\u673A\u7BA1\u7406\u7A0B\u5E8F\u8F6F\u4EF6\uFF0C\u7528\u4E8E\u7BA1\u7406\u6765\u5BBE\u865A\u62DF\u673A\uFF08\u88F8\u673A\u4E3B\u673A\u9664\u5916\uFF0C\u5C06\u5728\u201C\u9AD8\u7EA7\u5B89\u88C5\u6307\u5357\u201D\u4E2D\u8BA8\u8BBA\u8FD9\u4E00\u7279\u6B8A\u6848\u4F8B\uFF09\u3002\u4F8B\u5982\uFF0C\u542F\u7528\u4E86 KVM \u7684 Linux \u670D\u52A1\u5668\u3001Citrix XenServer \u670D\u52A1\u5668\u548C ESXi \u670D\u52A1\u5668\u90FD\u53EF\u7528\u4F5C\u4E3B\u673A\u3002\u5728\u57FA\u672C\u5B89\u88C5\u4E2D\uFF0C\u6211\u4EEC\u5C06\u4F7F\u7528\u4E00\u53F0\u8FD0\u884C XenServer \u7684\u4E3B\u673A\u3002

\u4E3B\u673A\u662F CloudStack\u2122 \u90E8\u7F72\u4E2D\u6700\u5C0F\u7684\u7EC4\u7EC7\u5355\u4F4D\u3002\u4E3B\u673A\u5305\u542B\u5728\u96C6\u7FA4\u4E2D\uFF0C\u96C6\u7FA4\u5305\u542B\u5728\u63D0\u4F9B\u70B9\u4E2D\uFF0C\u63D0\u4F9B\u70B9\u5305\u542B\u5728\u8D44\u6E90\u57DF\u4E2D\u3002", "message.installwizard.copy.whatisapod": "\u4E00\u4E2A\u63D0\u4F9B\u70B9\u901A\u5E38\u4EE3\u8868\u4E00\u4E2A\u673A\u67B6\u3002\u540C\u4E00\u63D0\u4F9B\u70B9\u4E2D\u7684\u4E3B\u673A\u4F4D\u4E8E\u540C\u4E00\u5B50\u7F51\u4E2D\u3002

\u63D0\u4F9B\u70B9\u662F CloudStack\u2122 \u90E8\u7F72\u4E2D\u7684\u7B2C\u4E8C\u5927\u7EC4\u7EC7\u5355\u4F4D\u3002\u63D0\u4F9B\u70B9\u5305\u542B\u5728\u8D44\u6E90\u57DF\u4E2D\u3002\u6BCF\u4E2A\u8D44\u6E90\u57DF\u4E2D\u53EF\u4EE5\u5305\u542B\u4E00\u4E2A\u6216\u591A\u4E2A\u63D0\u4F9B\u70B9\uFF1B\u5728\u57FA\u672C\u5B89\u88C5\u4E2D\uFF0C\u60A8\u7684\u8D44\u6E90\u57DF\u4E2D\u5C06\u4EC5\u5305\u542B\u4E00\u4E2A\u63D0\u4F9B\u70B9\u3002", "message.installwizard.copy.whatisazone": "\u8D44\u6E90\u57DF\u662F CloudStack\u2122 \u90E8\u7F72\u4E2D\u6700\u5927\u7684\u7EC4\u7EC7\u5355\u4F4D\u3002\u867D\u7136\u5141\u8BB8\u4E00\u4E2A\u6570\u636E\u4E2D\u5FC3\u4E2D\u5B58\u5728\u591A\u4E2A\u8D44\u6E90\u57DF\uFF0C\u4F46\u662F\u4E00\u4E2A\u8D44\u6E90\u57DF\u901A\u5E38\u4E0E\u4E00\u4E2A\u6570\u636E\u4E2D\u5FC3\u76F8\u5BF9\u5E94\u3002\u5C06\u57FA\u7840\u67B6\u6784\u7F16\u7EC4\u5230\u8D44\u6E90\u57DF\u4E2D\u7684\u597D\u5904\u662F\u53EF\u4EE5\u63D0\u4F9B\u7269\u7406\u9694\u79BB\u548C\u5197\u4F59\u3002\u4F8B\u5982\uFF0C\u6BCF\u4E2A\u8D44\u6E90\u57DF\u90FD\u53EF\u4EE5\u62E5\u6709\u5404\u81EA\u7684\u7535\u6E90\u4F9B\u5E94\u548C\u7F51\u7EDC\u4E0A\u884C\u65B9\u6848\uFF0C\u5E76\u4E14\u5404\u8D44\u6E90\u57DF\u53EF\u4EE5\u5728\u5730\u7406\u4F4D\u7F6E\u4E0A\u76F8\u9694\u5F88\u8FDC\uFF08\u867D\u7136\u5E76\u975E\u5FC5\u987B\u76F8\u9694\u5F88\u8FDC\uFF09\u3002", - "message.installwizard.copy.whatiscloudstack": "CloudStack\u2122 \u662F\u4E00\u4E2A\u8F6F\u4EF6\u5E73\u53F0\uFF0C\u53EF\u5C06\u8BA1\u7B97\u8D44\u6E90\u96C6\u4E2D\u5728\u4E00\u8D77\u4EE5\u6784\u5EFA\u516C\u6709\u3001\u79C1\u6709\u548C\u6DF7\u5408\u57FA\u7840\u8BBE\u65BD\u5373\u670D\u52A1\uFF08IaaS\uFF09\u4E91\u3002 CloudStack\u2122 \u8D1F\u8D23\u7BA1\u7406\u7EC4\u6210\u4E91\u57FA\u7840\u67B6\u6784\u7684\u7F51\u7EDC\u3001\u5B58\u50A8\u548C\u8BA1\u7B97\u8282\u70B9\u3002\u4F7F\u7528 CloudStack\u2122 \u53EF\u4EE5\u90E8\u7F72\u3001\u7BA1\u7406\u548C\u914D\u7F6E\u4E91\u8BA1\u7B97\u73AF\u5883\u3002

CloudStack\u2122 \u901A\u8FC7\u6269\u5C55\u5546\u7528\u786C\u4EF6\u4E0A\u8FD0\u884C\u7684\u6BCF\u4E2A\u865A\u62DF\u673A\u6620\u50CF\u7684\u8303\u56F4\uFF0C\u63D0\u4F9B\u4E86\u4E00\u4E2A\u5B9E\u65F6\u53EF\u7528\u7684\u4E91\u57FA\u7840\u67B6\u6784\u8F6F\u4EF6\u5806\u6808\u7528\u4E8E\u4EE5\u670D\u52A1\u65B9\u5F0F\u4EA4\u4ED8\u865A\u62DF\u6570\u636E\u4E2D\u5FC3\uFF0C\u5373\u4EA4\u4ED8\u6784\u5EFA\u3001\u90E8\u7F72\u548C\u7BA1\u7406\u591A\u5C42\u6B21\u548C\u591A\u79DF\u6237\u4E91\u5E94\u7528\u7A0B\u5E8F\u5FC5\u9700\u7684\u6240\u6709\u7EC4\u4EF6\u3002\u5F00\u6E90\u7248\u672C\u548C Premium \u7248\u672C\u90FD\u5DF2\u53EF\u7528\uFF0C\u4E14\u63D0\u4F9B\u7684\u529F\u80FD\u51E0\u4E4E\u5B8C\u5168\u76F8\u540C\u3002", + "message.installwizard.copy.whatiscloudstack": "CloudStack\u2122 \u662F\u4E00\u4E2A\u8F6F\u4EF6\u5E73\u53F0\uFF0C\u53EF\u5C06\u8BA1\u7B97\u8D44\u6E90\u96C6\u4E2D\u5728\u4E00\u8D77\u4EE5\u6784\u5EFA\u516C\u6709\u3001\u79C1\u6709\u548C\u6DF7\u5408\u57FA\u7840\u8BBE\u65BD\u5373\u670D\u52A1\uFF08IaaS\uFF09\u4E91\u3002 CloudStack\u2122 \u8D1F\u8D23\u7BA1\u7406\u7EC4\u6210\u4E91\u57FA\u7840\u67B6\u6784\u7684\u7F51\u7EDC\u3001\u5B58\u50A8\u548C\u8BA1\u7B97\u8282\u70B9\u3002\u4F7F\u7528 CloudStack\u2122 \u53EF\u4EE5\u90E8\u7F72\u3001\u7BA1\u7406\u548C\u914D\u7F6E\u4E91\u8BA1\u7B97\u73AF\u5883\u3002

CloudStack\u2122 \u901A\u8FC7\u6269\u5C55\u5546\u7528\u786C\u4EF6\u4E0A\u8FD0\u884C\u7684\u6BCF\u4E2A\u865A\u62DF\u673A\u6620\u50CF\u7684\u8303\u56F4\uFF0C\u63D0\u4F9B\u4E86\u4E00\u4E2A\u5B9E\u65F6\u53EF\u7528\u7684\u4E91\u57FA\u7840\u67B6\u6784\u8F6F\u4EF6\u5806\u6808\u7528\u4E8E\u4EE5\u670D\u52A1\u65B9\u5F0F\u4EA4\u4ED8\u865A\u62DF\u6570\u636E\u4E2D\u5FC3\uFF0C\u5373\u4EA4\u4ED8\u6784\u5EFA\u3001\u90E8\u7F72\u548C\u7BA1\u7406\u591A\u5C42\u6B21\u548C\u591A\u79DF\u6237\u4E91\u5E94\u7528\u7A0B\u5E8F\u5FC5\u9700\u7684\u6240\u6709\u7EC4\u4EF6\u3002", "message.installwizard.copy.whatisprimarystorage": "CloudStack\u2122 \u4E91\u57FA\u7840\u67B6\u6784\u4F7F\u7528\u4EE5\u4E0B\u4E24\u79CD\u7C7B\u578B\u7684\u5B58\u50A8: \u4E3B\u5B58\u50A8\u548C\u4E8C\u7EA7\u5B58\u50A8\u3002\u8FD9\u4E24\u79CD\u7C7B\u578B\u7684\u5B58\u50A8\u53EF\u4EE5\u662F iSCSI \u6216 NFS \u670D\u52A1\u5668\uFF0C\u4E5F\u53EF\u4EE5\u662F\u672C\u5730\u78C1\u76D8\u3002

\u4E3B\u5B58\u50A8\u4E0E\u96C6\u7FA4\u76F8\u5173\u8054\uFF0C\u7528\u4E8E\u5B58\u50A8\u8BE5\u96C6\u7FA4\u4E2D\u7684\u4E3B\u673A\u4E0A\u6B63\u5728\u8FD0\u884C\u7684\u6240\u6709\u865A\u62DF\u673A\u5BF9\u5E94\u7684\u6BCF\u4E2A\u6765\u5BBE\u865A\u62DF\u673A\u7684\u78C1\u76D8\u5377\u3002\u4E3B\u5B58\u50A8\u670D\u52A1\u5668\u901A\u5E38\u4F4D\u4E8E\u9760\u8FD1\u4E3B\u673A\u7684\u4F4D\u7F6E\u3002", "message.installwizard.copy.whatissecondarystorage": "\u4E8C\u7EA7\u5B58\u50A8\u4E0E\u8D44\u6E90\u57DF\u76F8\u5173\u8054\uFF0C\u7528\u4E8E\u5B58\u50A8\u4EE5\u4E0B\u9879\u76EE:
  • \u6A21\u677F - \u53EF\u7528\u4E8E\u542F\u52A8\u865A\u62DF\u673A\u5E76\u53EF\u4EE5\u5305\u542B\u5176\u4ED6\u914D\u7F6E\u4FE1\u606F\uFF08\u4F8B\u5982\uFF0C\u5DF2\u5B89\u88C5\u7684\u5E94\u7528\u7A0B\u5E8F\uFF09\u7684\u64CD\u4F5C\u7CFB\u7EDF\u6620\u50CF
  • ISO \u6620\u50CF - \u53EF\u91CD\u65B0\u542F\u52A8\u6216\u4E0D\u53EF\u91CD\u65B0\u542F\u52A8\u7684\u64CD\u4F5C\u7CFB\u7EDF\u6620\u50CF
  • \u78C1\u76D8\u5377\u5FEB\u7167 - \u5DF2\u4FDD\u5B58\u7684\u865A\u62DF\u673A\u6570\u636E\u526F\u672C\uFF0C\u53EF\u7528\u4E8E\u6267\u884C\u6570\u636E\u6062\u590D\u6216\u521B\u5EFA\u65B0\u6A21\u677F
", "message.installwizard.now.building": "\u73B0\u5728\u6B63\u5728\u6784\u5EFA\u60A8\u7684\u4E91...", From 212f2a3898c46a09b2515c954af8d61d995bcf56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernardo=20De=20Marco=20Gon=C3=A7alves?= Date: Mon, 17 Feb 2025 05:19:21 -0300 Subject: [PATCH 10/21] UI: Fix `docHelp` links for Add Hosts, Add Clusters, Disable Clusters and Enable Clusters forms (#10394) --- ui/src/config/section/infra/clusters.js | 6 +++--- ui/src/config/section/infra/hosts.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/src/config/section/infra/clusters.js b/ui/src/config/section/infra/clusters.js index 8b2f37d5b7b..a3dda2d760c 100644 --- a/ui/src/config/section/infra/clusters.js +++ b/ui/src/config/section/infra/clusters.js @@ -73,7 +73,7 @@ export default { api: 'addCluster', icon: 'plus-outlined', label: 'label.add.cluster', - docHelp: 'adminguide/installguide/configuration.html#adding-a-cluster', + docHelp: 'installguide/configuration.html#adding-a-cluster', listView: true, popup: true, component: shallowRef(defineAsyncComponent(() => import('@/views/infra/ClusterAdd.vue'))) @@ -90,7 +90,7 @@ export default { icon: 'play-circle-outlined', label: 'label.action.enable.cluster', message: 'message.action.enable.cluster', - docHelp: 'adminguide/installguide/hosts.html#disabling-and-enabling-zones-pods-and-clusters', + docHelp: 'adminguide/hosts.html#disabling-and-enabling-zones-pods-and-clusters', dataView: true, defaultArgs: { allocationstate: 'Enabled' }, show: (record) => { return record.allocationstate === 'Disabled' } @@ -100,7 +100,7 @@ export default { icon: 'pause-circle-outlined', label: 'label.action.disable.cluster', message: 'message.action.disable.cluster', - docHelp: 'adminguide/installguide/hosts.html#disabling-and-enabling-zones-pods-and-clusters', + docHelp: 'adminguide/hosts.html#disabling-and-enabling-zones-pods-and-clusters', dataView: true, defaultArgs: { allocationstate: 'Disabled' }, show: (record) => { return record.allocationstate === 'Enabled' } diff --git a/ui/src/config/section/infra/hosts.js b/ui/src/config/section/infra/hosts.js index de42762c274..f13029b61ca 100644 --- a/ui/src/config/section/infra/hosts.js +++ b/ui/src/config/section/infra/hosts.js @@ -64,7 +64,7 @@ export default { api: 'addHost', icon: 'plus-outlined', label: 'label.add.host', - docHelp: 'adminguide/installguide/configuration.html#adding-a-host', + docHelp: 'installguide/configuration.html#adding-a-host', listView: true, popup: true, component: shallowRef(defineAsyncComponent(() => import('@/views/infra/HostAdd.vue'))) From b6cebe22f9ee5e07e16bf4213336be650b8ad48f Mon Sep 17 00:00:00 2001 From: Suresh Kumar Anaparti Date: Tue, 18 Feb 2025 13:17:05 +0530 Subject: [PATCH 11/21] Fixed VMware import issue - check and update pools in the order of the disks (do not update by position) (#10409) --- .../com/cloud/storage/VolumeApiService.java | 6 +- .../cloud/storage/VolumeApiServiceImpl.java | 20 ++-- .../VolumeImportUnmanageManagerImpl.java | 2 +- .../vm/UnmanagedVMsManagerImpl.java | 102 +++++++++--------- .../storage/VolumeApiServiceImplTest.java | 20 ++-- .../VolumeImportUnmanageManagerImplTest.java | 2 +- .../vm/UnmanagedVMsManagerImplTest.java | 6 +- 7 files changed, 77 insertions(+), 81 deletions(-) diff --git a/api/src/main/java/com/cloud/storage/VolumeApiService.java b/api/src/main/java/com/cloud/storage/VolumeApiService.java index 4f09702b7db..833ba442888 100644 --- a/api/src/main/java/com/cloud/storage/VolumeApiService.java +++ b/api/src/main/java/com/cloud/storage/VolumeApiService.java @@ -133,13 +133,13 @@ public interface VolumeApiService { Snapshot allocSnapshotForVm(Long vmId, Long volumeId, String snapshotName) throws ResourceAllocationException; /** - * Checks if the target storage supports the disk offering. + * Checks if the storage pool supports the disk offering tags. * This validation is consistent with the mechanism used to select a storage pool to deploy a volume when a virtual machine is deployed or when a data disk is allocated. * * The scenarios when this method returns true or false is presented in the following table. * * - * + * * * * @@ -163,7 +163,7 @@ public interface VolumeApiService { * *
#Disk offering tagsStorage tagsDoes the storage support the disk offering?#Disk offering diskOfferingTagsStorage diskOfferingTagsDoes the storage support the disk offering?
*/ - boolean doesTargetStorageSupportDiskOffering(StoragePool destPool, String diskOfferingTags); + boolean doesStoragePoolSupportDiskOfferingTags(StoragePool destPool, String diskOfferingTags); Volume destroyVolume(long volumeId, Account caller, boolean expunge, boolean forceExpunge); diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java index 3ea8116764a..e2babeacc71 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -3519,7 +3519,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic if ((destPool.isShared() && newDiskOffering.isUseLocalStorage()) || destPool.isLocal() && newDiskOffering.isShared()) { throw new InvalidParameterValueException("You cannot move the volume to a shared storage and assign a disk offering for local storage and vice versa."); } - if (!doesTargetStorageSupportDiskOffering(destPool, newDiskOffering)) { + if (!doesStoragePoolSupportDiskOffering(destPool, newDiskOffering)) { throw new InvalidParameterValueException(String.format("Migration failed: target pool [%s, tags:%s] has no matching tags for volume [%s, uuid:%s, tags:%s]", destPool.getName(), storagePoolTagsDao.getStoragePoolTags(destPool.getId()), volume.getName(), volume.getUuid(), newDiskOffering.getTags())); } @@ -3546,7 +3546,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } /** - * Checks if the target storage supports the new disk offering. + * Checks if the storage pool supports the new disk offering. * This validation is consistent with the mechanism used to select a storage pool to deploy a volume when a virtual machine is deployed or when a new data disk is allocated. * * The scenarios when this method returns true or false is presented in the following table. @@ -3577,9 +3577,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic * * */ - protected boolean doesTargetStorageSupportDiskOffering(StoragePool destPool, DiskOfferingVO diskOffering) { - String targetStoreTags = diskOffering.getTags(); - return doesTargetStorageSupportDiskOffering(destPool, targetStoreTags); + protected boolean doesStoragePoolSupportDiskOffering(StoragePool destPool, DiskOfferingVO diskOffering) { + String offeringTags = diskOffering.getTags(); + return doesStoragePoolSupportDiskOfferingTags(destPool, offeringTags); } public static boolean doesNewDiskOfferingHasTagsAsOldDiskOffering(DiskOfferingVO oldDO, DiskOfferingVO newDO) { @@ -3595,18 +3595,18 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } @Override - public boolean doesTargetStorageSupportDiskOffering(StoragePool destPool, String diskOfferingTags) { + public boolean doesStoragePoolSupportDiskOfferingTags(StoragePool destPool, String diskOfferingTags) { Pair, Boolean> storagePoolTags = getStoragePoolTags(destPool); if ((storagePoolTags == null || !storagePoolTags.second()) && org.apache.commons.lang.StringUtils.isBlank(diskOfferingTags)) { if (storagePoolTags == null) { - s_logger.debug(String.format("Destination storage pool [%s] does not have any tags, and so does the disk offering. Therefore, they are compatible", destPool.getUuid())); + s_logger.debug(String.format("Storage pool [%s] does not have any tags, and so does the disk offering. Therefore, they are compatible", destPool.getUuid())); } else { - s_logger.debug("Destination storage pool has tags [%s], and the disk offering has no tags. Therefore, they are compatible."); + s_logger.debug("Storage pool has tags [%s], and the disk offering has no tags. Therefore, they are compatible."); } return true; } if (storagePoolTags == null || CollectionUtils.isEmpty(storagePoolTags.first())) { - s_logger.debug(String.format("Destination storage pool [%s] has no tags, while disk offering has tags [%s]. Therefore, they are not compatible", destPool.getUuid(), + s_logger.debug(String.format("Storage pool [%s] has no tags, while disk offering has tags [%s]. Therefore, they are not compatible", destPool.getUuid(), diskOfferingTags)); return false; } @@ -3619,7 +3619,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } else { result = CollectionUtils.isSubCollection(Arrays.asList(newDiskOfferingTagsAsStringArray), storageTagsList); } - s_logger.debug(String.format("Destination storage pool [%s] accepts tags [%s]? %s", destPool.getUuid(), diskOfferingTags, result)); + s_logger.debug(String.format("Storage pool [%s] accepts tags [%s]? %s", destPool.getUuid(), diskOfferingTags, result)); return result; } diff --git a/server/src/main/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImpl.java b/server/src/main/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImpl.java index b3b164395f6..e48a6d413ad 100644 --- a/server/src/main/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImpl.java @@ -205,7 +205,7 @@ public class VolumeImportUnmanageManagerImpl implements VolumeImportUnmanageServ if (diskOffering.isCustomized()) { volumeApiService.validateCustomDiskOfferingSizeRange(volume.getVirtualSize() / ByteScaleUtils.GiB); } - if (!volumeApiService.doesTargetStorageSupportDiskOffering(pool, diskOffering.getTags())) { + if (!volumeApiService.doesStoragePoolSupportDiskOfferingTags(pool, diskOffering.getTags())) { logFailureAndThrowException(String.format("Disk offering: %s storage tags are not compatible with selected storage pool: %s", diskOffering.getUuid(), pool.getUuid())); } diff --git a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java index 187afece84f..f70a26f33c7 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java @@ -456,7 +456,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { if (diskOffering == null) { return false; } - return volumeApiService.doesTargetStorageSupportDiskOffering(pool, diskOffering.getTags()); + return volumeApiService.doesStoragePoolSupportDiskOfferingTags(pool, diskOffering.getTags()); } private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedInstanceTO instance, ServiceOfferingVO serviceOffering, final Account owner, final DataCenter zone, final Map details, Hypervisor.HypervisorType hypervisorType) @@ -547,7 +547,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { for (StoragePool pool : pools) { if (pool.getDataCenterId() == zone.getId() && (pool.getClusterId() == null || pool.getClusterId().equals(cluster.getId())) && - volumeApiService.doesTargetStorageSupportDiskOffering(pool, diskOfferingTags)) { + volumeApiService.doesStoragePoolSupportDiskOfferingTags(pool, diskOfferingTags)) { storagePool = pool; break; } @@ -560,7 +560,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { for (StoragePool pool : pools) { String searchPoolParam = StringUtils.isNotBlank(dsPath) ? dsPath : dsName; if (StringUtils.contains(pool.getPath(), searchPoolParam) && - volumeApiService.doesTargetStorageSupportDiskOffering(pool, diskOfferingTags)) { + volumeApiService.doesStoragePoolSupportDiskOfferingTags(pool, diskOfferingTags)) { storagePool = pool; break; } @@ -1732,9 +1732,9 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { convertedInstance.setPowerState(UnmanagedInstanceTO.PowerState.PowerOff); List convertedInstanceDisks = convertedInstance.getDisks(); List sourceVMwareInstanceDisks = sourceVMwareInstance.getDisks(); - for (UnmanagedInstanceTO.Disk sourceVMwareInstanceDisk : sourceVMwareInstanceDisks) { - UnmanagedInstanceTO.Disk convertedDisk = convertedInstanceDisks.get(sourceVMwareInstanceDisk.getPosition()); - convertedDisk.setDiskId(sourceVMwareInstanceDisk.getDiskId()); + for (int i = 0; i < convertedInstanceDisks.size(); i++) { + UnmanagedInstanceTO.Disk disk = convertedInstanceDisks.get(i); + disk.setDiskId(sourceVMwareInstanceDisks.get(i).getDiskId()); } List convertedInstanceNics = convertedInstance.getNics(); List sourceVMwareInstanceNics = sourceVMwareInstance.getNics(); @@ -2018,7 +2018,25 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { List pools = new ArrayList<>(); pools.addAll(primaryDataStoreDao.findClusterWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)); pools.addAll(primaryDataStoreDao.findZoneWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getDataCenterId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)); - List diskOfferingTags = new ArrayList<>(); + if (pools.isEmpty()) { + String msg = String.format("Cannot find suitable storage pools in the cluster %s for the conversion", destinationCluster.getName()); + LOGGER.error(msg); + throw new CloudRuntimeException(msg); + } + + if (serviceOffering.getDiskOfferingId() != null) { + DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); + if (diskOffering == null) { + String msg = String.format("Cannot find disk offering with ID %s that belongs to the service offering %s", serviceOffering.getDiskOfferingId(), serviceOffering.getName()); + LOGGER.error(msg); + throw new CloudRuntimeException(msg); + } + if (getStoragePoolWithTags(pools, diskOffering.getTags()) == null) { + String msg = String.format("Cannot find suitable storage pool for disk offering %s that belongs to the service offering %s", diskOffering.getName(), serviceOffering.getName()); + LOGGER.error(msg); + throw new CloudRuntimeException(msg); + } + } for (Long diskOfferingId : dataDiskOfferingMap.values()) { DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId); if (diskOffering == null) { @@ -2026,44 +2044,26 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { LOGGER.error(msg); throw new CloudRuntimeException(msg); } - diskOfferingTags.add(diskOffering.getTags()); - } - if (serviceOffering.getDiskOfferingId() != null) { - DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); - if (diskOffering != null) { - diskOfferingTags.add(diskOffering.getTags()); - } - } - - pools = getPoolsWithMatchingTags(pools, diskOfferingTags); - if (pools.isEmpty()) { - String msg = String.format("Cannot find suitable storage pools in cluster %s for the conversion", destinationCluster.getName()); - LOGGER.error(msg); - throw new CloudRuntimeException(msg); - } - return pools; - } - - private List getPoolsWithMatchingTags(List pools, List diskOfferingTags) { - if (diskOfferingTags.isEmpty()) { - return pools; - } - List poolsSupportingTags = new ArrayList<>(pools); - for (String tags : diskOfferingTags) { - boolean tagsMatched = false; - for (StoragePoolVO pool : pools) { - if (volumeApiService.doesTargetStorageSupportDiskOffering(pool, tags)) { - poolsSupportingTags.add(pool); - tagsMatched = true; - } - } - if (!tagsMatched) { - String msg = String.format("Cannot find suitable storage pools for the conversion with disk offering tags %s", tags); + if (getStoragePoolWithTags(pools, diskOffering.getTags()) == null) { + String msg = String.format("Cannot find suitable storage pool for disk offering %s", diskOffering.getName()); LOGGER.error(msg); throw new CloudRuntimeException(msg); } } - return poolsSupportingTags; + + return pools; + } + + private StoragePoolVO getStoragePoolWithTags(List pools, String tags) { + if (StringUtils.isEmpty(tags)) { + return pools.get(0); + } + for (StoragePoolVO pool : pools) { + if (volumeApiService.doesStoragePoolSupportDiskOfferingTags(pool, tags)) { + return pool; + } + } + return null; } private List selectInstanceConversionStoragePools( @@ -2071,26 +2071,22 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap ) { List storagePools = new ArrayList<>(disks.size()); - for (int i = 0; i < disks.size(); i++) { - storagePools.add(null); - } Set dataDiskIds = dataDiskOfferingMap.keySet(); for (UnmanagedInstanceTO.Disk disk : disks) { - Long diskOfferingId = dataDiskOfferingMap.get(disk.getDiskId()); - if (diskOfferingId == null && !dataDiskIds.contains(disk.getDiskId())) { + Long diskOfferingId = null; + if (dataDiskIds.contains(disk.getDiskId())) { + diskOfferingId = dataDiskOfferingMap.get(disk.getDiskId()); + } else { diskOfferingId = serviceOffering.getDiskOfferingId(); } + //TODO: Choose pools by capacity if (diskOfferingId == null) { - storagePools.set(disk.getPosition(), pools.get(0).getUuid()); + storagePools.add(pools.get(0).getUuid()); } else { DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId); - for (StoragePoolVO pool : pools) { - if (volumeApiService.doesTargetStorageSupportDiskOffering(pool, diskOffering.getTags())) { - storagePools.set(disk.getPosition(), pool.getUuid()); - break; - } - } + StoragePoolVO pool = getStoragePoolWithTags(pools, diskOffering.getTags()); + storagePools.add(pool.getUuid()); } } return storagePools; diff --git a/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java b/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java index 9b087bd384b..db74a004580 100644 --- a/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java +++ b/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java @@ -1164,7 +1164,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.doReturn(new Pair<>(List.of("A"), false)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertFalse(result); } @@ -1177,7 +1177,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.doReturn(new Pair<>(List.of("A","B","C","D","X","Y"), false)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertTrue(result); } @@ -1190,7 +1190,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.lenient().doReturn(new Pair<>(List.of("A,B,C,D,X,Y"), false)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertTrue(result); } @@ -1203,7 +1203,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.doReturn(new Pair<>(List.of(""), false)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertFalse(result); } @@ -1216,7 +1216,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.lenient().doReturn(new Pair<>(List.of(""), false)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertTrue(result); } @@ -1229,7 +1229,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.doReturn(new Pair<>(List.of("C,D"), false)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertFalse(result); } @@ -1242,7 +1242,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.doReturn(new Pair<>(List.of("A"), false)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertTrue(result); } @@ -1255,7 +1255,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.doReturn(new Pair<>(List.of("tags[0] == 'A'"), true)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertTrue(result); } @@ -1268,7 +1268,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.doReturn(new Pair<>(List.of("tags[0] == 'A'"), true)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertFalse(result); } @@ -1281,7 +1281,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.doReturn(new Pair<>(List.of("tags[0] == 'A'"), true)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertFalse(result); } diff --git a/server/src/test/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImplTest.java index dab46595438..aed8f6a291b 100644 --- a/server/src/test/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImplTest.java @@ -275,7 +275,7 @@ public class VolumeImportUnmanageManagerImplTest { when(diskOffering.isCustomized()).thenReturn(true); doReturn(diskOffering).when(volumeImportUnmanageManager).getOrCreateDiskOffering(account, diskOfferingId, zoneId, isLocal); doNothing().when(volumeApiService).validateCustomDiskOfferingSizeRange(anyLong()); - doReturn(true).when(volumeApiService).doesTargetStorageSupportDiskOffering(any(), isNull()); + doReturn(true).when(volumeApiService).doesStoragePoolSupportDiskOfferingTags(any(), isNull()); doReturn(diskProfile).when(volumeManager).importVolume(any(), anyString(), any(), eq(virtualSize), isNull(), isNull(), anyLong(), any(), isNull(), isNull(), any(), isNull(), anyLong(), anyString(), isNull()); when(diskProfile.getVolumeId()).thenReturn(volumeId); diff --git a/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java index 85402c0e254..9bdc05fe95c 100644 --- a/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java @@ -424,7 +424,7 @@ public class UnmanagedVMsManagerImplTest { ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class); when(importUnmanageInstanceCmd.getName()).thenReturn("TestInstance"); when(importUnmanageInstanceCmd.getDomainId()).thenReturn(null); - when(volumeApiService.doesTargetStorageSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true); + when(volumeApiService.doesStoragePoolSupportDiskOfferingTags(any(StoragePool.class), any())).thenReturn(true); try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class)) { unmanagedVMsManager.importUnmanagedInstance(importUnmanageInstanceCmd); } @@ -704,7 +704,7 @@ public class UnmanagedVMsManagerImplTest { when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(CheckConvertInstanceCommand.class))).thenReturn(checkConvertInstanceAnswer); } - when(volumeApiService.doesTargetStorageSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true); + when(volumeApiService.doesStoragePoolSupportDiskOfferingTags(any(StoragePool.class), any())).thenReturn(true); ConvertInstanceAnswer convertInstanceAnswer = mock(ConvertInstanceAnswer.class); ImportConvertedInstanceAnswer convertImportedInstanceAnswer = mock(ImportConvertedInstanceAnswer.class); @@ -769,7 +769,7 @@ public class UnmanagedVMsManagerImplTest { storagePools.add(storagePool); when(primaryDataStoreDao.findLocalStoragePoolsByHostAndTags(anyLong(), any())).thenReturn(storagePools); when(primaryDataStoreDao.findById(anyLong())).thenReturn(storagePool); - when(volumeApiService.doesTargetStorageSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true); + when(volumeApiService.doesStoragePoolSupportDiskOfferingTags(any(StoragePool.class), any())).thenReturn(true); StoragePoolHostVO storagePoolHost = Mockito.mock(StoragePoolHostVO.class); when(storagePoolHostDao.findByPoolHost(anyLong(), anyLong())).thenReturn(storagePoolHost); try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class)) { From b9ebc7b721b9dc187c38e3c97a3d43a12de09e12 Mon Sep 17 00:00:00 2001 From: Suresh Kumar Anaparti Date: Tue, 18 Feb 2025 13:53:25 +0530 Subject: [PATCH 12/21] VMware Import - Support external VMs in any folders/subfolders other than the root folder ('vm') of datacenter (#10411) --- .../cloud/agent/api/to/RemoteInstanceTO.java | 8 ++++++- .../cloudstack/vm/UnmanagedInstanceTO.java | 10 +++++++++ .../LibvirtConvertInstanceCommandWrapper.java | 7 +++++++ .../vm/UnmanagedVMsManagerImpl.java | 2 +- .../vmware/mo/VirtualMachineMO.java | 21 +++++++++++++++++++ .../hypervisor/vmware/util/VmwareHelper.java | 1 + 6 files changed, 47 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java b/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java index d86eb2a3a7f..18737c584b3 100644 --- a/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java +++ b/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java @@ -27,6 +27,7 @@ public class RemoteInstanceTO implements Serializable { private Hypervisor.HypervisorType hypervisorType; private String instanceName; + private String instancePath; // VMware Remote Instances parameters (required for exporting OVA through ovftool) // TODO: cloud.agent.transport.Request#getCommands() cannot handle gsoc decode for polymorphic classes @@ -44,9 +45,10 @@ public class RemoteInstanceTO implements Serializable { this.instanceName = instanceName; } - public RemoteInstanceTO(String instanceName, String vcenterHost, String vcenterUsername, String vcenterPassword, String datacenterName) { + public RemoteInstanceTO(String instanceName, String instancePath, String vcenterHost, String vcenterUsername, String vcenterPassword, String datacenterName) { this.hypervisorType = Hypervisor.HypervisorType.VMware; this.instanceName = instanceName; + this.instancePath = instancePath; this.vcenterHost = vcenterHost; this.vcenterUsername = vcenterUsername; this.vcenterPassword = vcenterPassword; @@ -61,6 +63,10 @@ public class RemoteInstanceTO implements Serializable { return this.instanceName; } + public String getInstancePath() { + return this.instancePath; + } + public String getVcenterUsername() { return vcenterUsername; } diff --git a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java index 5697a040b81..6f632853527 100644 --- a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java +++ b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java @@ -33,6 +33,8 @@ public class UnmanagedInstanceTO { private String internalCSName; + private String path; + private PowerState powerState; private PowerState cloneSourcePowerState; @@ -75,6 +77,14 @@ public class UnmanagedInstanceTO { this.internalCSName = internalCSName; } + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + public PowerState getPowerState() { return powerState; } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapper.java index e6654b1ffc5..504edb9d888 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapper.java @@ -57,6 +57,7 @@ public class LibvirtConvertInstanceCommandWrapper extends CommandWrapper destinationStoragePools = selectInstanceConversionStoragePools(convertStoragePools, sourceVMwareInstance.getDisks(), serviceOffering, dataDiskOfferingMap); ConvertInstanceCommand cmd = new ConvertInstanceCommand(remoteInstanceTO, Hypervisor.HypervisorType.KVM, temporaryConvertLocation, null, false, true); diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java index 20c62c30c0b..1e824f34fbb 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java @@ -891,6 +891,27 @@ public class VirtualMachineMO extends BaseMO { return fileLayout; } + public String getPath() throws Exception { + List subPaths = new ArrayList<>(); + ManagedObjectReference mor = _context.getVimClient().getDynamicProperty(_mor, "parent"); + while (mor != null && mor.getType().equalsIgnoreCase("Folder")) { + String subPath = _context.getVimClient().getDynamicProperty(mor, "name"); + if (StringUtils.isBlank(subPath)) { + return null; + } + subPaths.add(subPath); + mor = _context.getVimClient().getDynamicProperty(mor, "parent"); + } + + if (!subPaths.isEmpty()) { + Collections.reverse(subPaths); + String path = StringUtils.join(subPaths, "/"); + return path; + } + + return null; + } + @Override public ManagedObjectReference getParentMor() throws Exception { return _context.getVimClient().getDynamicProperty(_mor, "parent"); diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java index 96b176df5f6..b273688c162 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java @@ -801,6 +801,7 @@ public class VmwareHelper { instance = new UnmanagedInstanceTO(); instance.setName(vmMo.getVmName()); instance.setInternalCSName(vmMo.getInternalCSName()); + instance.setPath((vmMo.getPath())); instance.setCpuCoresPerSocket(vmMo.getCoresPerSocket()); instance.setOperatingSystemId(vmMo.getVmGuestInfo().getGuestId()); VirtualMachineConfigSummary configSummary = vmMo.getConfigSummary(); From c121d5bb6db9822efed9fef7a8a19215dc7218e0 Mon Sep 17 00:00:00 2001 From: Manoj Kumar Date: Tue, 18 Feb 2025 19:51:29 +0530 Subject: [PATCH 13/21] usage: use runtime scope when running maven usage profile (#10331) Fixes error running usage server with maven. Signed-off-by: Abhishek Kumar Co-authored-by: Abhishek Kumar --- usage/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usage/pom.xml b/usage/pom.xml index 325e56c3151..aea5a6a4706 100644 --- a/usage/pom.xml +++ b/usage/pom.xml @@ -61,7 +61,7 @@ com.mysql mysql-connector-j - provided + runtime org.dbunit From 6a3314c40b9769bda90b5798b8878668c764c1a2 Mon Sep 17 00:00:00 2001 From: Vishesh Date: Tue, 18 Feb 2025 19:53:43 +0530 Subject: [PATCH 14/21] Fixup alerting and logging error in BGPServiceImpl (#10252) * Fixup alerting and logging error in BGPServiceImpl * Update unit tests * Apply suggestions from code review Co-authored-by: dahn --------- Co-authored-by: dahn --- .../com/cloud/alert/AlertManagerImpl.java | 5 +- .../java/com/cloud/bgp/BGPServiceImpl.java | 6 +- .../com/cloud/alert/AlertManagerImplTest.java | 71 +++++++++++++++---- 3 files changed, 65 insertions(+), 17 deletions(-) diff --git a/server/src/main/java/com/cloud/alert/AlertManagerImpl.java b/server/src/main/java/com/cloud/alert/AlertManagerImpl.java index f4a8167c5a2..60ba90b77d5 100644 --- a/server/src/main/java/com/cloud/alert/AlertManagerImpl.java +++ b/server/src/main/java/com/cloud/alert/AlertManagerImpl.java @@ -778,13 +778,14 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager, Confi AlertVO alert = null; Long clusterId = cluster == null ? null : cluster.getId(); Long podId = pod == null ? null : pod.getId(); + long dcId = dataCenter == null ? 0L : dataCenter.getId(); if ((alertType != AlertManager.AlertType.ALERT_TYPE_HOST) && (alertType != AlertManager.AlertType.ALERT_TYPE_USERVM) && (alertType != AlertManager.AlertType.ALERT_TYPE_DOMAIN_ROUTER) && (alertType != AlertManager.AlertType.ALERT_TYPE_CONSOLE_PROXY) && (alertType != AlertManager.AlertType.ALERT_TYPE_SSVM) && (alertType != AlertManager.AlertType.ALERT_TYPE_STORAGE_MISC) && (alertType != AlertManager.AlertType.ALERT_TYPE_MANAGEMENT_NODE) && (alertType != AlertManager.AlertType.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED) && (alertType != AlertManager.AlertType.ALERT_TYPE_UPLOAD_FAILED) && (alertType != AlertManager.AlertType.ALERT_TYPE_OOBM_AUTH_ERROR) && (alertType != AlertManager.AlertType.ALERT_TYPE_HA_ACTION) && (alertType != AlertManager.AlertType.ALERT_TYPE_CA_CERT)) { - alert = _alertDao.getLastAlert(alertType.getType(), dataCenter.getId(), podId, clusterId); + alert = _alertDao.getLastAlert(alertType.getType(), dcId, podId, clusterId); } if (alert == null) { @@ -794,7 +795,7 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager, Confi newAlert.setContent(content); newAlert.setClusterId(clusterId); newAlert.setPodId(podId); - newAlert.setDataCenterId(dataCenter.getId()); + newAlert.setDataCenterId(dcId); newAlert.setSentCount(1); newAlert.setLastSent(new Date()); newAlert.setName(alertType.getName()); diff --git a/server/src/main/java/com/cloud/bgp/BGPServiceImpl.java b/server/src/main/java/com/cloud/bgp/BGPServiceImpl.java index 101731774e7..c003bd05a51 100644 --- a/server/src/main/java/com/cloud/bgp/BGPServiceImpl.java +++ b/server/src/main/java/com/cloud/bgp/BGPServiceImpl.java @@ -255,9 +255,9 @@ public class BGPServiceImpl implements BGPService { netName = network.getName(); } - LOGGER.debug("Allocating the AS Number {} to {} on zone {}", asNumber::toString, - (Objects.nonNull(vpcId) ? "VPC " + vpc : "network " + network)::toString, - () -> dataCenterDao.findById(zoneId)); + String networkName = Objects.nonNull(vpcId) ? ("VPC " + vpc) : ("network " + network); + LOGGER.debug("Allocating the AS Number {} to {} on zone {}", asNumberVO::toString, + networkName::toString, () -> dataCenterDao.findById(zoneId)); asNumberVO.setAllocated(true); asNumberVO.setAllocatedTime(new Date()); if (Objects.nonNull(vpcId)) { diff --git a/server/src/test/java/com/cloud/alert/AlertManagerImplTest.java b/server/src/test/java/com/cloud/alert/AlertManagerImplTest.java index 2959e73ae9e..d34d0b5873f 100644 --- a/server/src/test/java/com/cloud/alert/AlertManagerImplTest.java +++ b/server/src/test/java/com/cloud/alert/AlertManagerImplTest.java @@ -26,8 +26,10 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.utils.mailing.SMTPMailSender; import org.apache.logging.log4j.Logger; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; @@ -48,6 +50,12 @@ import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.storage.StorageManager; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; + @RunWith(MockitoJUnitRunner.class) public class AlertManagerImplTest { @@ -56,7 +64,7 @@ public class AlertManagerImplTest { AlertManagerImpl alertManagerImplMock; @Mock - AlertDao alertDaoMock; + AlertDao _alertDao; @Mock private DataCenterDao _dcDao; @@ -88,7 +96,16 @@ public class AlertManagerImplTest { @Mock SMTPMailSender mailSenderMock; - private void sendMessage (){ + private final String[] recipients = new String[]{"test@test.com"}; + private final String senderAddress = "sender@test.com"; + + @Before + public void setUp() { + alertManagerImplMock.recipients = recipients; + alertManagerImplMock.senderAddress = senderAddress; + } + + private void sendMessage() { try { DataCenterVO zone = Mockito.mock(DataCenterVO.class); Mockito.when(zone.getId()).thenReturn(0L); @@ -100,7 +117,7 @@ public class AlertManagerImplTest { Mockito.when(cluster.getId()).thenReturn(1L); Mockito.when(_clusterDao.findById(1L)).thenReturn(cluster); - alertManagerImplMock.sendAlert(AlertManager.AlertType.ALERT_TYPE_CPU, 0, 1l, 1l, "", ""); + alertManagerImplMock.sendAlert(AlertManager.AlertType.ALERT_TYPE_CPU, 0, 1L, 1L, "", ""); } catch (UnsupportedEncodingException | MessagingException e) { Assert.fail(); } @@ -108,39 +125,69 @@ public class AlertManagerImplTest { @Test public void sendAlertTestSendMail() { - Mockito.doReturn(null).when(alertDaoMock).getLastAlert(Mockito.anyShort(), Mockito.anyLong(), + Mockito.doReturn(null).when(_alertDao).getLastAlert(Mockito.anyShort(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong()); - Mockito.doReturn(null).when(alertDaoMock).persist(Mockito.any()); - alertManagerImplMock.recipients = new String [] {""}; + Mockito.doReturn(null).when(_alertDao).persist(any()); + alertManagerImplMock.recipients = new String[]{""}; sendMessage(); - Mockito.verify(alertManagerImplMock).sendMessage(Mockito.any()); + Mockito.verify(alertManagerImplMock).sendMessage(any()); } @Test public void sendAlertTestDebugLogging() { Mockito.doReturn(0).when(alertVOMock).getSentCount(); - Mockito.doReturn(alertVOMock).when(alertDaoMock).getLastAlert(Mockito.anyShort(), Mockito.anyLong(), + Mockito.doReturn(alertVOMock).when(_alertDao).getLastAlert(Mockito.anyShort(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong()); sendMessage(); Mockito.verify(alertManagerImplMock.logger).debug(Mockito.anyString()); - Mockito.verify(alertManagerImplMock, Mockito.never()).sendMessage(Mockito.any()); + Mockito.verify(alertManagerImplMock, Mockito.never()).sendMessage(any()); } @Test public void sendAlertTestWarnLogging() { - Mockito.doReturn(null).when(alertDaoMock).getLastAlert(Mockito.anyShort(), Mockito.anyLong(), + Mockito.doReturn(null).when(_alertDao).getLastAlert(Mockito.anyShort(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong()); - Mockito.doReturn(null).when(alertDaoMock).persist(Mockito.any()); + Mockito.doReturn(null).when(_alertDao).persist(Mockito.any()); alertManagerImplMock.recipients = null; sendMessage(); Mockito.verify(alertManagerImplMock.logger, Mockito.times(2)).warn(Mockito.anyString()); - Mockito.verify(alertManagerImplMock, Mockito.never()).sendMessage(Mockito.any()); + Mockito.verify(alertManagerImplMock, Mockito.never()).sendMessage(any()); + } + + @Test + public void testSendAlertWithNullParameters() throws MessagingException, UnsupportedEncodingException { + // Given + String subject = "Test Subject"; + String content = "Test Content"; + AlertManager.AlertType alertType = AlertManager.AlertType.ALERT_TYPE_MEMORY; + + // When + alertManagerImplMock.sendAlert(alertType, null, null, null, subject, content); + + // Then + ArgumentCaptor alertCaptor = ArgumentCaptor.forClass(AlertVO.class); + verify(_alertDao).persist(alertCaptor.capture()); + + AlertVO capturedAlert = alertCaptor.getValue(); + assertNotNull("Captured alert should not be null", capturedAlert); + assertEquals(0L, capturedAlert.getDataCenterId()); + assertNull(capturedAlert.getPodId()); + assertNull(capturedAlert.getClusterId()); + assertEquals(subject, capturedAlert.getSubject()); + assertEquals(content, capturedAlert.getContent()); + assertEquals(alertType.getType(), capturedAlert.getType()); + } + + @Test(expected = NullPointerException.class) + public void testSendAlertWithNullAlertType() throws MessagingException, UnsupportedEncodingException { + // When + alertManagerImplMock.sendAlert(null, 0, 1L, 1L, "subject", "content"); } @Test From 21b5e4dcae5b3cb73637fc82410bd8e4fd55e99c Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Tue, 18 Feb 2025 17:31:15 +0100 Subject: [PATCH 15/21] Veeam: set backed_volumes for each backup (#9898) --- .../org/apache/cloudstack/backup/VeeamBackupProvider.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/VeeamBackupProvider.java b/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/VeeamBackupProvider.java index c120d8bd599..50caa2ea888 100644 --- a/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/VeeamBackupProvider.java +++ b/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/VeeamBackupProvider.java @@ -50,6 +50,7 @@ import com.cloud.dc.VmwareDatacenter; import com.cloud.hypervisor.vmware.VmwareDatacenterZoneMap; import com.cloud.dc.dao.VmwareDatacenterDao; import com.cloud.hypervisor.vmware.dao.VmwareDatacenterZoneMapDao; +import com.cloud.storage.dao.VolumeDao; import com.cloud.user.User; import com.cloud.utils.Pair; import com.cloud.utils.component.AdapterBase; @@ -109,6 +110,8 @@ public class VeeamBackupProvider extends AdapterBase implements BackupProvider, private AgentManager agentMgr; @Inject private VirtualMachineManager virtualMachineManager; + @Inject + private VolumeDao volumeDao; protected VeeamClient getClient(final Long zoneId) { try { @@ -378,6 +381,7 @@ public class VeeamBackupProvider extends AdapterBase implements BackupProvider, backup.setAccountId(vm.getAccountId()); backup.setDomainId(vm.getDomainId()); backup.setZoneId(vm.getDataCenterId()); + backup.setBackedUpVolumes(BackupManagerImpl.createVolumeInfoFromVolumes(volumeDao.findByInstance(vm.getId()))); logger.debug("Creating a new entry in backups: [id: {}, uuid: {}, name: {}, vm_id: {}, external_id: {}, type: {}, date: {}, backup_offering_id: {}, account_id: {}, " + "domain_id: {}, zone_id: {}].", backup.getId(), backup.getUuid(), backup.getName(), backup.getVmId(), backup.getExternalId(), backup.getType(), backup.getDate(), backup.getBackupOfferingId(), backup.getAccountId(), backup.getDomainId(), backup.getZoneId()); From c0e05c4a6d7fb0cc429a5ee6433b928ebbed043e Mon Sep 17 00:00:00 2001 From: Fabricio Duarte Date: Wed, 19 Feb 2025 08:44:26 -0300 Subject: [PATCH 16/21] Fix Usage inconsistencies (#9888) --- .../cloud/usage/dao/UsageNetworksDaoImpl.java | 10 ++++------ .../com/cloud/usage/dao/UsageVpcDaoImpl.java | 10 ++++------ .../com/cloud/usage/UsageManagerImpl.java | 19 +++++++++++++------ 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/usage/dao/UsageNetworksDaoImpl.java b/engine/schema/src/main/java/com/cloud/usage/dao/UsageNetworksDaoImpl.java index f8ffbf74f85..99ba3587688 100644 --- a/engine/schema/src/main/java/com/cloud/usage/dao/UsageNetworksDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/usage/dao/UsageNetworksDaoImpl.java @@ -16,7 +16,6 @@ // under the License. package com.cloud.usage.dao; -import com.cloud.network.Network; import com.cloud.usage.UsageNetworksVO; import com.cloud.utils.DateUtil; import com.cloud.utils.db.GenericDaoBase; @@ -70,11 +69,10 @@ public class UsageNetworksDaoImpl extends GenericDaoBase SearchCriteria sc = this.createSearchCriteria(); sc.addAnd("networkId", SearchCriteria.Op.EQ, networkId); sc.addAnd("removed", SearchCriteria.Op.NULL); - UsageNetworksVO vo = findOneBy(sc); - if (vo != null) { - vo.setRemoved(removed); - vo.setState(Network.State.Destroy.name()); - update(vo.getId(), vo); + List usageNetworksVOs = listBy(sc); + for (UsageNetworksVO entry : usageNetworksVOs) { + entry.setRemoved(removed); + update(entry.getId(), entry); } } catch (final Exception e) { txn.rollback(); diff --git a/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java b/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java index 45ae845e58f..70cdadd1629 100644 --- a/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java @@ -16,7 +16,6 @@ // under the License. package com.cloud.usage.dao; -import com.cloud.network.vpc.Vpc; import com.cloud.usage.UsageVpcVO; import com.cloud.utils.DateUtil; import com.cloud.utils.db.GenericDaoBase; @@ -64,11 +63,10 @@ public class UsageVpcDaoImpl extends GenericDaoBase implements SearchCriteria sc = this.createSearchCriteria(); sc.addAnd("vpcId", SearchCriteria.Op.EQ, vpcId); sc.addAnd("removed", SearchCriteria.Op.NULL); - UsageVpcVO vo = findOneBy(sc); - if (vo != null) { - vo.setRemoved(removed); - vo.setState(Vpc.State.Inactive.name()); - update(vo.getId(), vo); + List usageVpcVOs = listBy(sc); + for (UsageVpcVO entry : usageVpcVOs) { + entry.setRemoved(removed); + update(entry.getId(), entry); } } catch (final Exception e) { txn.rollback(); diff --git a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java index b9b32e7ff9b..9be7c0538b7 100644 --- a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java +++ b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java @@ -1544,7 +1544,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna //For volumes which are 'attached' successfully, set the 'deleted' column in the usage_storage table, //so that the secondary storage should stop accounting and only primary will be accounted. SearchCriteria sc = _usageStorageDao.createSearchCriteria(); - sc.addAnd("id", SearchCriteria.Op.EQ, volId); + sc.addAnd("entityId", SearchCriteria.Op.EQ, volId); sc.addAnd("storageType", SearchCriteria.Op.EQ, StorageTypes.VOLUME); List volumesVOs = _usageStorageDao.search(sc, null); if (volumesVOs != null) { @@ -1599,7 +1599,8 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna //For Upload event add an entry to the usage_storage table. SearchCriteria sc = _usageStorageDao.createSearchCriteria(); sc.addAnd("accountId", SearchCriteria.Op.EQ, event.getAccountId()); - sc.addAnd("id", SearchCriteria.Op.EQ, volId); + sc.addAnd("entityId", SearchCriteria.Op.EQ, volId); + sc.addAnd("storageType", SearchCriteria.Op.EQ, StorageTypes.VOLUME); sc.addAnd("deleted", SearchCriteria.Op.NULL); List volumesVOs = _usageStorageDao.search(sc, null); @@ -1776,7 +1777,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna } else if (EventTypes.EVENT_LOAD_BALANCER_DELETE.equals(event.getType())) { SearchCriteria sc = _usageLoadBalancerPolicyDao.createSearchCriteria(); sc.addAnd("accountId", SearchCriteria.Op.EQ, event.getAccountId()); - sc.addAnd("id", SearchCriteria.Op.EQ, id); + sc.addAnd("lbId", SearchCriteria.Op.EQ, id); sc.addAnd("deleted", SearchCriteria.Op.NULL); List lbVOs = _usageLoadBalancerPolicyDao.search(sc, null); if (lbVOs.size() > 1) { @@ -1810,7 +1811,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna } else if (EventTypes.EVENT_NET_RULE_DELETE.equals(event.getType())) { SearchCriteria sc = _usagePortForwardingRuleDao.createSearchCriteria(); sc.addAnd("accountId", SearchCriteria.Op.EQ, event.getAccountId()); - sc.addAnd("id", SearchCriteria.Op.EQ, id); + sc.addAnd("pfId", SearchCriteria.Op.EQ, id); sc.addAnd("deleted", SearchCriteria.Op.NULL); List pfVOs = _usagePortForwardingRuleDao.search(sc, null); if (pfVOs.size() > 1) { @@ -2111,7 +2112,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna } else if (EventTypes.EVENT_VM_SNAPSHOT_OFF_PRIMARY.equals(event.getType())) { QueryBuilder sc = QueryBuilder.create(UsageSnapshotOnPrimaryVO.class); sc.and(sc.entity().getAccountId(), SearchCriteria.Op.EQ, event.getAccountId()); - sc.and(sc.entity().getId(), SearchCriteria.Op.EQ, vmId); + sc.and(sc.entity().getVmId(), SearchCriteria.Op.EQ, vmId); sc.and(sc.entity().getName(), SearchCriteria.Op.EQ, name); sc.and(sc.entity().getDeleted(), SearchCriteria.Op.NULL); List vmsnaps = sc.list(); @@ -2154,6 +2155,9 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna if (EventTypes.EVENT_NETWORK_DELETE.equals(event.getType())) { usageNetworksDao.remove(event.getResourceId(), event.getCreateDate()); } else if (EventTypes.EVENT_NETWORK_CREATE.equals(event.getType())) { + logger.debug("Marking existing helper entries for network [{}] as removed.", event.getResourceId()); + usageNetworksDao.remove(event.getResourceId(), event.getCreateDate()); + logger.debug("Creating a helper entry for network [{}].", event.getResourceId()); UsageNetworksVO usageNetworksVO = new UsageNetworksVO(event.getResourceId(), event.getOfferingId(), event.getZoneId(), event.getAccountId(), domainId, Network.State.Allocated.name(), event.getCreateDate(), null); usageNetworksDao.persist(usageNetworksVO); } else if (EventTypes.EVENT_NETWORK_UPDATE.equals(event.getType())) { @@ -2169,10 +2173,13 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna if (EventTypes.EVENT_VPC_DELETE.equals(event.getType())) { usageVpcDao.remove(event.getResourceId(), event.getCreateDate()); } else if (EventTypes.EVENT_VPC_CREATE.equals(event.getType())) { + logger.debug("Marking existing helper entries for VPC [{}] as removed.", event.getResourceId()); + usageVpcDao.remove(event.getResourceId(), event.getCreateDate()); + logger.debug("Creating a helper entry for VPC [{}].", event.getResourceId()); UsageVpcVO usageVPCVO = new UsageVpcVO(event.getResourceId(), event.getZoneId(), event.getAccountId(), domainId, Vpc.State.Enabled.name(), event.getCreateDate(), null); usageVpcDao.persist(usageVPCVO); } else { - logger.error(String.format("Unknown event type [%s] in VPC event parser. Skipping it.", event.getType())); + logger.error("Unknown event type [{}] in VPC event parser. Skipping it.", event.getType()); } } From 66f8a351dd5767ca86e8b18fb2cc21f74ad60268 Mon Sep 17 00:00:00 2001 From: dahn Date: Wed, 19 Feb 2025 12:53:10 +0100 Subject: [PATCH 17/21] migrate Vmware to KVM ui issues (#10413) --- ui/public/locales/en.json | 4 ++- ui/src/views/tools/SelectVmwareVcenter.vue | 32 +++++++++++++------ .../cloud/hypervisor/vmware/mo/BaseMO.java | 4 +++ 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 944a24f4219..666d2a31e39 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -1591,6 +1591,8 @@ "label.prepare.for.shutdown": "Prepare for Shutdown", "label.prepareformaintenance": "Prepare for Maintenance", "label.presetup": "PreSetup", +"label.press.enter": "Press enter when done.", +"label.press.enter.tooltip": "On leaving a any of these fields above, when they all contain values, or on pressing enter, ESXi hosts will be retrieved. If this is successful, a dropdown will appear with the list of ESXi hosts.", "label.prev": "Prev", "label.previous": "Previous", "label.primera.username.tooltip": "The username with edit privileges", @@ -3006,7 +3008,7 @@ "message.license.agreements.not.accepted": "License agreements not accepted.", "message.linstor.resourcegroup.description": "Linstor resource group to use for primary storage.", "message.list.zone.vmware.datacenter.empty": "No VMware Datacenter exists in the selected Zone", -"message.list.zone.vmware.hosts.empty": "No VMware hosts were found in the selected Datacenter", +"message.list.zone.vmware.hosts.empty": "No EXSi hosts were found in the selected Datacenter.\nAre the entered credentials correct?\n", "message.listnsp.not.return.providerid": "error: listNetworkServiceProviders API doesn't return VirtualRouter provider ID.", "message.load.host.failed": "Failed to load hosts.", "message.loadbalancer.stickypolicy.configuration": "Customize the load balancer stickiness policy:", diff --git a/ui/src/views/tools/SelectVmwareVcenter.vue b/ui/src/views/tools/SelectVmwareVcenter.vue index 1d25657b11b..e93d893e9fc 100644 --- a/ui/src/views/tools/SelectVmwareVcenter.vue +++ b/ui/src/views/tools/SelectVmwareVcenter.vue @@ -89,7 +89,8 @@ @@ -99,7 +100,8 @@ @@ -109,7 +111,8 @@ @@ -119,13 +122,16 @@ +   +
- + + {{ }} {{ 'ESXi: ' + opt.name }} @@ -283,7 +290,7 @@ export default { this.loading = false }) }, - listZoneVmwareDcHosts () { + loadZoneVmwareDcHosts (doNotify) { this.loading = true const params = {} if (this.vcenterSelectedOption === 'new') { @@ -299,18 +306,23 @@ export default { this.hosts = response.listvmwaredchostsresponse.host } }).catch(error => { - this.$notifyError(error) + if (doNotify) { + this.$notifyError(error) + } + this.hosts = [] + return false }).finally(() => { this.loading = false + return true }) }, onSelectExistingVmwareDatacenter (value) { this.selectedExistingVcenterId = value - this.listZoneVmwareDcHosts() + this.loadZoneVmwareDcHosts(true) }, onSelectExternalVmwareDatacenter (value) { if (this.vcenterSelectedOption === 'new' && !(this.vcenter === '' || this.datacentername === '' || this.username === '' || this.password === '')) { - this.listZoneVmwareDcHosts() + this.loadZoneVmwareDcHosts(false) } }, onSelectExistingVmwareHost (value) { diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/BaseMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/BaseMO.java index 15fc4ab8b2e..27ca6396a47 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/BaseMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/BaseMO.java @@ -33,6 +33,7 @@ import com.vmware.vim25.ObjectContent; import com.vmware.vim25.RetrieveResult; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; import java.util.List; public class BaseMO { @@ -65,6 +66,9 @@ public class BaseMO { if (s_logger.isDebugEnabled()) { s_logger.debug("vmware result : " + ReflectionToStringBuilderUtils.reflectCollection(result)); } + if (result == null) { + return new Pair<>(null, new ArrayList<>()); + } String tokenForRetrievingNewResults = result.getToken(); List listOfObjects = result.getObjects(); return new Pair<>(tokenForRetrievingNewResults, listOfObjects); From ee32f4cfe8c76e9d71649d87994c9093c9feef84 Mon Sep 17 00:00:00 2001 From: BartJM Date: Wed, 19 Feb 2025 14:33:49 +0100 Subject: [PATCH 18/21] Add cpu speed detection methods (#9762) Added additional match for lscpu Added additional file to check --- .../cloudstack/utils/linux/KVMHostInfo.java | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/linux/KVMHostInfo.java b/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/linux/KVMHostInfo.java index c0b416410cb..cee07421314 100644 --- a/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/linux/KVMHostInfo.java +++ b/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/linux/KVMHostInfo.java @@ -58,9 +58,8 @@ public class KVMHostInfo { private long reservedMemory; private long overCommitMemory; private List capabilities = new ArrayList<>(); - - private static String cpuInfoFreqFileName = "/sys/devices/system/cpu/cpu0/cpufreq/base_frequency"; private static String cpuArchCommand = "/usr/bin/arch"; + private static List cpuInfoFreqFileNames = List.of("/sys/devices/system/cpu/cpu0/cpufreq/base_frequency","/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq"); public KVMHostInfo(long reservedMemory, long overCommitMemory, long manualSpeed, int reservedCpus) { this.cpuSpeed = manualSpeed; @@ -134,29 +133,41 @@ public class KVMHostInfo { } private static long getCpuSpeedFromCommandLscpu() { + long speed = 0L; + LOGGER.info("Fetching CPU speed from command \"lscpu\"."); try { - LOGGER.info("Fetching CPU speed from command \"lscpu\"."); String command = "lscpu | grep -i 'Model name' | head -n 1 | egrep -o '[[:digit:]].[[:digit:]]+GHz' | sed 's/GHz//g'"; String result = Script.runSimpleBashScript(command); - long speed = (long) (Float.parseFloat(result) * 1000); + speed = (long) (Float.parseFloat(result) * 1000); LOGGER.info(String.format("Command [%s] resulted in the value [%s] for CPU speed.", command, speed)); return speed; } catch (NullPointerException | NumberFormatException e) { LOGGER.error(String.format("Unable to retrieve the CPU speed from lscpu."), e); - return 0L; } + try { + String command = "lscpu | grep -i 'CPU max MHz' | head -n 1 | sed 's/^.*: //' | xargs"; + String result = Script.runSimpleBashScript(command); + speed = (long) (Float.parseFloat(result)); + LOGGER.info(String.format("Command [%s] resulted in the value [%s] for CPU speed.", command, speed)); + return speed; + } catch (NullPointerException | NumberFormatException e) { + LOGGER.error(String.format("Unable to retrieve the CPU speed from lscpu."), e); + } + return speed; } private static long getCpuSpeedFromFile() { - LOGGER.info(String.format("Fetching CPU speed from file [%s].", cpuInfoFreqFileName)); - try (Reader reader = new FileReader(cpuInfoFreqFileName)) { - Long cpuInfoFreq = Long.parseLong(IOUtils.toString(reader).trim()); - LOGGER.info(String.format("Retrieved value [%s] from file [%s]. This corresponds to a CPU speed of [%s] MHz.", cpuInfoFreq, cpuInfoFreqFileName, cpuInfoFreq / 1000)); - return cpuInfoFreq / 1000; - } catch (IOException | NumberFormatException e) { - LOGGER.error(String.format("Unable to retrieve the CPU speed from file [%s]", cpuInfoFreqFileName), e); - return 0L; + for (final String cpuInfoFreqFileName: cpuInfoFreqFileNames) { + LOGGER.info(String.format("Fetching CPU speed from file [%s].", cpuInfoFreqFileName)); + try (Reader reader = new FileReader(cpuInfoFreqFileName)) { + Long cpuInfoFreq = Long.parseLong(IOUtils.toString(reader).trim()); + LOGGER.info(String.format("Retrieved value [%s] from file [%s]. This corresponds to a CPU speed of [%s] MHz.", cpuInfoFreq, cpuInfoFreqFileName, cpuInfoFreq / 1000)); + return cpuInfoFreq / 1000; + } catch (IOException | NumberFormatException e) { + LOGGER.error(String.format("Unable to retrieve the CPU speed from file [%s]", cpuInfoFreqFileName), e); + } } + return 0L; } protected static long getCpuSpeedFromHostCapabilities(final String capabilities) { From 4b432c82ca00fa1bd9198de82434d1e6d9fcd321 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 19 Feb 2025 08:43:41 -0500 Subject: [PATCH 19/21] List only those hosts matching source host arch in multi-arch zones (#10369) * List only those hosts matching source host arch in multi-arch zones * remove duplicate import due to merge conflict * filter only if suitable hosts aren't empty * get cpu archs only if there are suitable hosts --- .../main/java/com/cloud/server/ManagementServerImpl.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index 9ffad8b8418..8575a26a5cb 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -44,6 +44,7 @@ import javax.crypto.spec.SecretKeySpec; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.cpu.CPU; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.affinity.AffinityGroupProcessor; @@ -1612,6 +1613,14 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe logger.debug("Hosts having capacity and suitable for migration: {}", suitableHosts); } + // Only list hosts of the same architecture as the source Host in a multi-arch zone + if (!suitableHosts.isEmpty()) { + List clusterArchs = ApiDBUtils.listZoneClustersArchs(vm.getDataCenterId()); + if (CollectionUtils.isNotEmpty(clusterArchs) && clusterArchs.size() > 1) { + suitableHosts = suitableHosts.stream().filter(h -> h.getArch() == srcHost.getArch()).collect(Collectors.toList()); + } + } + return new Ternary<>(otherHosts, suitableHosts, requiresStorageMotion); } From e196275d5a6e4b6c05cd9c82db30b4dc0ef7e545 Mon Sep 17 00:00:00 2001 From: dahn Date: Thu, 20 Feb 2025 09:01:28 +0100 Subject: [PATCH 20/21] ipmi: extra log sanitation (#10428) --- .../IpmitoolOutOfBandManagementDriver.java | 8 ++-- .../driver/ipmitool/IpmitoolWrapper.java | 37 +++++++++++-------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/plugins/outofbandmanagement-drivers/ipmitool/src/main/java/org/apache/cloudstack/outofbandmanagement/driver/ipmitool/IpmitoolOutOfBandManagementDriver.java b/plugins/outofbandmanagement-drivers/ipmitool/src/main/java/org/apache/cloudstack/outofbandmanagement/driver/ipmitool/IpmitoolOutOfBandManagementDriver.java index 2c42554afcc..53a7efbea9e 100644 --- a/plugins/outofbandmanagement-drivers/ipmitool/src/main/java/org/apache/cloudstack/outofbandmanagement/driver/ipmitool/IpmitoolOutOfBandManagementDriver.java +++ b/plugins/outofbandmanagement-drivers/ipmitool/src/main/java/org/apache/cloudstack/outofbandmanagement/driver/ipmitool/IpmitoolOutOfBandManagementDriver.java @@ -47,13 +47,13 @@ public final class IpmitoolOutOfBandManagementDriver extends AdapterBase impleme private final ExecutorService ipmitoolExecutor = Executors.newFixedThreadPool(OutOfBandManagementService.SyncThreadPoolSize.value(), new NamedThreadFactory("IpmiToolDriver")); private final IpmitoolWrapper IPMITOOL = new IpmitoolWrapper(ipmitoolExecutor); - public final ConfigKey IpmiToolPath = new ConfigKey("Advanced", String.class, "outofbandmanagement.ipmitool.path", "/usr/bin/ipmitool", + public final ConfigKey IpmiToolPath = new ConfigKey<>("Advanced", String.class, "outofbandmanagement.ipmitool.path", "/usr/bin/ipmitool", "The out of band management ipmitool path used by the IpmiTool driver. Default: /usr/bin/ipmitool.", true, ConfigKey.Scope.Global); - public final ConfigKey IpmiToolInterface = new ConfigKey("Advanced", String.class, "outofbandmanagement.ipmitool.interface", "lanplus", + public final ConfigKey IpmiToolInterface = new ConfigKey<>("Advanced", String.class, "outofbandmanagement.ipmitool.interface", "lanplus", "The out of band management IpmiTool driver interface to use. Default: lanplus. Valid values are: lan, lanplus, open etc.", true, ConfigKey.Scope.Global); - public final ConfigKey IpmiToolRetries = new ConfigKey("Advanced", String.class, "outofbandmanagement.ipmitool.retries", "1", + public final ConfigKey IpmiToolRetries = new ConfigKey<>("Advanced", String.class, "outofbandmanagement.ipmitool.retries", "1", "The out of band management IpmiTool driver retries option -R. Default 1.", true, ConfigKey.Scope.Global); private String getIpmiUserId(ImmutableMap options, final Duration timeOut) { @@ -122,7 +122,7 @@ public final class IpmitoolOutOfBandManagementDriver extends AdapterBase impleme final OutOfBandManagementDriverResponse response = IPMITOOL.executeCommands(ipmiToolCommands, cmd.getTimeout()); - String oneLineCommand = StringUtils.join(ipmiToolCommands, " "); + String oneLineCommand = StringUtils.join(IPMITOOL.getSanatisedCommandStrings(ipmiToolCommands), " "); String result = response.getResult().trim(); if (response.isSuccess()) { diff --git a/plugins/outofbandmanagement-drivers/ipmitool/src/main/java/org/apache/cloudstack/outofbandmanagement/driver/ipmitool/IpmitoolWrapper.java b/plugins/outofbandmanagement-drivers/ipmitool/src/main/java/org/apache/cloudstack/outofbandmanagement/driver/ipmitool/IpmitoolWrapper.java index 6fe98c0925c..2004943c0c6 100644 --- a/plugins/outofbandmanagement-drivers/ipmitool/src/main/java/org/apache/cloudstack/outofbandmanagement/driver/ipmitool/IpmitoolWrapper.java +++ b/plugins/outofbandmanagement-drivers/ipmitool/src/main/java/org/apache/cloudstack/outofbandmanagement/driver/ipmitool/IpmitoolWrapper.java @@ -26,6 +26,7 @@ import org.apache.cloudstack.outofbandmanagement.driver.OutOfBandManagementDrive import org.apache.cloudstack.utils.process.ProcessResult; import org.apache.cloudstack.utils.process.ProcessRunner; import org.apache.log4j.Logger; +import org.jetbrains.annotations.NotNull; import org.joda.time.Duration; import java.util.ArrayList; @@ -156,25 +157,31 @@ public final class IpmitoolWrapper { public OutOfBandManagementDriverResponse executeCommands(final List commands, final Duration timeOut) { final ProcessResult result = RUNNER.executeCommands(commands, timeOut); if (LOG.isTraceEnabled()) { - List cleanedCommands = new ArrayList(); - int maskNextCommand = 0; - for (String command : commands) { - if (maskNextCommand > 0) { - cleanedCommands.add("**** "); - maskNextCommand--; - continue; - } - if (command.equalsIgnoreCase("-P")) { - maskNextCommand = 1; - } else if (command.toLowerCase().endsWith("password")) { - maskNextCommand = 2; - } - cleanedCommands.add(command); - } + List cleanedCommands = getSanatisedCommandStrings(commands); LOG.trace("Executed ipmitool process with commands: " + StringUtils.join(cleanedCommands, ", ") + "\nIpmitool execution standard output: " + result.getStdOutput() + "\nIpmitool execution error output: " + result.getStdError()); } return new OutOfBandManagementDriverResponse(result.getStdOutput(), result.getStdError(), result.isSuccess()); } + + @NotNull + List getSanatisedCommandStrings(List commands) { + List cleanedCommands = new ArrayList(); + int maskNextCommand = 0; + for (String command : commands) { + if (maskNextCommand > 0) { + cleanedCommands.add("**** "); + maskNextCommand--; + continue; + } + if (command.equalsIgnoreCase("-P")) { + maskNextCommand = 1; + } else if (command.toLowerCase().endsWith("password")) { + maskNextCommand = 2; + } + cleanedCommands.add(command); + } + return cleanedCommands; + } } From c80b8860e49c61252588c8cf8f40277dcf2c4ee8 Mon Sep 17 00:00:00 2001 From: Nicole Schmidt <45316185+nicoschmdt@users.noreply.github.com> Date: Thu, 20 Feb 2025 11:11:53 -0300 Subject: [PATCH 21/21] Fix hostId verification on unsuccessful expunge operation (#10418) --- .../src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index 6d27b0efed3..7b231d02cb0 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -707,7 +707,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac private void handleUnsuccessfulExpungeOperation(List finalizeExpungeCommands, List nicExpungeCommands, VMInstanceVO vm, Long hostId) throws OperationTimedoutException, AgentUnavailableException { - if (CollectionUtils.isNotEmpty(finalizeExpungeCommands) || CollectionUtils.isNotEmpty(nicExpungeCommands) && (hostId != null)) { + if ((CollectionUtils.isNotEmpty(finalizeExpungeCommands) || CollectionUtils.isNotEmpty(nicExpungeCommands)) && hostId != null) { final Commands cmds = new Commands(Command.OnError.Stop); addAllExpungeCommandsFromList(finalizeExpungeCommands, cmds, vm); addAllExpungeCommandsFromList(nicExpungeCommands, cmds, vm);