diff --git a/config.ts b/config.ts
index f0e24735..71c14208 100644
--- a/config.ts
+++ b/config.ts
@@ -141,6 +141,12 @@ const conf: Config = {
types: ["destination"],
requiredFields: ["cluster"],
},
+ {
+ name: "cloudstack",
+ types: ["destination"],
+ requiredFields: ["zone"],
+ relistFields: ["linux_template", "windows_template"],
+ },
],
/*
@@ -170,6 +176,7 @@ const conf: Config = {
metal: 4,
lxd: 4,
libvirt: 4,
+ cloudstack: 4,
},
providerNames: {
@@ -193,6 +200,7 @@ const conf: Config = {
lxd: "LXD",
proxmox: "Proxmox VE",
libvirt: "Libvirt",
+ cloudstack: "Cloudstack",
},
// The list of providers for which to disable setting the 'Execute Now Options' field
diff --git a/server/api/resources/providerLogos/cloudstack-128-disabled.svg b/server/api/resources/providerLogos/cloudstack-128-disabled.svg
new file mode 100644
index 00000000..0785912c
--- /dev/null
+++ b/server/api/resources/providerLogos/cloudstack-128-disabled.svg
@@ -0,0 +1,363 @@
+
+
diff --git a/server/api/resources/providerLogos/cloudstack-128.svg b/server/api/resources/providerLogos/cloudstack-128.svg
new file mode 100644
index 00000000..14680f5b
--- /dev/null
+++ b/server/api/resources/providerLogos/cloudstack-128.svg
@@ -0,0 +1,362 @@
+
+
diff --git a/server/api/resources/providerLogos/cloudstack-32-white.svg b/server/api/resources/providerLogos/cloudstack-32-white.svg
new file mode 100644
index 00000000..a24e3dfd
--- /dev/null
+++ b/server/api/resources/providerLogos/cloudstack-32-white.svg
@@ -0,0 +1,207 @@
+
+
diff --git a/server/api/resources/providerLogos/cloudstack-32.svg b/server/api/resources/providerLogos/cloudstack-32.svg
new file mode 100644
index 00000000..99025377
--- /dev/null
+++ b/server/api/resources/providerLogos/cloudstack-32.svg
@@ -0,0 +1,206 @@
+
+
diff --git a/server/api/resources/providerLogos/cloudstack-42.svg b/server/api/resources/providerLogos/cloudstack-42.svg
new file mode 100644
index 00000000..a20900a9
--- /dev/null
+++ b/server/api/resources/providerLogos/cloudstack-42.svg
@@ -0,0 +1,207 @@
+
+
diff --git a/server/api/resources/providerLogos/cloudstack-64.svg b/server/api/resources/providerLogos/cloudstack-64.svg
new file mode 100644
index 00000000..b7820860
--- /dev/null
+++ b/server/api/resources/providerLogos/cloudstack-64.svg
@@ -0,0 +1,363 @@
+
+
diff --git a/src/@types/Providers.ts b/src/@types/Providers.ts
index 773c0c34..0aab6fdc 100644
--- a/src/@types/Providers.ts
+++ b/src/@types/Providers.ts
@@ -32,7 +32,8 @@ export type ProviderTypes =
| "metal"
| "rhev"
| "lxd"
- | "libvirt";
+ | "libvirt"
+ | "cloudstack";
export type Providers = {
[provider in ProviderTypes]: {
diff --git a/src/plugins/cloudstack/OptionsSchemaPlugin.ts b/src/plugins/cloudstack/OptionsSchemaPlugin.ts
new file mode 100644
index 00000000..5a0f316e
--- /dev/null
+++ b/src/plugins/cloudstack/OptionsSchemaPlugin.ts
@@ -0,0 +1,42 @@
+/*
+Copyright (C) 2026 Cloudbase Solutions SRL
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+*/
+
+import type { Field } from "@src/@types/Field";
+import type { SchemaProperties, SchemaDefinitions } from "@src/@types/Schema";
+import OptionsSchemaPluginBase from "../default/OptionsSchemaPlugin";
+
+export default class OptionsSchemaParser extends OptionsSchemaPluginBase {
+ override parseSchemaToFields(opts: {
+ schema: SchemaProperties;
+ schemaDefinitions?: SchemaDefinitions | null | undefined;
+ dictionaryKey?: string;
+ requiresWindowsImage?: boolean;
+ }) {
+ return super.parseSchemaToFields(opts);
+ }
+
+ override sortFields(fields: Field[]) {
+ super.sortFields(fields);
+ fields.sort((f1, f2) => {
+ // sort zone field first
+ if (f1.name === "zone") {
+ return -1;
+ }
+ if (f2.name === "zone") {
+ return 1;
+ }
+ return 0;
+ });
+ }
+}
diff --git a/tests/mocks/ProvidersMock.ts b/tests/mocks/ProvidersMock.ts
index 0ac952b5..c33482e9 100644
--- a/tests/mocks/ProvidersMock.ts
+++ b/tests/mocks/ProvidersMock.ts
@@ -62,4 +62,7 @@ export const PROVIDERS_MOCK: Providers = {
vhi: {
types: [],
},
+ cloudstack: {
+ types: [],
+ },
};