[lxc-devel] [lxd/master] Network: OVN uplink terminology
tomponline on Github
lxc-bot at linuxcontainers.org
Tue Oct 13 12:43:17 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 489 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20201013/e65e1ae1/attachment-0001.bin>
-------------- next part --------------
From 5d8ced58e9b060ef3638237f3b6ffeb150c65c23 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 9 Oct 2020 09:38:36 +0100
Subject: [PATCH 1/8] shared/validate/validate: Removes inaccurate comments
about optional values
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
shared/validate/validate.go | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/shared/validate/validate.go b/shared/validate/validate.go
index 10067d8c26..92939c4e39 100644
--- a/shared/validate/validate.go
+++ b/shared/validate/validate.go
@@ -161,7 +161,7 @@ func IsNetworkMAC(value string) error {
return nil
}
-// IsNetworkAddress validates an IP (v4 or v6) address string. If string is empty, returns valid.
+// IsNetworkAddress validates an IP (v4 or v6) address string.
func IsNetworkAddress(value string) error {
ip := net.ParseIP(value)
if ip == nil {
@@ -184,7 +184,7 @@ func IsNetworkAddressList(value string) error {
return nil
}
-// IsNetworkV4 validates an IPv4 CIDR string. If string is empty, returns valid.
+// IsNetworkV4 validates an IPv4 CIDR string.
func IsNetworkV4(value string) error {
ip, subnet, err := net.ParseCIDR(value)
if err != nil {
@@ -202,7 +202,7 @@ func IsNetworkV4(value string) error {
return nil
}
-// IsNetworkAddressV4 validates an IPv4 addresss string. If string is empty, returns valid.
+// IsNetworkAddressV4 validates an IPv4 addresss string.
func IsNetworkAddressV4(value string) error {
ip := net.ParseIP(value)
if ip == nil || ip.To4() == nil {
@@ -212,7 +212,7 @@ func IsNetworkAddressV4(value string) error {
return nil
}
-// IsNetworkAddressCIDRV4 validates an IPv4 addresss string in CIDR format. If string is empty, returns valid.
+// IsNetworkAddressCIDRV4 validates an IPv4 addresss string in CIDR format.
func IsNetworkAddressCIDRV4(value string) error {
ip, subnet, err := net.ParseCIDR(value)
if err != nil {
@@ -256,7 +256,7 @@ func IsNetworkV4List(value string) error {
return nil
}
-// IsNetworkV6 validates an IPv6 CIDR string. If string is empty, returns valid.
+// IsNetworkV6 validates an IPv6 CIDR string.
func IsNetworkV6(value string) error {
ip, subnet, err := net.ParseCIDR(value)
if err != nil {
@@ -274,7 +274,7 @@ func IsNetworkV6(value string) error {
return nil
}
-// IsNetworkAddressV6 validates an IPv6 addresss string. If string is empty, returns valid.
+// IsNetworkAddressV6 validates an IPv6 addresss string.
func IsNetworkAddressV6(value string) error {
ip := net.ParseIP(value)
if ip == nil || ip.To4() != nil {
@@ -284,7 +284,7 @@ func IsNetworkAddressV6(value string) error {
return nil
}
-// IsNetworkAddressCIDRV6 validates an IPv6 addresss string in CIDR format. If string is empty, returns valid.
+// IsNetworkAddressCIDRV6 validates an IPv6 addresss string in CIDR format.
func IsNetworkAddressCIDRV6(value string) error {
ip, subnet, err := net.ParseCIDR(value)
if err != nil {
From 6bc696e845f1e50f717363cb9b9191320452952a Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 9 Oct 2020 09:39:08 +0100
Subject: [PATCH 2/8] shared/validate/validate: Adds IsNetwork and
IsNetworkList functions
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
shared/validate/validate.go | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/shared/validate/validate.go b/shared/validate/validate.go
index 92939c4e39..3978ad5a80 100644
--- a/shared/validate/validate.go
+++ b/shared/validate/validate.go
@@ -184,6 +184,32 @@ func IsNetworkAddressList(value string) error {
return nil
}
+// IsNetwork validates an IP network CIDR string.
+func IsNetwork(value string) error {
+ ip, subnet, err := net.ParseCIDR(value)
+ if err != nil {
+ return err
+ }
+
+ if ip.String() != subnet.IP.String() {
+ return fmt.Errorf("Not an IP network address %q", value)
+ }
+
+ return nil
+}
+
+// IsNetworkList validates a comma delimited list of IP network CIDR strings.
+func IsNetworkList(value string) error {
+ for _, network := range strings.Split(value, ",") {
+ err := IsNetwork(strings.TrimSpace(network))
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
// IsNetworkV4 validates an IPv4 CIDR string.
func IsNetworkV4(value string) error {
ip, subnet, err := net.ParseCIDR(value)
From 654413bedc13dd4f2d48d886fe5855f9ca395aaf Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 9 Oct 2020 09:41:09 +0100
Subject: [PATCH 3/8] shared/validate/validate: Re-orders IP validation
functions
So that IP family functions are together and in logical order (single item validator before list validators).
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
shared/validate/validate.go | 120 ++++++++++++++++++------------------
1 file changed, 60 insertions(+), 60 deletions(-)
diff --git a/shared/validate/validate.go b/shared/validate/validate.go
index 3978ad5a80..2a84a2bf3e 100644
--- a/shared/validate/validate.go
+++ b/shared/validate/validate.go
@@ -228,6 +228,19 @@ func IsNetworkV4(value string) error {
return nil
}
+// IsNetworkV4List validates a comma delimited list of IPv4 CIDR strings.
+func IsNetworkV4List(value string) error {
+ for _, network := range strings.Split(value, ",") {
+ network = strings.TrimSpace(network)
+ err := IsNetworkV4(network)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
// IsNetworkAddressV4 validates an IPv4 addresss string.
func IsNetworkAddressV4(value string) error {
ip := net.ParseIP(value)
@@ -238,6 +251,19 @@ func IsNetworkAddressV4(value string) error {
return nil
}
+// IsNetworkAddressV4List validates a comma delimited list of IPv4 addresses.
+func IsNetworkAddressV4List(value string) error {
+ for _, v := range strings.Split(value, ",") {
+ v = strings.TrimSpace(v)
+ err := IsNetworkAddressV4(v)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
// IsNetworkAddressCIDRV4 validates an IPv4 addresss string in CIDR format.
func IsNetworkAddressCIDRV4(value string) error {
ip, subnet, err := net.ParseCIDR(value)
@@ -256,11 +282,15 @@ func IsNetworkAddressCIDRV4(value string) error {
return nil
}
-// IsNetworkAddressV4List validates a comma delimited list of IPv4 addresses.
-func IsNetworkAddressV4List(value string) error {
- for _, v := range strings.Split(value, ",") {
- v = strings.TrimSpace(v)
- err := IsNetworkAddressV4(v)
+// IsNetworkRangeV4 validates an IPv4 range in the format "start-end".
+func IsNetworkRangeV4(value string) error {
+ ips := strings.SplitN(value, "-", 2)
+ if len(ips) != 2 {
+ return fmt.Errorf("IP range must contain start and end IP addresses")
+ }
+
+ for _, ip := range ips {
+ err := IsNetworkAddressV4(ip)
if err != nil {
return err
}
@@ -269,11 +299,10 @@ func IsNetworkAddressV4List(value string) error {
return nil
}
-// IsNetworkV4List validates a comma delimited list of IPv4 CIDR strings.
-func IsNetworkV4List(value string) error {
- for _, network := range strings.Split(value, ",") {
- network = strings.TrimSpace(network)
- err := IsNetworkV4(network)
+// IsNetworkRangeV4List validates a comma delimited list of IPv4 ranges.
+func IsNetworkRangeV4List(value string) error {
+ for _, ipRange := range strings.Split(value, ",") {
+ err := IsNetworkRangeV4(strings.TrimSpace(ipRange))
if err != nil {
return err
}
@@ -300,31 +329,26 @@ func IsNetworkV6(value string) error {
return nil
}
-// IsNetworkAddressV6 validates an IPv6 addresss string.
-func IsNetworkAddressV6(value string) error {
- ip := net.ParseIP(value)
- if ip == nil || ip.To4() != nil {
- return fmt.Errorf("Not an IPv6 address %q", value)
+// IsNetworkV6List validates a comma delimited list of IPv6 CIDR strings.
+func IsNetworkV6List(value string) error {
+ for _, network := range strings.Split(value, ",") {
+ network = strings.TrimSpace(network)
+ err := IsNetworkV6(network)
+ if err != nil {
+ return err
+ }
}
return nil
}
-// IsNetworkAddressCIDRV6 validates an IPv6 addresss string in CIDR format.
-func IsNetworkAddressCIDRV6(value string) error {
- ip, subnet, err := net.ParseCIDR(value)
- if err != nil {
- return err
- }
-
- if ip.To4() != nil {
+// IsNetworkAddressV6 validates an IPv6 addresss string.
+func IsNetworkAddressV6(value string) error {
+ ip := net.ParseIP(value)
+ if ip == nil || ip.To4() != nil {
return fmt.Errorf("Not an IPv6 address %q", value)
}
- if ip.String() == subnet.IP.String() {
- return fmt.Errorf("Not a usable IPv6 address %q", value)
- }
-
return nil
}
@@ -340,43 +364,19 @@ func IsNetworkAddressV6List(value string) error {
return nil
}
-// IsNetworkV6List validates a comma delimited list of IPv6 CIDR strings.
-func IsNetworkV6List(value string) error {
- for _, network := range strings.Split(value, ",") {
- network = strings.TrimSpace(network)
- err := IsNetworkV6(network)
- if err != nil {
- return err
- }
- }
-
- return nil
-}
-
-// IsNetworkRangeV4 validates an IPv4 range in the format "start-end".
-func IsNetworkRangeV4(value string) error {
- ips := strings.SplitN(value, "-", 2)
- if len(ips) != 2 {
- return fmt.Errorf("IP range must contain start and end IP addresses")
+// IsNetworkAddressCIDRV6 validates an IPv6 addresss string in CIDR format.
+func IsNetworkAddressCIDRV6(value string) error {
+ ip, subnet, err := net.ParseCIDR(value)
+ if err != nil {
+ return err
}
- for _, ip := range ips {
- err := IsNetworkAddressV4(ip)
- if err != nil {
- return err
- }
+ if ip.To4() != nil {
+ return fmt.Errorf("Not an IPv6 address %q", value)
}
- return nil
-}
-
-// IsNetworkRangeV4List validates a comma delimited list of IPv4 ranges.
-func IsNetworkRangeV4List(value string) error {
- for _, ipRange := range strings.Split(value, ",") {
- err := IsNetworkRangeV4(strings.TrimSpace(ipRange))
- if err != nil {
- return err
- }
+ if ip.String() == subnet.IP.String() {
+ return fmt.Errorf("Not a usable IPv6 address %q", value)
}
return nil
From 7a900762a1978b06297a1870514337de45f77cef Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 9 Oct 2020 10:14:08 +0100
Subject: [PATCH 4/8] lxd/device/nic/ovn: Comment
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/device/nic_ovn.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lxd/device/nic_ovn.go b/lxd/device/nic_ovn.go
index 71c77419d8..e499c7cf90 100644
--- a/lxd/device/nic_ovn.go
+++ b/lxd/device/nic_ovn.go
@@ -26,7 +26,7 @@ import (
type nicOVN struct {
deviceCommon
- network network.Network
+ network network.Network // Populated in validateConfig().
}
// getIntegrationBridgeName returns the OVS integration bridge to use.
From c34ee20298981bedd5d392dad010907e5001a218 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 9 Oct 2020 10:29:29 +0100
Subject: [PATCH 5/8] doc/api-extensions: Removes mention of "parent" from
projects_networks_restricted_uplinks feature
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
doc/api-extensions.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index bc3ee9e2d2..a2688afac2 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -1157,7 +1157,7 @@ Adds the `features.networks` config key to projects and the ability for a projec
## projects\_networks\_restricted\_uplinks
Adds the `restricted.networks.uplinks` project config key to indicate (as a comma delimited list) which networks
-the networks created inside the project can use as their uplink parent network.
+the networks created inside the project can use as their uplink network.
## custom\_volume\_backup
Add custom volume backup support.
From 1b2dc8eba3c670b5794af94fad0226668bc95cf3 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 9 Oct 2020 10:29:55 +0100
Subject: [PATCH 6/8] doc/networks: Switch to "uplink" terminology for external
OVN network access
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
doc/networks.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/doc/networks.md b/doc/networks.md
index 6df04b13c4..cc63de9c11 100644
--- a/doc/networks.md
+++ b/doc/networks.md
@@ -299,7 +299,7 @@ dns.search | string | - | -
ipv4.address | string | standard mode | random unused subnet | IPv4 address for the bridge (CIDR notation). Use "none" to turn off IPv4 or "auto" to generate a new one
ipv6.address | string | standard mode | random unused subnet | IPv6 address for the bridge (CIDR notation). Use "none" to turn off IPv6 or "auto" to generate a new one
ipv6.dhcp.stateful | boolean | ipv6 dhcp | false | Whether to allocate addresses using DHCP
-network | string | - | - | Parent network to use for outbound external network access
+network | string | - | - | Uplink network to use for external network access
## network: physical
From 6085a3da6a9ee8fb27b4e56fdd788165954b5b57 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 9 Oct 2020 10:30:21 +0100
Subject: [PATCH 7/8] lxd/network/driver/ovn: Replace parent terminology with
uplink
Now that "uplink" concept is formalised in `restricted.networks.uplinks` we should use consistent terminilogy in code.
Also "parent" concept is different and used for other meanings, so re-using when talking about uplink is confusing.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/driver_ovn.go | 400 +++++++++++++++++++-------------------
1 file changed, 200 insertions(+), 200 deletions(-)
diff --git a/lxd/network/driver_ovn.go b/lxd/network/driver_ovn.go
index 7387f10270..ca3373c9f4 100644
--- a/lxd/network/driver_ovn.go
+++ b/lxd/network/driver_ovn.go
@@ -29,11 +29,11 @@ import (
)
const ovnChassisPriorityMax = 32767
-const ovnVolatileParentIPv4 = "volatile.network.ipv4.address"
-const ovnVolatileParentIPv6 = "volatile.network.ipv6.address"
+const ovnVolatileUplinkIPv4 = "volatile.network.ipv4.address"
+const ovnVolatileUplinkIPv6 = "volatile.network.ipv6.address"
-// ovnParentVars OVN object variables derived from parent network.
-type ovnParentVars struct {
+// ovnUplinkVars OVN object variables derived from uplink network.
+type ovnUplinkVars struct {
// Router.
routerExtPortIPv4Net string
routerExtPortIPv6Net string
@@ -48,10 +48,10 @@ type ovnParentVars struct {
dnsIPv4 []net.IP
}
-// ovnParentPortBridgeVars parent bridge port variables used for start/stop.
-type ovnParentPortBridgeVars struct {
+// ovnUplinkPortBridgeVars uplink bridge port variables used for start/stop.
+type ovnUplinkPortBridgeVars struct {
ovsBridge string
- parentEnd string
+ uplinkEnd string
ovsEnd string
}
@@ -103,8 +103,8 @@ func (n *ovn) Validate(config map[string]string) error {
"dns.search": validate.IsAny,
// Volatile keys populated automatically as needed.
- ovnVolatileParentIPv4: validate.Optional(validate.IsNetworkAddressV4),
- ovnVolatileParentIPv6: validate.Optional(validate.IsNetworkAddressV6),
+ ovnVolatileUplinkIPv4: validate.Optional(validate.IsNetworkAddressV4),
+ ovnVolatileUplinkIPv6: validate.Optional(validate.IsNetworkAddressV6),
}
err := n.validate(config, rules)
@@ -351,102 +351,102 @@ func (n *ovn) getIntSwitchInstancePortPrefix() string {
return fmt.Sprintf("%s-instance", n.getNetworkPrefix())
}
-// setupParentPort initialises the parent uplink connection. Returns the derived ovnParentVars settings used
+// setupUplinkPort initialises the uplink connection. Returns the derived ovnUplinkVars settings used
// during the initial creation of the logical network.
-func (n *ovn) setupParentPort(routerMAC net.HardwareAddr) (*ovnParentVars, error) {
- // Parent network must be in default project.
- parentNet, err := LoadByName(n.state, project.Default, n.config["network"])
+func (n *ovn) setupUplinkPort(routerMAC net.HardwareAddr) (*ovnUplinkVars, error) {
+ // Uplink network must be in default project.
+ uplinkNet, err := LoadByName(n.state, project.Default, n.config["network"])
if err != nil {
- return nil, errors.Wrapf(err, "Failed loading parent network %q", n.config["network"])
+ return nil, errors.Wrapf(err, "Failed loading uplink network %q", n.config["network"])
}
- switch parentNet.Type() {
+ switch uplinkNet.Type() {
case "bridge":
- return n.setupParentPortBridge(parentNet, routerMAC)
+ return n.setupUplinkPortBridge(uplinkNet, routerMAC)
case "physical":
- return n.setupParentPortPhysical(parentNet, routerMAC)
+ return n.setupUplinkPortPhysical(uplinkNet, routerMAC)
}
- return nil, fmt.Errorf("Failed setting up parent port, network type %q unsupported as OVN parent", parentNet.Type())
+ return nil, fmt.Errorf("Failed setting up uplink port, network type %q unsupported as OVN uplink", uplinkNet.Type())
}
-// setupParentPortBridge allocates external IPs on the parent bridge.
-// Returns the derived ovnParentVars settings.
-func (n *ovn) setupParentPortBridge(parentNet Network, routerMAC net.HardwareAddr) (*ovnParentVars, error) {
- bridgeNet, ok := parentNet.(*bridge)
+// setupUplinkPortBridge allocates external IPs on the uplink bridge.
+// Returns the derived ovnUplinkVars settings.
+func (n *ovn) setupUplinkPortBridge(uplinkNet Network, routerMAC net.HardwareAddr) (*ovnUplinkVars, error) {
+ bridgeNet, ok := uplinkNet.(*bridge)
if !ok {
return nil, fmt.Errorf("Network is not bridge type")
}
err := bridgeNet.checkClusterWideMACSafe(bridgeNet.config)
if err != nil {
- return nil, errors.Wrapf(err, "Network %q is not suitable for use as OVN parent", bridgeNet.name)
+ return nil, errors.Wrapf(err, "Network %q is not suitable for use as OVN uplink", bridgeNet.name)
}
- v, err := n.allocateParentPortIPs(parentNet, routerMAC)
+ v, err := n.allocateUplinkPortIPs(uplinkNet, routerMAC)
if err != nil {
- return nil, errors.Wrapf(err, "Failed allocating parent port IPs on network %q", parentNet.Name())
+ return nil, errors.Wrapf(err, "Failed allocating uplink port IPs on network %q", uplinkNet.Name())
}
return v, nil
}
-// setupParentPortPhysical allocates external IPs on the parent network.
-// Returns the derived ovnParentVars settings.
-func (n *ovn) setupParentPortPhysical(parentNet Network, routerMAC net.HardwareAddr) (*ovnParentVars, error) {
- v, err := n.allocateParentPortIPs(parentNet, routerMAC)
+// setupUplinkPortPhysical allocates external IPs on the uplink network.
+// Returns the derived ovnUplinkVars settings.
+func (n *ovn) setupUplinkPortPhysical(uplinkNet Network, routerMAC net.HardwareAddr) (*ovnUplinkVars, error) {
+ v, err := n.allocateUplinkPortIPs(uplinkNet, routerMAC)
if err != nil {
- return nil, errors.Wrapf(err, "Failed allocating parent port IPs on network %q", parentNet.Name())
+ return nil, errors.Wrapf(err, "Failed allocating uplink port IPs on network %q", uplinkNet.Name())
}
return v, nil
}
-// allocateParentPortIPs attempts to find a free IP in the parent network's OVN ranges and then stores it in
-// ovnVolatileParentIPv4 and ovnVolatileParentIPv6 config keys on this network. Returns ovnParentVars settings.
-func (n *ovn) allocateParentPortIPs(parentNet Network, routerMAC net.HardwareAddr) (*ovnParentVars, error) {
- v := &ovnParentVars{}
+// allocateUplinkPortIPs attempts to find a free IP in the uplink network's OVN ranges and then stores it in
+// ovnVolatileUplinkIPv4 and ovnVolatileUplinkIPv6 config keys on this network. Returns ovnUplinkVars settings.
+func (n *ovn) allocateUplinkPortIPs(uplinkNet Network, routerMAC net.HardwareAddr) (*ovnUplinkVars, error) {
+ v := &ovnUplinkVars{}
- parentNetConf := parentNet.Config()
+ uplinkNetConf := uplinkNet.Config()
- // Parent derived settings.
- v.extSwitchProviderName = parentNet.Name()
+ // Uplink derived settings.
+ v.extSwitchProviderName = uplinkNet.Name()
- // Detect parent gateway setting.
- parentIPv4CIDR := parentNetConf["ipv4.address"]
- if parentIPv4CIDR == "" {
- parentIPv4CIDR = parentNetConf["ipv4.gateway"]
+ // Detect uplink gateway setting.
+ uplinkIPv4CIDR := uplinkNetConf["ipv4.address"]
+ if uplinkIPv4CIDR == "" {
+ uplinkIPv4CIDR = uplinkNetConf["ipv4.gateway"]
}
- parentIPv6CIDR := parentNetConf["ipv6.address"]
- if parentIPv6CIDR == "" {
- parentIPv6CIDR = parentNetConf["ipv6.gateway"]
+ uplinkIPv6CIDR := uplinkNetConf["ipv6.address"]
+ if uplinkIPv6CIDR == "" {
+ uplinkIPv6CIDR = uplinkNetConf["ipv6.gateway"]
}
- // Optional parent values.
- parentIPv4, parentIPv4Net, err := net.ParseCIDR(parentIPv4CIDR)
+ // Optional uplink values.
+ uplinkIPv4, uplinkIPv4Net, err := net.ParseCIDR(uplinkIPv4CIDR)
if err == nil {
- v.dnsIPv4 = []net.IP{parentIPv4}
- v.routerExtGwIPv4 = parentIPv4
+ v.dnsIPv4 = []net.IP{uplinkIPv4}
+ v.routerExtGwIPv4 = uplinkIPv4
}
- parentIPv6, parentIPv6Net, err := net.ParseCIDR(parentIPv6CIDR)
+ uplinkIPv6, uplinkIPv6Net, err := net.ParseCIDR(uplinkIPv6CIDR)
if err == nil {
- v.dnsIPv6 = []net.IP{parentIPv6}
- v.routerExtGwIPv6 = parentIPv6
+ v.dnsIPv6 = []net.IP{uplinkIPv6}
+ v.routerExtGwIPv6 = uplinkIPv6
}
// Detect optional DNS server list.
- if parentNetConf["dns.nameservers"] != "" {
+ if uplinkNetConf["dns.nameservers"] != "" {
// Reset nameservers.
v.dnsIPv4 = nil
v.dnsIPv6 = nil
- nsList := strings.Split(parentNetConf["dns.nameservers"], ",")
+ nsList := strings.Split(uplinkNetConf["dns.nameservers"], ",")
for _, ns := range nsList {
nsIP := net.ParseIP(strings.TrimSpace(ns))
if nsIP == nil {
- return nil, fmt.Errorf("Invalid parent nameserver")
+ return nil, fmt.Errorf("Invalid uplink nameserver")
}
if nsIP.To4() == nil {
@@ -457,63 +457,63 @@ func (n *ovn) allocateParentPortIPs(parentNet Network, routerMAC net.HardwareAdd
}
}
- // Parse existing allocated IPs for this network on the parent network (if not set yet, will be nil).
- routerExtPortIPv4 := net.ParseIP(n.config[ovnVolatileParentIPv4])
- routerExtPortIPv6 := net.ParseIP(n.config[ovnVolatileParentIPv6])
+ // Parse existing allocated IPs for this network on the uplink network (if not set yet, will be nil).
+ routerExtPortIPv4 := net.ParseIP(n.config[ovnVolatileUplinkIPv4])
+ routerExtPortIPv6 := net.ParseIP(n.config[ovnVolatileUplinkIPv6])
// Decide whether we need to allocate new IP(s) and go to the expense of retrieving all allocated IPs.
- if (parentIPv4Net != nil && routerExtPortIPv4 == nil) || (parentIPv6Net != nil && routerExtPortIPv6 == nil) {
+ if (uplinkIPv4Net != nil && routerExtPortIPv4 == nil) || (uplinkIPv6Net != nil && routerExtPortIPv6 == nil) {
err := n.state.Cluster.Transaction(func(tx *db.ClusterTx) error {
- allAllocatedIPv4, allAllocatedIPv6, err := n.parentAllAllocatedIPs(tx, parentNet.Name())
+ allAllocatedIPv4, allAllocatedIPv6, err := n.uplinkAllAllocatedIPs(tx, uplinkNet.Name())
if err != nil {
- return errors.Wrapf(err, "Failed to get all allocated IPs for parent")
+ return errors.Wrapf(err, "Failed to get all allocated IPs for uplink")
}
- if parentIPv4Net != nil && routerExtPortIPv4 == nil {
- if parentNetConf["ipv4.ovn.ranges"] == "" {
- return fmt.Errorf(`Missing required "ipv4.ovn.ranges" config key on parent network`)
+ if uplinkIPv4Net != nil && routerExtPortIPv4 == nil {
+ if uplinkNetConf["ipv4.ovn.ranges"] == "" {
+ return fmt.Errorf(`Missing required "ipv4.ovn.ranges" config key on uplink network`)
}
- ipRanges, err := parseIPRanges(parentNetConf["ipv4.ovn.ranges"], parentNet.DHCPv4Subnet())
+ ipRanges, err := parseIPRanges(uplinkNetConf["ipv4.ovn.ranges"], uplinkNet.DHCPv4Subnet())
if err != nil {
- return errors.Wrapf(err, "Failed to parse parent IPv4 OVN ranges")
+ return errors.Wrapf(err, "Failed to parse uplink IPv4 OVN ranges")
}
- routerExtPortIPv4, err = n.parentAllocateIP(ipRanges, allAllocatedIPv4)
+ routerExtPortIPv4, err = n.uplinkAllocateIP(ipRanges, allAllocatedIPv4)
if err != nil {
- return errors.Wrapf(err, "Failed to allocate parent IPv4 address")
+ return errors.Wrapf(err, "Failed to allocate uplink IPv4 address")
}
- n.config[ovnVolatileParentIPv4] = routerExtPortIPv4.String()
+ n.config[ovnVolatileUplinkIPv4] = routerExtPortIPv4.String()
}
- if parentIPv6Net != nil && routerExtPortIPv6 == nil {
- // If IPv6 OVN ranges are specified by the parent, allocate from them.
- if parentNetConf["ipv6.ovn.ranges"] != "" {
- ipRanges, err := parseIPRanges(parentNetConf["ipv6.ovn.ranges"], parentNet.DHCPv6Subnet())
+ if uplinkIPv6Net != nil && routerExtPortIPv6 == nil {
+ // If IPv6 OVN ranges are specified by the uplink, allocate from them.
+ if uplinkNetConf["ipv6.ovn.ranges"] != "" {
+ ipRanges, err := parseIPRanges(uplinkNetConf["ipv6.ovn.ranges"], uplinkNet.DHCPv6Subnet())
if err != nil {
- return errors.Wrapf(err, "Failed to parse parent IPv6 OVN ranges")
+ return errors.Wrapf(err, "Failed to parse uplink IPv6 OVN ranges")
}
- routerExtPortIPv6, err = n.parentAllocateIP(ipRanges, allAllocatedIPv6)
+ routerExtPortIPv6, err = n.uplinkAllocateIP(ipRanges, allAllocatedIPv6)
if err != nil {
- return errors.Wrapf(err, "Failed to allocate parent IPv6 address")
+ return errors.Wrapf(err, "Failed to allocate uplink IPv6 address")
}
} else {
// Otherwise use EUI64 derived from MAC address.
- routerExtPortIPv6, err = eui64.ParseMAC(parentIPv6Net.IP, routerMAC)
+ routerExtPortIPv6, err = eui64.ParseMAC(uplinkIPv6Net.IP, routerMAC)
if err != nil {
return err
}
}
- n.config[ovnVolatileParentIPv6] = routerExtPortIPv6.String()
+ n.config[ovnVolatileUplinkIPv6] = routerExtPortIPv6.String()
}
err = tx.UpdateNetwork(n.id, n.description, n.config)
if err != nil {
- return errors.Wrapf(err, "Failed saving allocated parent network IPs")
+ return errors.Wrapf(err, "Failed saving allocated uplink network IPs")
}
return nil
@@ -524,17 +524,17 @@ func (n *ovn) allocateParentPortIPs(parentNet Network, routerMAC net.HardwareAdd
}
// Configure variables needed to configure OVN router.
- if parentIPv4Net != nil && routerExtPortIPv4 != nil {
+ if uplinkIPv4Net != nil && routerExtPortIPv4 != nil {
routerExtPortIPv4Net := &net.IPNet{
- Mask: parentIPv4Net.Mask,
+ Mask: uplinkIPv4Net.Mask,
IP: routerExtPortIPv4,
}
v.routerExtPortIPv4Net = routerExtPortIPv4Net.String()
}
- if parentIPv6Net != nil {
+ if uplinkIPv6Net != nil {
routerExtPortIPv6Net := &net.IPNet{
- Mask: parentIPv6Net.Mask,
+ Mask: uplinkIPv6Net.Mask,
IP: routerExtPortIPv6,
}
v.routerExtPortIPv6Net = routerExtPortIPv6Net.String()
@@ -543,8 +543,8 @@ func (n *ovn) allocateParentPortIPs(parentNet Network, routerMAC net.HardwareAdd
return v, nil
}
-// parentAllAllocatedIPs gets a list of all IPv4 and IPv6 addresses allocated to OVN networks connected to parent.
-func (n *ovn) parentAllAllocatedIPs(tx *db.ClusterTx, parentNetName string) ([]net.IP, []net.IP, error) {
+// uplinkAllAllocatedIPs gets a list of all IPv4 and IPv6 addresses allocated to OVN networks connected to uplink.
+func (n *ovn) uplinkAllAllocatedIPs(tx *db.ClusterTx, uplinkNetName string) ([]net.IP, []net.IP, error) {
// Get all managed networks across all projects.
projectNetworks, err := tx.GetNonPendingNetworks()
if err != nil {
@@ -556,11 +556,11 @@ func (n *ovn) parentAllAllocatedIPs(tx *db.ClusterTx, parentNetName string) ([]n
for _, networks := range projectNetworks {
for _, netInfo := range networks {
- if netInfo.Type != "ovn" || netInfo.Config["network"] != parentNetName {
+ if netInfo.Type != "ovn" || netInfo.Config["network"] != uplinkNetName {
continue
}
- for _, k := range []string{ovnVolatileParentIPv4, ovnVolatileParentIPv6} {
+ for _, k := range []string{ovnVolatileUplinkIPv4, ovnVolatileUplinkIPv6} {
if netInfo.Config[k] != "" {
ip := net.ParseIP(netInfo.Config[k])
if ip != nil {
@@ -578,8 +578,8 @@ func (n *ovn) parentAllAllocatedIPs(tx *db.ClusterTx, parentNetName string) ([]n
return v4IPs, v6IPs, nil
}
-// parentAllocateIP allocates a free IP from one of the IP ranges.
-func (n *ovn) parentAllocateIP(ipRanges []*shared.IPRange, allAllocated []net.IP) (net.IP, error) {
+// uplinkAllocateIP allocates a free IP from one of the IP ranges.
+func (n *ovn) uplinkAllocateIP(ipRanges []*shared.IPRange, allAllocated []net.IP) (net.IP, error) {
for _, ipRange := range ipRanges {
inc := big.NewInt(1)
@@ -629,73 +629,73 @@ func (n *ovn) parentAllocateIP(ipRanges []*shared.IPRange, allAllocated []net.IP
return nil, fmt.Errorf("No free IPs available")
}
-// startParentPort performs any network start up logic needed to connect the parent uplink connection to OVN.
-func (n *ovn) startParentPort() error {
- // Parent network must be in default project.
- parentNet, err := LoadByName(n.state, project.Default, n.config["network"])
+// startUplinkPort performs any network start up logic needed to connect the uplink connection to OVN.
+func (n *ovn) startUplinkPort() error {
+ // Uplink network must be in default project.
+ uplinkNet, err := LoadByName(n.state, project.Default, n.config["network"])
if err != nil {
- return errors.Wrapf(err, "Failed loading parent network")
+ return errors.Wrapf(err, "Failed loading uplink network")
}
- // Lock parent network so that if multiple OVN networks are trying to connect to the same parent we don't
+ // Lock uplink network so that if multiple OVN networks are trying to connect to the same uplink we don't
// race each other setting up the connection.
- unlock := locking.Lock(n.parentOperationLockName(parentNet))
+ unlock := locking.Lock(n.uplinkOperationLockName(uplinkNet))
defer unlock()
- switch parentNet.Type() {
+ switch uplinkNet.Type() {
case "bridge":
- return n.startParentPortBridge(parentNet)
+ return n.startUplinkPortBridge(uplinkNet)
case "physical":
- return n.startParentPortPhysical(parentNet)
+ return n.startUplinkPortPhysical(uplinkNet)
}
- return fmt.Errorf("Failed starting parent port, network type %q unsupported as OVN parent", parentNet.Type())
+ return fmt.Errorf("Failed starting uplink port, network type %q unsupported as OVN uplink", uplinkNet.Type())
}
-// parentOperationLockName returns the lock name to use for operations on the parent network.
-func (n *ovn) parentOperationLockName(parentNet Network) string {
- return fmt.Sprintf("network.ovn.%s", parentNet.Name())
+// uplinkOperationLockName returns the lock name to use for operations on the uplink network.
+func (n *ovn) uplinkOperationLockName(uplinkNet Network) string {
+ return fmt.Sprintf("network.ovn.%s", uplinkNet.Name())
}
-// parentPortBridgeVars returns the parent port bridge variables needed for port start/stop.
-func (n *ovn) parentPortBridgeVars(parentNet Network) *ovnParentPortBridgeVars {
- ovsBridge := fmt.Sprintf("lxdovn%d", parentNet.ID())
+// uplinkPortBridgeVars returns the uplink port bridge variables needed for port start/stop.
+func (n *ovn) uplinkPortBridgeVars(uplinkNet Network) *ovnUplinkPortBridgeVars {
+ ovsBridge := fmt.Sprintf("lxdovn%d", uplinkNet.ID())
- return &ovnParentPortBridgeVars{
+ return &ovnUplinkPortBridgeVars{
ovsBridge: ovsBridge,
- parentEnd: fmt.Sprintf("%sa", ovsBridge),
+ uplinkEnd: fmt.Sprintf("%sa", ovsBridge),
ovsEnd: fmt.Sprintf("%sb", ovsBridge),
}
}
-// startParentPortBridge creates veth pair (if doesn't exist), creates OVS bridge (if doesn't exist) and
-// connects veth pair to parent bridge and OVS bridge.
-func (n *ovn) startParentPortBridge(parentNet Network) error {
- vars := n.parentPortBridgeVars(parentNet)
+// startUplinkPortBridge creates veth pair (if doesn't exist), creates OVS bridge (if doesn't exist) and
+// connects veth pair to uplink bridge and OVS bridge.
+func (n *ovn) startUplinkPortBridge(uplinkNet Network) error {
+ vars := n.uplinkPortBridgeVars(uplinkNet)
// Do this after gaining lock so that on failure we revert before release locking.
revert := revert.New()
defer revert.Fail()
// Create veth pair if needed.
- if !InterfaceExists(vars.parentEnd) && !InterfaceExists(vars.ovsEnd) {
- _, err := shared.RunCommand("ip", "link", "add", "dev", vars.parentEnd, "type", "veth", "peer", "name", vars.ovsEnd)
+ if !InterfaceExists(vars.uplinkEnd) && !InterfaceExists(vars.ovsEnd) {
+ _, err := shared.RunCommand("ip", "link", "add", "dev", vars.uplinkEnd, "type", "veth", "peer", "name", vars.ovsEnd)
if err != nil {
- return errors.Wrapf(err, "Failed to create the uplink veth interfaces %q and %q", vars.parentEnd, vars.ovsEnd)
+ return errors.Wrapf(err, "Failed to create the uplink veth interfaces %q and %q", vars.uplinkEnd, vars.ovsEnd)
}
- revert.Add(func() { shared.RunCommand("ip", "link", "delete", vars.parentEnd) })
+ revert.Add(func() { shared.RunCommand("ip", "link", "delete", vars.uplinkEnd) })
}
// Ensure that the veth interfaces inherit the uplink bridge's MTU (which the OVS bridge also inherits).
- parentNetConfig := parentNet.Config()
- if parentNetConfig["bridge.mtu"] != "" {
- err := InterfaceSetMTU(vars.parentEnd, parentNetConfig["bridge.mtu"])
+ uplinkNetConfig := uplinkNet.Config()
+ if uplinkNetConfig["bridge.mtu"] != "" {
+ err := InterfaceSetMTU(vars.uplinkEnd, uplinkNetConfig["bridge.mtu"])
if err != nil {
return err
}
- err = InterfaceSetMTU(vars.ovsEnd, parentNetConfig["bridge.mtu"])
+ err = InterfaceSetMTU(vars.ovsEnd, uplinkNetConfig["bridge.mtu"])
if err != nil {
return err
}
@@ -703,55 +703,55 @@ func (n *ovn) startParentPortBridge(parentNet Network) error {
// Ensure correct sysctls are set on uplink veth interfaces to avoid getting IPv6 link-local addresses.
err := util.SysctlSet(
- fmt.Sprintf("net/ipv6/conf/%s/disable_ipv6", vars.parentEnd), "1",
+ fmt.Sprintf("net/ipv6/conf/%s/disable_ipv6", vars.uplinkEnd), "1",
fmt.Sprintf("net/ipv6/conf/%s/disable_ipv6", vars.ovsEnd), "1",
- fmt.Sprintf("net/ipv6/conf/%s/forwarding", vars.parentEnd), "0",
+ fmt.Sprintf("net/ipv6/conf/%s/forwarding", vars.uplinkEnd), "0",
fmt.Sprintf("net/ipv6/conf/%s/forwarding", vars.ovsEnd), "0",
)
if err != nil {
- return errors.Wrapf(err, "Failed to configure uplink veth interfaces %q and %q", vars.parentEnd, vars.ovsEnd)
+ return errors.Wrapf(err, "Failed to configure uplink veth interfaces %q and %q", vars.uplinkEnd, vars.ovsEnd)
}
- // Connect parent end of veth pair to parent bridge and bring up.
- _, err = shared.RunCommand("ip", "link", "set", "master", parentNet.Name(), "dev", vars.parentEnd, "up")
+ // Connect uplink end of veth pair to uplink bridge and bring up.
+ _, err = shared.RunCommand("ip", "link", "set", "master", uplinkNet.Name(), "dev", vars.uplinkEnd, "up")
if err != nil {
- return errors.Wrapf(err, "Failed to connect uplink veth interface %q to parent bridge %q", vars.parentEnd, parentNet.Name())
+ return errors.Wrapf(err, "Failed to connect uplink veth interface %q to uplink bridge %q", vars.uplinkEnd, uplinkNet.Name())
}
// Ensure uplink OVS end veth interface is up.
_, err = shared.RunCommand("ip", "link", "set", "dev", vars.ovsEnd, "up")
if err != nil {
- return errors.Wrapf(err, "Failed to bring up parent veth interface %q", vars.ovsEnd)
+ return errors.Wrapf(err, "Failed to bring up uplink veth interface %q", vars.ovsEnd)
}
- // Create parent OVS bridge if needed.
+ // Create uplink OVS bridge if needed.
ovs := openvswitch.NewOVS()
err = ovs.BridgeAdd(vars.ovsBridge, true)
if err != nil {
- return errors.Wrapf(err, "Failed to create parent uplink OVS bridge %q", vars.ovsBridge)
+ return errors.Wrapf(err, "Failed to create uplink OVS bridge %q", vars.ovsBridge)
}
// Connect OVS end veth interface to OVS bridge.
err = ovs.BridgePortAdd(vars.ovsBridge, vars.ovsEnd, true)
if err != nil {
- return errors.Wrapf(err, "Failed to connect uplink veth interface %q to parent OVS bridge %q", vars.ovsEnd, vars.ovsBridge)
+ return errors.Wrapf(err, "Failed to connect uplink veth interface %q to uplink OVS bridge %q", vars.ovsEnd, vars.ovsBridge)
}
// Associate OVS bridge to logical OVN provider.
- err = ovs.OVNBridgeMappingAdd(vars.ovsBridge, parentNet.Name())
+ err = ovs.OVNBridgeMappingAdd(vars.ovsBridge, uplinkNet.Name())
if err != nil {
- return errors.Wrapf(err, "Failed to associate parent OVS bridge %q to OVN provider %q", vars.ovsBridge, parentNet.Name())
+ return errors.Wrapf(err, "Failed to associate uplink OVS bridge %q to OVN provider %q", vars.ovsBridge, uplinkNet.Name())
}
- routerExtPortIPv6 := net.ParseIP(n.config[ovnVolatileParentIPv6])
+ routerExtPortIPv6 := net.ParseIP(n.config[ovnVolatileUplinkIPv6])
if routerExtPortIPv6 != nil {
- // Now that the OVN router is connected to the uplink parent bridge, attempt to ping the OVN
- // router's external IPv6 from the LXD host running the parent bridge in an attempt to trigger the
- // OVN router to learn the parent uplink gateway's MAC address. This is to work around a bug in
+ // Now that the OVN router is connected to the uplink bridge, attempt to ping the OVN
+ // router's external IPv6 from the LXD host running the uplink bridge in an attempt to trigger the
+ // OVN router to learn the uplink gateway's MAC address. This is to work around a bug in
// older versions of OVN that meant that the OVN router would not attempt to learn the external
// uplink IPv6 gateway MAC address when using SNAT, meaning that external IPv6 connectivity
// wouldn't work until the next router advertisement was sent (which could be several minutes).
- // By pinging the OVN router's external IP this will trigger an NDP request from the parent bridge
+ // By pinging the OVN router's external IP this will trigger an NDP request from the uplink bridge
// which will cause the OVN router to learn its MAC address.
go func() {
// Try several attempts as it can take a few seconds for the network to come up.
@@ -774,19 +774,19 @@ func (n *ovn) startParentPortBridge(parentNet Network) error {
return nil
}
-// startParentPortPhysical creates OVS bridge (if doesn't exist) and connects parent interface to the OVS bridge.
-func (n *ovn) startParentPortPhysical(parentNet Network) error {
- vars := n.parentPortBridgeVars(parentNet)
+// startUplinkPortPhysical creates OVS bridge (if doesn't exist) and connects uplink interface to the OVS bridge.
+func (n *ovn) startUplinkPortPhysical(uplinkNet Network) error {
+ vars := n.uplinkPortBridgeVars(uplinkNet)
// Do this after gaining lock so that on failure we revert before release locking.
revert := revert.New()
defer revert.Fail()
- parentConfig := parentNet.Config()
- uplinkHostName := GetHostDevice(parentConfig["parent"], parentConfig["vlan"])
+ uplinkConfig := uplinkNet.Config()
+ uplinkHostName := GetHostDevice(uplinkConfig["parent"], uplinkConfig["vlan"])
if !InterfaceExists(uplinkHostName) {
- return fmt.Errorf("Uplink network %q is not started", parentNet.Name())
+ return fmt.Errorf("Uplink network %q is not started", uplinkNet.Name())
}
// Ensure correct sysctls are set on uplink interface to avoid getting IPv6 link-local addresses.
@@ -798,29 +798,29 @@ func (n *ovn) startParentPortPhysical(parentNet Network) error {
return errors.Wrapf(err, "Failed to configure uplink interface %q", uplinkHostName)
}
- // Create parent OVS bridge if needed.
+ // Create uplink OVS bridge if needed.
ovs := openvswitch.NewOVS()
err = ovs.BridgeAdd(vars.ovsBridge, true)
if err != nil {
- return errors.Wrapf(err, "Failed to create parent uplink OVS bridge %q", vars.ovsBridge)
+ return errors.Wrapf(err, "Failed to create uplink OVS bridge %q", vars.ovsBridge)
}
// Connect OVS end veth interface to OVS bridge.
err = ovs.BridgePortAdd(vars.ovsBridge, uplinkHostName, true)
if err != nil {
- return errors.Wrapf(err, "Failed to connect uplink interface %q to parent OVS bridge %q", uplinkHostName, vars.ovsBridge)
+ return errors.Wrapf(err, "Failed to connect uplink interface %q to uplink OVS bridge %q", uplinkHostName, vars.ovsBridge)
}
// Associate OVS bridge to logical OVN provider.
- err = ovs.OVNBridgeMappingAdd(vars.ovsBridge, parentNet.Name())
+ err = ovs.OVNBridgeMappingAdd(vars.ovsBridge, uplinkNet.Name())
if err != nil {
- return errors.Wrapf(err, "Failed to associate parent OVS bridge %q to OVN provider %q", vars.ovsBridge, parentNet.Name())
+ return errors.Wrapf(err, "Failed to associate uplink OVS bridge %q to OVN provider %q", vars.ovsBridge, uplinkNet.Name())
}
// Bring uplink interface up.
_, err = shared.RunCommand("ip", "link", "set", uplinkHostName, "up")
if err != nil {
- return errors.Wrapf(err, "Failed to bring up parent interface %q", uplinkHostName)
+ return errors.Wrapf(err, "Failed to bring up uplink interface %q", uplinkHostName)
}
revert.Success()
@@ -847,7 +847,7 @@ func (n *ovn) checkUplinkUse() (bool, error) {
continue // Ignore our own DB record or non OVN networks.
}
- // Check if another network is using our parent.
+ // Check if another network is using our uplink.
if network.Config["network"] == n.config["network"] {
return true, nil
}
@@ -857,37 +857,37 @@ func (n *ovn) checkUplinkUse() (bool, error) {
return false, nil
}
-// deleteParentPort deletes the parent uplink connection.
-func (n *ovn) deleteParentPort() error {
- // Parent network must be in default project.
+// deleteUplinkPort deletes the uplink connection.
+func (n *ovn) deleteUplinkPort() error {
+ // Uplink network must be in default project.
if n.config["network"] != "" {
- parentNet, err := LoadByName(n.state, project.Default, n.config["network"])
+ uplinkNet, err := LoadByName(n.state, project.Default, n.config["network"])
if err != nil {
- return errors.Wrapf(err, "Failed loading parent network")
+ return errors.Wrapf(err, "Failed loading uplink network")
}
- // Lock parent network so we don't race each other networks using the OVS uplink bridge.
- unlock := locking.Lock(n.parentOperationLockName(parentNet))
+ // Lock uplink network so we don't race each other networks using the OVS uplink bridge.
+ unlock := locking.Lock(n.uplinkOperationLockName(uplinkNet))
defer unlock()
- switch parentNet.Type() {
+ switch uplinkNet.Type() {
case "bridge":
- return n.deleteParentPortBridge(parentNet)
+ return n.deleteUplinkPortBridge(uplinkNet)
case "physical":
- return n.deleteParentPortPhysical(parentNet)
+ return n.deleteUplinkPortPhysical(uplinkNet)
}
- return fmt.Errorf("Failed deleting parent port, network type %q unsupported as OVN parent", parentNet.Type())
+ return fmt.Errorf("Failed deleting uplink port, network type %q unsupported as OVN uplink", uplinkNet.Type())
}
return nil
}
-// deleteParentPortBridge deletes parent uplink OVS bridge, OVN bridge mappings and veth interfaces if not in use.
-func (n *ovn) deleteParentPortBridge(parentNet Network) error {
+// deleteUplinkPortBridge deletes uplink OVS bridge, OVN bridge mappings and veth interfaces if not in use.
+func (n *ovn) deleteUplinkPortBridge(uplinkNet Network) error {
// Check OVS uplink bridge exists, if it does, check whether the uplink network is in use.
removeVeths := false
- vars := n.parentPortBridgeVars(parentNet)
+ vars := n.uplinkPortBridgeVars(uplinkNet)
if InterfaceExists(vars.ovsBridge) {
uplinkUsed, err := n.checkUplinkUse()
if err != nil {
@@ -899,7 +899,7 @@ func (n *ovn) deleteParentPortBridge(parentNet Network) error {
removeVeths = true
ovs := openvswitch.NewOVS()
- err = ovs.OVNBridgeMappingDelete(vars.ovsBridge, parentNet.Name())
+ err = ovs.OVNBridgeMappingDelete(vars.ovsBridge, uplinkNet.Name())
if err != nil {
return err
}
@@ -915,10 +915,10 @@ func (n *ovn) deleteParentPortBridge(parentNet Network) error {
// Remove the veth interfaces if they exist.
if removeVeths {
- if InterfaceExists(vars.parentEnd) {
- _, err := shared.RunCommand("ip", "link", "delete", "dev", vars.parentEnd)
+ if InterfaceExists(vars.uplinkEnd) {
+ _, err := shared.RunCommand("ip", "link", "delete", "dev", vars.uplinkEnd)
if err != nil {
- return errors.Wrapf(err, "Failed to delete the uplink veth interface %q", vars.parentEnd)
+ return errors.Wrapf(err, "Failed to delete the uplink veth interface %q", vars.uplinkEnd)
}
}
@@ -933,11 +933,11 @@ func (n *ovn) deleteParentPortBridge(parentNet Network) error {
return nil
}
-// deleteParentPortPhysical deletes parent uplink OVS bridge and OVN bridge mappings if not in use.
-func (n *ovn) deleteParentPortPhysical(parentNet Network) error {
+// deleteUplinkPortPhysical deletes uplink OVS bridge and OVN bridge mappings if not in use.
+func (n *ovn) deleteUplinkPortPhysical(uplinkNet Network) error {
// Check OVS uplink bridge exists, if it does, check whether the uplink network is in use.
releaseIF := false
- vars := n.parentPortBridgeVars(parentNet)
+ vars := n.uplinkPortBridgeVars(uplinkNet)
if InterfaceExists(vars.ovsBridge) {
uplinkUsed, err := n.checkUplinkUse()
if err != nil {
@@ -949,7 +949,7 @@ func (n *ovn) deleteParentPortPhysical(parentNet Network) error {
releaseIF = true
ovs := openvswitch.NewOVS()
- err = ovs.OVNBridgeMappingDelete(vars.ovsBridge, parentNet.Name())
+ err = ovs.OVNBridgeMappingDelete(vars.ovsBridge, uplinkNet.Name())
if err != nil {
return err
}
@@ -965,12 +965,12 @@ func (n *ovn) deleteParentPortPhysical(parentNet Network) error {
// Bring down uplink interface if exists.
if releaseIF {
- parentConfig := parentNet.Config()
- parentDev := GetHostDevice(parentConfig["parent"], parentConfig["vlan"])
- if InterfaceExists(parentDev) {
- _, err := shared.RunCommand("ip", "link", "set", parentDev, "down")
+ uplinkConfig := uplinkNet.Config()
+ uplinkDev := GetHostDevice(uplinkConfig["parent"], uplinkConfig["vlan"])
+ if InterfaceExists(uplinkDev) {
+ _, err := shared.RunCommand("ip", "link", "set", uplinkDev, "down")
if err != nil {
- return errors.Wrapf(err, "Failed to bring down uplink interface %q", parentDev)
+ return errors.Wrapf(err, "Failed to bring down uplink interface %q", uplinkDev)
}
}
}
@@ -1171,24 +1171,24 @@ func (n *ovn) setup(update bool) error {
return err
}
- // Setup parent port (do this first to check parent is suitable).
- parent, err := n.setupParentPort(routerMAC)
+ // Setup uplink port (do this first to check uplink is suitable).
+ uplinkNet, err := n.setupUplinkPort(routerMAC)
if err != nil {
return err
}
// Parse router IP config.
- if parent.routerExtPortIPv4Net != "" {
- routerExtPortIPv4, routerExtPortIPv4Net, err = net.ParseCIDR(parent.routerExtPortIPv4Net)
+ if uplinkNet.routerExtPortIPv4Net != "" {
+ routerExtPortIPv4, routerExtPortIPv4Net, err = net.ParseCIDR(uplinkNet.routerExtPortIPv4Net)
if err != nil {
- return errors.Wrapf(err, "Failed parsing router's external parent port IPv4 Net")
+ return errors.Wrapf(err, "Failed parsing router's external uplink port IPv4 Net")
}
}
- if parent.routerExtPortIPv6Net != "" {
- routerExtPortIPv6, routerExtPortIPv6Net, err = net.ParseCIDR(parent.routerExtPortIPv6Net)
+ if uplinkNet.routerExtPortIPv6Net != "" {
+ routerExtPortIPv6, routerExtPortIPv6Net, err = net.ParseCIDR(uplinkNet.routerExtPortIPv6Net)
if err != nil {
- return errors.Wrapf(err, "Failed parsing router's external parent port IPv6 Net")
+ return errors.Wrapf(err, "Failed parsing router's external uplink port IPv6 Net")
}
}
@@ -1228,15 +1228,15 @@ func (n *ovn) setup(update bool) error {
// Configure logical router.
// Add default routes.
- if parent.routerExtGwIPv4 != nil {
- err = client.LogicalRouterRouteAdd(n.getRouterName(), &net.IPNet{IP: net.IPv4zero, Mask: net.CIDRMask(0, 32)}, parent.routerExtGwIPv4)
+ if uplinkNet.routerExtGwIPv4 != nil {
+ err = client.LogicalRouterRouteAdd(n.getRouterName(), &net.IPNet{IP: net.IPv4zero, Mask: net.CIDRMask(0, 32)}, uplinkNet.routerExtGwIPv4)
if err != nil {
return errors.Wrapf(err, "Failed adding IPv4 default route")
}
}
- if parent.routerExtGwIPv6 != nil {
- err = client.LogicalRouterRouteAdd(n.getRouterName(), &net.IPNet{IP: net.IPv6zero, Mask: net.CIDRMask(0, 128)}, parent.routerExtGwIPv6)
+ if uplinkNet.routerExtGwIPv6 != nil {
+ err = client.LogicalRouterRouteAdd(n.getRouterName(), &net.IPNet{IP: net.IPv6zero, Mask: net.CIDRMask(0, 128)}, uplinkNet.routerExtGwIPv6)
if err != nil {
return errors.Wrapf(err, "Failed adding IPv6 default route")
}
@@ -1317,7 +1317,7 @@ func (n *ovn) setup(update bool) error {
}
revert.Add(func() { client.LogicalSwitchPortDelete(n.getExtSwitchProviderPortName()) })
- err = client.LogicalSwitchPortLinkProviderNetwork(n.getExtSwitchProviderPortName(), parent.extSwitchProviderName)
+ err = client.LogicalSwitchPortLinkProviderNetwork(n.getExtSwitchProviderPortName(), uplinkNet.extSwitchProviderName)
if err != nil {
return errors.Wrapf(err, "Failed linking external switch provider port to external provider network")
}
@@ -1367,7 +1367,7 @@ func (n *ovn) setup(update bool) error {
ServerID: routerIntPortIPv4,
ServerMAC: routerMAC,
Router: routerIntPortIPv4,
- RecursiveDNSServer: parent.dnsIPv4,
+ RecursiveDNSServer: uplinkNet.dnsIPv4,
DomainName: n.getDomainName(),
LeaseTime: time.Duration(time.Hour * 1),
MTU: bridgeMTU,
@@ -1379,7 +1379,7 @@ func (n *ovn) setup(update bool) error {
// Create DHCPv6 options for internal switch.
err = client.LogicalSwitchDHCPv6OptionsSet(n.getIntSwitchName(), dhcpv6UUID, routerIntPortIPv6Net, &openvswitch.OVNDHCPv6Opts{
ServerID: routerMAC,
- RecursiveDNSServer: parent.dnsIPv6,
+ RecursiveDNSServer: uplinkNet.dnsIPv6,
DNSSearchList: n.getDNSSearchList(),
})
if err != nil {
@@ -1417,8 +1417,8 @@ func (n *ovn) setup(update bool) error {
}
var recursiveDNSServer net.IP
- if len(parent.dnsIPv6) > 0 {
- recursiveDNSServer = parent.dnsIPv6[0] // OVN only supports 1 RA DNS server.
+ if len(uplinkNet.dnsIPv6) > 0 {
+ recursiveDNSServer = uplinkNet.dnsIPv6[0] // OVN only supports 1 RA DNS server.
}
err = client.LogicalRouterPortSetIPv6Advertisements(n.getRouterIntPortName(), &openvswitch.OVNIPv6RAOpts{
@@ -1577,7 +1577,7 @@ func (n *ovn) Rename(newName string) error {
return nil
}
-// Start starts adds the local OVS chassis ID to the OVN chass group and starts the local OVS parent uplink port.
+// Start starts adds the local OVS chassis ID to the OVN chass group and starts the local OVS uplink port.
func (n *ovn) Start() error {
n.logger.Debug("Start")
@@ -1591,7 +1591,7 @@ func (n *ovn) Start() error {
return err
}
- err = n.startParentPort()
+ err = n.startUplinkPort()
if err != nil {
return err
}
@@ -1599,7 +1599,7 @@ func (n *ovn) Start() error {
return nil
}
-// Stop deletes the local OVS parent uplink port (if unused) and deletes the local OVS chassis ID from the
+// Stop deletes the local OVS uplink port (if unused) and deletes the local OVS chassis ID from the
// OVN chass group
func (n *ovn) Stop() error {
n.logger.Debug("Stop")
@@ -1610,8 +1610,8 @@ func (n *ovn) Stop() error {
return err
}
- // Delete local parent uplink port if not used by other OVN networks.
- err = n.deleteParentPort()
+ // Delete local uplink port if not used by other OVN networks.
+ err = n.deleteUplinkPort()
if err != nil {
return err
}
@@ -1663,8 +1663,8 @@ func (n *ovn) Update(newNetwork api.NetworkPut, targetNode string, clientType cl
}
// Remove volatile keys associated with old network in new config.
- delete(newNetwork.Config, ovnVolatileParentIPv4)
- delete(newNetwork.Config, ovnVolatileParentIPv6)
+ delete(newNetwork.Config, ovnVolatileUplinkIPv4)
+ delete(newNetwork.Config, ovnVolatileUplinkIPv6)
}
// Apply changes to all nodes and databse.
From 406d4fc37c9b00a0065e237fc74e0122acea92a6 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 13 Oct 2020 09:36:01 +0100
Subject: [PATCH 8/8] lxd/network/driver/common: Ban : char from network names
in ValidateName()
This prevents network names from conflicting with vlan alias interface names and when used as a prefix for `restricted.networks.subnets` in projects.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/driver_common.go | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/lxd/network/driver_common.go b/lxd/network/driver_common.go
index 3c422c5a1a..23cff9a58c 100644
--- a/lxd/network/driver_common.go
+++ b/lxd/network/driver_common.go
@@ -101,7 +101,16 @@ func (n *common) validate(config map[string]string, driverRules map[string]func(
// ValidateName validates network name.
func (n *common) ValidateName(name string) error {
- return validate.IsURLSegmentSafe(name)
+ err := validate.IsURLSegmentSafe(name)
+ if err != nil {
+ return err
+ }
+
+ if strings.Contains(name, ":") {
+ return fmt.Errorf("Cannot contain %q", ":")
+ }
+
+ return nil
}
// ID returns the network ID.
More information about the lxc-devel
mailing list