From 90458ac08cd2f5b44bc66b6cbde1e7561371ae17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Peliz=C3=A4us?= Date: Wed, 12 Aug 2026 14:22:27 +0200 Subject: [PATCH 01/15] github: Add dependabot checks for doc/requirements.txt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similar to https://github.com/canonical/lxd/commit/f69ed17ba65221a62ea6536aa63f55185971ca44. Should address some of the code scanning alerts like https://github.com/canonical/microcloud/security/code-scanning/505. Signed-off-by: Julian Pelizäus (cherry picked from commit 6d7f8937c35ab10830e3af930324c8b56f492920) --- .github/dependabot.yml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 9d9e1584c..1aab8c33e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -28,6 +28,23 @@ updates: patterns: - "*" + - package-ecosystem: "pip" + directory: "/doc" + ignore: + # Pinned intentionally: myst-parser v5.0.0 causes version conflicts. + - dependency-name: "myst-parser" + versions: [">=5.0.0"] + labels: [] + schedule: + interval: "weekly" + target-branch: "main" + cooldown: + default-days: 7 + groups: + pip: + patterns: + - "*" + - package-ecosystem: "github-actions" directories: - "/" @@ -55,3 +72,20 @@ updates: gomod: patterns: - "*" + + - package-ecosystem: "pip" + directory: "/doc" + ignore: + # Pinned intentionally: myst-parser v5.0.0 causes version conflicts. + - dependency-name: "myst-parser" + versions: [">=5.0.0"] + labels: [] + schedule: + interval: "weekly" + target-branch: "v2-edge" + cooldown: + default-days: 7 + groups: + pip: + patterns: + - "*" From ca5b56c05d7cd537d0b91ac73139b05c0af0351b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Peliz=C3=A4us?= Date: Wed, 12 Aug 2026 14:00:58 +0200 Subject: [PATCH 02/15] test/e2e/run: Add instanceListByMember func MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julian Pelizäus (cherry picked from commit fdf752ca73e131897739db0c4ccab70e9747e5a2) --- test/e2e/run | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/e2e/run b/test/e2e/run index e6ee35d24..06d7d2dc5 100755 --- a/test/e2e/run +++ b/test/e2e/run @@ -202,6 +202,11 @@ instanceList() { lxc list --project e2e-testing -f csv -c n "${REMOTE}:" } +instanceListByMember() { + local member="${1}" + lxc list --project e2e-testing -f csv -c n "${REMOTE}:" location="${member}" +} + clusterMembers() { local state="${1}" [ "${state}" = "ALL" ] && state=".*" From 4269a8d56691485485915a996de0ee6c766755b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Peliz=C3=A4us?= Date: Wed, 12 Aug 2026 14:01:43 +0200 Subject: [PATCH 03/15] test/e2e/run: Wait for restarted instances to actually have an address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is important later for the connectivity tests. Signed-off-by: Julian Pelizäus (cherry picked from commit 2dd3c2ec5ea3a8c49237476f838d464f375a0d80) --- test/e2e/run | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/test/e2e/run b/test/e2e/run index 06d7d2dc5..4f12e2f04 100755 --- a/test/e2e/run +++ b/test/e2e/run @@ -289,14 +289,23 @@ evacuation() { fi lxc cluster restore --project e2e-testing --force "${REMOTE}:${member}" - done - echo -n "Allow time for stopped instances to start back again " - for _ in $(seq 20); do - echo -n "." - sleep 1 + echo -n "Allow time for stopped instances on ${member} to start back again and have an IPv4 address" + for instance in $(instanceListByMember "${member}"); do + attempts=0 + while [ -z "$(getIPv4 "${instance}")" ]; do + echo -n "." + sleep 1 + attempts=$((attempts + 1)) + if [ "${attempts}" -ge 30 ]; then + echo " FAILED" + exit 1 + fi + done + done + + echo " DONE" done - echo " DONE" } From 570bdc75003e8483df3885bc29b1fbb5beac80ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Peliz=C3=A4us?= Date: Thu, 13 Aug 2026 10:54:11 +0200 Subject: [PATCH 04/15] cmd/microcloud/preseed: Drop disk existance check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When in preseed mode, we cannot simply check for the existance of the disks selected for Ceph OSDs from the initiator. An os.Stat on the disk path would only work for disks which are actually located on the initiator. An approach would be to compare the selected disks against the disks returned from LXD's resources endpoint. However we can only generate a limited list of disks paths from the response like /dev/xyz and /dev/disk/by-id/xyz. This means we cannot account for all different device disk paths a user might pick to compare against. Therefore the only practical approach in the moment is to remove the faulty check. In case wrong disks are selected, either local or remote storage setup will fail anyway if the disk is not available. In the interactive mode we generate a list of disks paths from the LXD resource API response. The user can select disks from this list which ensures only valid disks are picked. Signed-off-by: Julian Pelizäus (cherry picked from commit dea46a95607da097edfe97667fc32334fd2afa38) --- cmd/microcloud/preseed.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/cmd/microcloud/preseed.go b/cmd/microcloud/preseed.go index 920df5034..4fc4397ac 100644 --- a/cmd/microcloud/preseed.go +++ b/cmd/microcloud/preseed.go @@ -918,13 +918,6 @@ func (p *Preseed) Parse(s *service.Handler, c *initConfig, installedServices map directLocal = sys.Storage.Local directCeph = sys.Storage.Ceph } - - for _, disk := range directCeph { - _, err := os.Stat(disk.Path) - if err != nil { - return nil, fmt.Errorf("Failed to find specified disk path: %w", err) - } - } } // Setup directly specified disks for ZFS pool. From abbddc420060167dca7d818ff2a47399a72c29ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Peliz=C3=A4us?= Date: Thu, 13 Aug 2026 12:20:01 +0200 Subject: [PATCH 05/15] api: Include status retrieval errors to log message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should help to further investigate https://github.com/canonical/microcloud/issues/1307. Signed-off-by: Julian Pelizäus (cherry picked from commit b01d79412d059c1e6129ef746be991666cb779cf) --- api/status.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/status.go b/api/status.go index d486ad2da..ca42c8ecb 100644 --- a/api/status.go +++ b/api/status.go @@ -90,7 +90,7 @@ func statusGet(sh *service.Handler) endpointHandler { case types.LXD: clusterMembers, err := lxdStatus(r.Context(), s) if err != nil { - logger.Error("Failed to get service status", logger.Ctx{"type": s.Type(), "name": sh.Name}) + logger.Error("Failed to get service status", logger.Ctx{"type": s.Type(), "name": sh.Name, "err": err}) } statusMu.Lock() @@ -99,7 +99,7 @@ func statusGet(sh *service.Handler) endpointHandler { case types.MicroCeph: clusterMembers, osds, cephServices, err := cephStatus(r.Context(), s) if err != nil { - logger.Error("Failed to get service status", logger.Ctx{"type": s.Type(), "name": sh.Name}) + logger.Error("Failed to get service status", logger.Ctx{"type": s.Type(), "name": sh.Name, "err": err}) } status.OSDs = osds @@ -111,7 +111,7 @@ func statusGet(sh *service.Handler) endpointHandler { case types.MicroOVN: clusterMembers, ovnServices, err := ovnStatus(r.Context(), s) if err != nil { - logger.Error("Failed to get service status", logger.Ctx{"type": s.Type(), "name": sh.Name}) + logger.Error("Failed to get service status", logger.Ctx{"type": s.Type(), "name": sh.Name, "err": err}) } status.OVNServices = ovnServices @@ -127,7 +127,7 @@ func statusGet(sh *service.Handler) endpointHandler { clusterMembers, err := microStatus(r.Context(), microClient, s) if err != nil { - logger.Error("Failed to get service status", logger.Ctx{"type": s.Type(), "name": sh.Name}) + logger.Error("Failed to get service status", logger.Ctx{"type": s.Type(), "name": sh.Name, "err": err}) } statusMu.Lock() From f2c30a6da0a109712f8a3b607ccbd956cf59f037 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Peliz=C3=A4us?= Date: Thu, 13 Aug 2026 12:25:38 +0200 Subject: [PATCH 06/15] api: Use same log err format everywhere in the file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julian Pelizäus (cherry picked from commit 424134be7989ef28285f1b83532485720935bfe7) --- api/status.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/status.go b/api/status.go index ca42c8ecb..6fc119ff1 100644 --- a/api/status.go +++ b/api/status.go @@ -50,7 +50,7 @@ func statusGet(sh *service.Handler) endpointHandler { err = cluster.Query(r.Context(), true, func(ctx context.Context, c *microClient.Client) error { memberStatuses, err := client.GetStatus(ctx, c) if err != nil { - logger.Error("Failed to get status for cluster member", logger.Ctx{"error": err, "address": c.URL()}) + logger.Error("Failed to get status for cluster member", logger.Ctx{"err": err, "address": c.URL()}) return nil } From 0303c252734e747958b16472f1a31d5b19cb05d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Peliz=C3=A4us?= Date: Thu, 13 Aug 2026 17:34:16 +0200 Subject: [PATCH 07/15] doc/reference/preseed: Move reference yaml file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julian Pelizäus (cherry picked from commit 5f98f1b3ac0a1e38ed8c621953552873fb46d7c6) --- doc/{how-to => reference}/preseed.yaml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename doc/{how-to => reference}/preseed.yaml (100%) diff --git a/doc/how-to/preseed.yaml b/doc/reference/preseed.yaml similarity index 100% rename from doc/how-to/preseed.yaml rename to doc/reference/preseed.yaml From 970a9cee58e8d50576a70211c86f0ea70bedfbd1 Mon Sep 17 00:00:00 2001 From: ggouzi Date: Thu, 13 Aug 2026 19:35:42 +0200 Subject: [PATCH 08/15] test/e2e/README: document the --report argument Signed-off-by: ggouzi (cherry picked from commit 399832d08734a98ab9d75f4255ba917411d61419) --- test/e2e/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/e2e/README.md b/test/e2e/README.md index 8973f5527..28b007fa2 100644 --- a/test/e2e/README.md +++ b/test/e2e/README.md @@ -105,3 +105,11 @@ EVACUATION_COUNTS=0 ./run mc # do multuple rolling reboots/evacuation tests: EVACUATION_COUNTS=5 ./run mc ``` + +### HTML report + +Passing `--report` to the `run` script will generate a brief HTML report upon completion (whether the tests pass or fail). The report file is created in the current directory. + +```sh +./run --report mc +``` From be659af2fb8d585abdf29f4e743101c5c97bb440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Peliz=C3=A4us?= Date: Fri, 14 Aug 2026 10:37:29 +0200 Subject: [PATCH 09/15] cmd/microcloud: Hide the --state-dir flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It used used by the snaps 'microcloud' wrapper command but never by the user directly. Signed-off-by: Julian Pelizäus (cherry picked from commit 79707eb12fddebb4efee66e00b0ad210edc3a8bc) --- cmd/microcloud/main.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmd/microcloud/main.go b/cmd/microcloud/main.go index 8d53f2bb5..72fa07774 100644 --- a/cmd/microcloud/main.go +++ b/cmd/microcloud/main.go @@ -62,6 +62,14 @@ func main() { app.SetVersionTemplate("{{.Version}}\n") + // Don't display the --state-dir flag in the help output. + // It is used by the snaps "microcloud" wrapper command but never by the user directly. + err = app.PersistentFlags().MarkHidden("state-dir") + if err != nil { + fmt.Fprintf(os.Stderr, "Cannot hide --state-dir flag: %v\n", err) + os.Exit(1) + } + var cmdInit = cmdInit{common: &commonCmd} app.AddCommand(cmdInit.command()) From fae2d11ad6d239debee1bd24920e7e4814bb9b28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Peliz=C3=A4us?= Date: Fri, 14 Aug 2026 10:52:09 +0200 Subject: [PATCH 10/15] cmd/microcloud: Consistently log errors to stderr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julian Pelizäus (cherry picked from commit 54018673b657399d6982ac6ef2b45e8392cf6236) --- cmd/microcloud/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/microcloud/main.go b/cmd/microcloud/main.go index 72fa07774..fa4853d43 100644 --- a/cmd/microcloud/main.go +++ b/cmd/microcloud/main.go @@ -37,7 +37,7 @@ func main() { asker, err := setupAsker(ctx) if err != nil { - fmt.Println(err.Error()) + fmt.Fprintf(os.Stderr, "Failed setting up asker: %v\n", err) os.Exit(1) } From 15e5622a49d6963d40e5b9575153f23649870ac1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Peliz=C3=A4us?= Date: Thu, 13 Aug 2026 17:35:36 +0200 Subject: [PATCH 11/15] doc/reference: Add preseed reference page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julian Pelizäus (cherry picked from commit 348c99a94ff9e9371e63b47664f580eca1d8b76c) --- doc/reference/index.md | 10 ++++ doc/reference/preseed.md | 100 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 doc/reference/preseed.md diff --git a/doc/reference/index.md b/doc/reference/index.md index cff299af6..69a92196d 100644 --- a/doc/reference/index.md +++ b/doc/reference/index.md @@ -19,6 +19,16 @@ Consult this command reference to work with MicroCloud through the CLI. /reference/commands ``` +## Preseed + +Consult this preseed reference for a detailed explanation of the various configuration options. + +```{toctree} +:maxdepth: 1 + +/reference/preseed +``` + ## Requirements and releases ```{toctree} diff --git a/doc/reference/preseed.md b/doc/reference/preseed.md new file mode 100644 index 000000000..78a35d9b5 --- /dev/null +++ b/doc/reference/preseed.md @@ -0,0 +1,100 @@ +(ref-preseed)= +# Preseed configuration options + +MicroCloud preseed allows the unattended (non-interactive) deployment of a cluster using a pre-configured file. +See below for detailed descriptions of the main building blocks of the file, followed by a {ref}`full configuration example ` file. + +(ref-preseed-filters)= +## Storage disk filters + +Explicitly setting the storage disks per system under `systems.[*].storage` is optional. +Use filters if the exact disk paths are unknown when crafting the preseed file. +This also makes the preseed file generic enough to be usable across various MicroCloud deployments. + +Filters allow MicroCloud to make a selection from a list of all disks available on the systems. +These filters correspond to the YAML field names of the disk resources returned from LXD's `/1.0/resources` endpoint. + +The following table lists all of the available filters: + +```{table} +:align: left + +| Filter | Example | +| ------------------ | ------------------------------------------- | +| `id` | `nvme0n1` | +| `device` | `259:0` | +| `model` | `` | +| `type` | `nvme` | +| `read_only` | `false` | +| `mounted` | `false` | +| `size` | `1024209543168` (size of the disk in bytes) | +| `removable` | `false` | +| `wwn` | `eui.00xxxxxxxxxxxxxx` | +| `numa_node` | `0` | +| `device_path` | `pci-0000:04:00.0-nvme-1` | +| `block_size` | `512` | +| `firmware_version` | `4L2XXXXX` | +| `rpm` | `0` | +| `serial` | `S7XKXXXXXXXXXX` | +| `device_id` | `nvme-eui.00xxxxxxxxxxxxxx` | +| `pci_address` | `0000:04:00.0` | +| `used_by` | `bcache` | +``` + +When using the `size` filter, its value can be compared against a user-defined number using byte suffixes in either units of 1000 or 1024: + +`B`, `kB`, `MB`, `GB`, `TB`, `EB`, `KiB`, `MiB`, `GiB`, `TiB`, `PiB`, `EiB` + +### Filter operands + +All filters can use the following operands to compare against defined values: + +`&&`, `||`, `<`, `>`, `<=`, `>=`, `==`, `!=`, `!` + +Furthermore the following restrictions apply: + +* Filters are checked in order of appearance +* String values must not be in quotes unless the string contains a space +* Single quotes are fine, but double quotes must be escaped + + +Multiple filters can be added to a single section: + +```yaml +storage: + ceph: + - find: + - find: +``` + +### Limit filtered disks + +In addition to finding disks by filter, the minimum and maximum number of disks can also be specified. +For this, the `find_min` and `find_max` settings can be added to the relevant section: + +```yaml +storage: + ceph: + - find: + find_min: 1 + find_max: 2 +``` + +The example above will make sure that the filters select at least one, but not more than two, disks for remote (Ceph) storage. + +```{note} +For local storage there can only ever be one disk per system. +If the filters return more than one disk, only one of them will be used. + +For remote storage the filters apply for all disks across all systems. +``` + +(ref-preseed-full-configuration-example)= +## Full configuration example + +The preseed YAML file must use the following syntax: + +```{literalinclude} preseed.yaml +:language: YAML +:emphasize-lines: 1-4,7-10,13-14,17-19,22,25-27,30-35,63-66,72,79-88 +``` From cad8a4e528963e184acc62d544bcd1133b5dbeae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Peliz=C3=A4us?= Date: Thu, 13 Aug 2026 17:35:00 +0200 Subject: [PATCH 12/15] doc/how-to: Refer to preseed reference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julian Pelizäus (cherry picked from commit 465a871e98f7a6b14102b33ad8494cebc74dd9d5) --- doc/how-to/initialize.md | 8 +------- doc/how-to/member_add.md | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/doc/how-to/initialize.md b/doc/how-to/initialize.md index 9c9076ef7..46b303c73 100644 --- a/doc/how-to/initialize.md +++ b/doc/how-to/initialize.md @@ -182,13 +182,7 @@ If you want to automate the initialization process, you can provide a preseed co cat | microcloud preseed Make sure to distribute and run the same preseed configuration on all systems that should be part of the MicroCloud. - -The preseed YAML file must use the following syntax: - -```{literalinclude} preseed.yaml -:language: YAML -:emphasize-lines: 1-4,7-10,13-14,17-19,22,25-27,30-35,63-66,72,79-87 -``` +See the {ref}`full reference ` for possible configuration options or the minimal example below. ### Minimal preseed using multicast discovery diff --git a/doc/how-to/member_add.md b/doc/how-to/member_add.md index 50532ed36..56b8c2225 100644 --- a/doc/how-to/member_add.md +++ b/doc/how-to/member_add.md @@ -31,13 +31,7 @@ In the list of systems, include only the new machine and set either `initiator` that is already part of the MicroCloud. Distribute and run the same preseed configuration on both the machine being added, and the cluster member used for the `initiator` or `initiator_address`. - -The preseed YAML file must use the following syntax: - -```{literalinclude} preseed.yaml -:language: YAML -:emphasize-lines: 1-4,7-10,13-14,17-19,22,25-27,30-35,63-66,72,79-88 -``` +See the {ref}`full reference ` for possible configuration options or the minimal example below. ### Minimal preseed using multicast discovery From d1f96f9bd8e9813d0d673af76eeb00732591a08f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Peliz=C3=A4us?= Date: Thu, 13 Aug 2026 17:35:58 +0200 Subject: [PATCH 13/15] doc/how-to/initialize: Add preseed filter how-to MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julian Pelizäus (cherry picked from commit 6ccd3d71314f7728c26a5b0d46e610a8c926c2b0) --- doc/how-to/initialize.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/doc/how-to/initialize.md b/doc/how-to/initialize.md index 46b303c73..9dc1881c7 100644 --- a/doc/how-to/initialize.md +++ b/doc/how-to/initialize.md @@ -233,6 +233,40 @@ ovn: If you initialized MicroCloud without local storage _and_ with CephFS storage, continue to the section below to complete your initialization. ``` +### Use storage disk filters + +You may not know the exact disk paths used for local and remote storage when crafting the preseed file. +In such cases, you can add disk filters for local and remote storage configuration. +By using those filters, you can narrow down the list of available disks to the ones eligible based on the given rules. + +For example you might want to use all disks for local storage which are of type `nvme` and use a model description ``: + +```yaml +storage: + local: + - find: type == nvme && model == "" +``` + +As another example, you can filter for remote (Ceph) storage disks with size greater than 1TiB and model description ``, and ensure there are at least six disks (maximum eight) selected across all members: + +```yaml +storage: + ceph: + - find: size > 1TiB && model == "" + find_min: 6 + find_max: 8 +``` + +See the {ref}`list of filters ` for a full reference. + +```{admonition} Finding the right filters +:class: note +If you want to see the actual filter values for your system(s) for further refinement of the preseed file, you can run `lxc query /1.0/resources | jq .storage.disks` on any of the MicroCloud members prior to initialization. + +The response will show all the disks available to MicroCloud on this member. +Repeat the command on every member for a full list of disks across the cluster. +``` + (howto-initialize-images-backups)= ## Configure `backups_volume` and `images_volume` From f19055ec40ebab00089a38b3f3388d41f945040e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Peliz=C3=A4us?= Date: Tue, 18 Aug 2026 09:47:07 +0200 Subject: [PATCH 14/15] cmd/microcloud/init: Set OVN connection string only if necessary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Starting the with the ovn_dynamic_northbound_connection API extension in LXD, we don't anymore have to manually set the OVN northbound DB connection string. This also has the benefit that in case it requires a change, LXD always picks up the latest info from file setup by MicroOVN. Signed-off-by: Julian Pelizäus (cherry picked from commit 33743b5b3e0831fc0d543f5821465c352b55152a) --- cmd/microcloud/main_init.go | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/cmd/microcloud/main_init.go b/cmd/microcloud/main_init.go index fc4b87588..c576cac31 100644 --- a/cmd/microcloud/main_init.go +++ b/cmd/microcloud/main_init.go @@ -885,8 +885,18 @@ func (c *initConfig) setupCluster(s *service.Handler) error { fmt.Println("Configuring cluster-wide devices ...") - var ovnConfig string - if s.Services[types.MicroOVN] != nil { + // Update LXD's global config. + server, _, err := lxdClient.GetServer() + if err != nil { + return err + } + + config := make(map[string]string) + + // LXD can dynamically determine the OVN northbound DB connection string from MicroOVN's `ovn.env` file. + // This feature was added with the ovn_dynamic_northbound_connection API extension. + // Only set the connection string in case of an older LXD. + if s.Services[types.MicroOVN] != nil && !lxdClient.HasExtension("ovn_dynamic_northbound_connection") { serviceOVN := s.Services[types.MicroOVN].(*service.OVNService) services, err := serviceOVN.GetServices(context.Background()) @@ -911,14 +921,7 @@ func (c *initConfig) setupCluster(s *service.Handler) error { } } - ovnConfig = strings.Join(conns, ",") - } - - config := map[string]string{"network.ovn.northbound_connection": ovnConfig} - // Update LXD's global config. - server, _, err := lxdClient.GetServer() - if err != nil { - return err + config["network.ovn.northbound_connection"] = strings.Join(conns, ",") } newServer := server.Writable() From 2d2a488667a8b1aa8c9080b64be0e9335c8c5678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Peliz=C3=A4us?= Date: Tue, 18 Aug 2026 09:53:35 +0200 Subject: [PATCH 15/15] test/includes/microcloud: Update OVN validation check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julian Pelizäus (cherry picked from commit 02c5c1f041fad1d66cd60256fd1bfc81af2a278d) --- test/includes/microcloud.sh | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/test/includes/microcloud.sh b/test/includes/microcloud.sh index 401f8c595..99ac9cd59 100644 --- a/test/includes/microcloud.sh +++ b/test/includes/microcloud.sh @@ -550,16 +550,19 @@ validate_system_lxd_ovn() { echo " ${name} Validating OVN network" - num_conns=3 - if [ "${num_peers}" -lt "${num_conns}" ]; then - num_conns="${num_peers}" - fi + # Check if the connection string is set correctly. + if ! check_api_extension ovn_dynamic_northbound_connection "${name}"; then + num_conns=3 + if [ "${num_peers}" -lt "${num_conns}" ]; then + num_conns="${num_peers}" + fi - [ "$(lxc config get network.ovn.northbound_connection --target "${name}" | sed -e 's/,/\n/g' | wc -l)" = "${num_conns}" ] + [ "$(lxc config get network.ovn.northbound_connection --target "${name}" | sed -e 's/,/\n/g' | wc -l)" = "${num_conns}" ] - # Make sure there's no empty addresses. - ! lxc config get network.ovn.northbound_connection --target "${name}" | sed -e 's/,/\n/g' | grep -q '^ssl:$' || false - ! lxc config get network.ovn.northbound_connection --target "${name}" | sed -e 's/,/\n/g' | grep -q '^ssl::' || false + # Make sure there's no empty addresses. + ! lxc config get network.ovn.northbound_connection --target "${name}" | sed -e 's/,/\n/g' | grep -q '^ssl:$' || false + ! lxc config get network.ovn.northbound_connection --target "${name}" | sed -e 's/,/\n/g' | grep -q '^ssl::' || false + fi # Check that the created UPLINK network has the right DNS servers. if [ -n "${dns_namesersers}" ] ; then