From 6b2a89080a398c311dd14eab67b6f87f65533a1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Peliz=C3=A4us?= Date: Fri, 4 Jul 2025 10:31:54 +0200 Subject: [PATCH 1/4] cmd/microcloud: Require either IPv4 or IPv6 gateway on uplink MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not configuring the gateway on the uplink configures an OVN network without external connectivity. Whilst that might be a valid use case, currently this is not really supported in LXD as you have to provide an uplink network even though it's not used. Until this is supported in LXD, we simply don't allow this type of configuration. Signed-off-by: Julian Pelizäus --- cmd/microcloud/ask.go | 52 +++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/cmd/microcloud/ask.go b/cmd/microcloud/ask.go index e38339251..196678d54 100644 --- a/cmd/microcloud/ask.go +++ b/cmd/microcloud/ask.go @@ -1042,47 +1042,51 @@ func (c *initConfig) askOVNNetwork(sh *service.Handler) error { return nil } - msg := fmt.Sprintf("Specify the %s gateway (CIDR) on the uplink network (empty to skip %s)", ip, ip) + msg := fmt.Sprintf("Specify the %s gateway (CIDR) on the uplink network", ip) gateway, err := c.asker.AskString(msg, "", validator) if err != nil { return err } - if gateway != "" { - if ip == "IPv4" { - rangeStart, err := c.asker.AskString(fmt.Sprintf("Specify the first %s address in the range to use on the uplink network", ip), "", validate.Required(validate.IsNetworkAddressV4)) - if err != nil { - return err - } - - rangeEnd, err := c.asker.AskString(fmt.Sprintf("Specify the last %s address in the range to use on the uplink network", ip), "", validate.Required(validate.IsNetworkAddressV4)) - if err != nil { - return err - } + if gateway == "" { + continue + } - ipConfig[gateway] = fmt.Sprintf("%s-%s", rangeStart, rangeEnd) - } else { - ipConfig[gateway] = "" + if ip == "IPv4" { + rangeStart, err := c.asker.AskString(fmt.Sprintf("Specify the first %s address in the range to use on the uplink network", ip), "", validate.Required(validate.IsNetworkAddressV4)) + if err != nil { + return err } - } - } - if len(ipConfig) > 0 { - gateways := []string{} - for gateway := range ipConfig { - gatewayAddr, _, err := net.ParseCIDR(gateway) + rangeEnd, err := c.asker.AskString(fmt.Sprintf("Specify the last %s address in the range to use on the uplink network", ip), "", validate.Required(validate.IsNetworkAddressV4)) if err != nil { return err } - gateways = append(gateways, gatewayAddr.String()) + ipConfig[gateway] = fmt.Sprintf("%s-%s", rangeStart, rangeEnd) + } else { + ipConfig[gateway] = "" } + } + + if len(ipConfig) == 0 { + return errors.New("Either the IPv4 or IPv6 gateway has to be set on the uplink network") + } - gatewayAddrs := strings.Join(gateways, ",") - dnsAddresses, err = c.asker.AskString("Specify the DNS addresses (comma-separated IPv4 / IPv6 addresses) for the distributed network", gatewayAddrs, validate.Optional(validate.IsListOf(validate.IsNetworkAddress))) + gateways := []string{} + for gateway := range ipConfig { + gatewayAddr, _, err := net.ParseCIDR(gateway) if err != nil { return err } + + gateways = append(gateways, gatewayAddr.String()) + } + + gatewayAddrs := strings.Join(gateways, ",") + dnsAddresses, err = c.asker.AskString("Specify the DNS addresses (comma-separated IPv4 / IPv6 addresses) for the distributed network", gatewayAddrs, validate.Optional(validate.IsListOf(validate.IsNetworkAddress))) + if err != nil { + return err } } From 34aeec89aa7e3b0dcda3124e0a28a5e9905a53cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Peliz=C3=A4us?= Date: Fri, 4 Jul 2025 10:55:22 +0200 Subject: [PATCH 2/4] cmd/microcloud: Require either IPv4 or IPv6 gateway on uplink (preseed) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julian Pelizäus --- cmd/microcloud/preseed.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd/microcloud/preseed.go b/cmd/microcloud/preseed.go index 253e1137c..6e8837668 100644 --- a/cmd/microcloud/preseed.go +++ b/cmd/microcloud/preseed.go @@ -366,6 +366,10 @@ func (p *Preseed) validate(name string, bootstrap bool) error { if system.UplinkInterface != "" { uplinkCount++ + + if p.OVN.IPv4Gateway == "" && p.OVN.IPv6Gateway == "" && bootstrap { + return errors.New("Either the IPv4 or IPv6 gateway has to be set on the uplink network") + } } if system.UnderlayIP != "" { From dcc19fbb55c48d8ba1a0ad437de47387df652a35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Peliz=C3=A4us?= Date: Fri, 4 Jul 2025 10:39:21 +0200 Subject: [PATCH 3/4] cmd/tui: Allow forwarding an invalid input's error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case the asker is using a validator, make sure it's error message can be displayed to the user. Signed-off-by: Julian Pelizäus --- cmd/tui/handler.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/cmd/tui/handler.go b/cmd/tui/handler.go index 01df497c3..8bcf27838 100644 --- a/cmd/tui/handler.go +++ b/cmd/tui/handler.go @@ -15,7 +15,15 @@ import ( var ContextError error = tea.ErrProgramKilled // InvalidInputError is used to indicate false input to an asked question. -var InvalidInputError func() = func() { PrintError("Invalid input, try again") } +var InvalidInputError func(err error) = func(err error) { + errorMsg := "Invalid input, try again" + + if err != nil { + PrintError(fmt.Sprintf("%s: %s", errorMsg, err.Error())) + } else { + PrintError(errorMsg) + } +} // InputHandler handles input dialogs. type InputHandler struct { @@ -121,7 +129,7 @@ func (i *InputHandler) AskBool(question string, defaultAnswer bool) (bool, error return false, nil } - InvalidInputError() + InvalidInputError(nil) } } @@ -145,7 +153,7 @@ func (i *InputHandler) AskString(question string, defaultAnswer string, validato if validator != nil { err = validator(answer) if err != nil { - InvalidInputError() + InvalidInputError(err) continue } @@ -156,6 +164,6 @@ func (i *InputHandler) AskString(question string, defaultAnswer string, validato return answer, err } - InvalidInputError() + InvalidInputError(nil) } } From b915432dbc3c8064fceb5ee634926728d9156434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Peliz=C3=A4us?= Date: Fri, 4 Jul 2025 11:33:23 +0200 Subject: [PATCH 4/4] test/suites/instances: Add missing OVN uplink gateway MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julian Pelizäus --- test/suites/instances.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/suites/instances.sh b/test/suites/instances.sh index 2b71b0586..547a19689 100644 --- a/test/suites/instances.sh +++ b/test/suites/instances.sh @@ -187,6 +187,10 @@ systems: local: path: /dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_lxd_disk1 wipe: true +ovn: + ipv4_gateway: 10.1.123.1/24 + ipv4_range: 10.1.123.100-10.1.123.254 + ipv6_gateway: fd42:1:1234:1234::1/64 EOF )"