From f6c0c761dce6f88852558db323081d21fb74bc2c Mon Sep 17 00:00:00 2001 From: hamistao Date: Sun, 20 Oct 2024 14:50:19 -0300 Subject: [PATCH 1/6] lxd/network/driver_bridge: List gateway leases when !features.networks Signed-off-by: hamistao --- lxd/network/driver_bridge.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/lxd/network/driver_bridge.go b/lxd/network/driver_bridge.go index f5243cf4c0b7..e19263ce9154 100644 --- a/lxd/network/driver_bridge.go +++ b/lxd/network/driver_bridge.go @@ -3447,10 +3447,23 @@ func (n *bridge) Leases(projectName string, clientType request.ClientType) ([]ap instanceProjects := make(map[string]string) leases := []api.NetworkLease{} + // Include gateway leases if network is visible from requested project or requesting all projects. + // Avoid querying project if we don't need to check features.networks. + includeGatewayLeases := projectName == "" || n.project == projectName + if !includeGatewayLeases { + var effectiveProject string + effectiveProject, _, err = project.NetworkProject(n.state.DB.Cluster, projectName) + if err != nil { + return nil, err + } + + includeGatewayLeases = n.project == effectiveProject + } + // Get all static leases. if clientType == request.ClientTypeNormal { - // If requested project matches network's project then include gateway and downstream uplink IPs. - if projectName == n.project || projectName == "" { + // Include gateway IPs if applicable. + if includeGatewayLeases { // Add our own gateway IPs. for _, addr := range []string{n.config["ipv4.address"], n.config["ipv6.address"]} { ip, _, _ := net.ParseCIDR(addr) From ad16e6684390c6d6f69eecd7e14caad2f8a9f6f0 Mon Sep 17 00:00:00 2001 From: hamistao Date: Sun, 20 Oct 2024 14:50:00 -0300 Subject: [PATCH 2/6] lxd/network/driver_ovn: List gateway leases when !features.networks Signed-off-by: hamistao --- lxd/network/driver_ovn.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/lxd/network/driver_ovn.go b/lxd/network/driver_ovn.go index d97b338f4721..4945179aeac1 100644 --- a/lxd/network/driver_ovn.go +++ b/lxd/network/driver_ovn.go @@ -5442,8 +5442,21 @@ func (n *ovn) Leases(projectName string, clientType request.ClientType) ([]api.N var err error leases := []api.NetworkLease{} - // If requested project matches network's project then include gateway IPs. - if projectName == n.project || projectName == "" { + // Include gateway leases if network is visible from requested project or requesting all projects. + // Avoid querying project if we don't need to check features.networks. + includeGatewayLeases := projectName == "" || n.project == projectName + if !includeGatewayLeases { + var effectiveProject string + effectiveProject, _, err = project.NetworkProject(n.state.DB.Cluster, projectName) + if err != nil { + return nil, err + } + + includeGatewayLeases = n.project == effectiveProject + } + + // Include gateway IPs if applicable. + if includeGatewayLeases { // Add our own gateway IPs. for _, addr := range []string{n.config["ipv4.address"], n.config["ipv6.address"]} { ip, _, _ := net.ParseCIDR(addr) From 0bd8de97efbd89966ba743e1511ab405de946dcd Mon Sep 17 00:00:00 2001 From: hamistao Date: Sun, 20 Oct 2024 14:50:32 -0300 Subject: [PATCH 3/6] lxd/networks: Remove unused parameter Signed-off-by: hamistao --- lxd/networks.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lxd/networks.go b/lxd/networks.go index ff13a115f80a..b43baf2becbb 100644 --- a/lxd/networks.go +++ b/lxd/networks.go @@ -1349,7 +1349,7 @@ func networkPut(d *Daemon, r *http.Request) response.Response { clientType := clusterRequest.UserAgentClientType(r.Header.Get("User-Agent")) - response := doNetworkUpdate(effectiveProjectName, n, req, targetNode, clientType, r.Method, s.ServerClustered) + response := doNetworkUpdate(n, req, targetNode, clientType, r.Method, s.ServerClustered) requestor := request.CreateRequestor(r) s.Events.SendLifecycle(effectiveProjectName, lifecycle.NetworkUpdated.Event(n, requestor, nil)) @@ -1402,7 +1402,7 @@ func networkPatch(d *Daemon, r *http.Request) response.Response { // doNetworkUpdate loads the current local network config, merges with the requested network config, validates // and applies the changes. Will also notify other cluster nodes of non-node specific config if needed. -func doNetworkUpdate(projectName string, n network.Network, req api.NetworkPut, targetNode string, clientType clusterRequest.ClientType, httpMethod string, clustered bool) response.Response { +func doNetworkUpdate(n network.Network, req api.NetworkPut, targetNode string, clientType clusterRequest.ClientType, httpMethod string, clustered bool) response.Response { if req.Config == nil { req.Config = map[string]string{} } From 9efb65f17a267bd6b1d35d6012c280fb9c35d7f4 Mon Sep 17 00:00:00 2001 From: hamistao Date: Tue, 22 Oct 2024 16:26:27 -0300 Subject: [PATCH 4/6] test/suites: Test for listing gateway leases Signed-off-by: hamistao --- test/suites/network.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/suites/network.sh b/test/suites/network.sh index 295556f8b2fb..671b3db811c2 100644 --- a/test/suites/network.sh +++ b/test/suites/network.sh @@ -94,6 +94,7 @@ test_network() { # Create new project with an instance with ipv[46] for the next tests. lxc project create foo -c features.networks=false -c features.images=false -c features.profiles=false lxc launch testimage outsider -n lxdt$$ --project foo + gateway_addr="$(lxc network get lxdt$$ ipv4.address | cut -d/ -f1)" v4_addr_foo="$(lxc network get lxdt$$ ipv4.address | cut -d/ -f1)1" v6_addr_foo="$(lxc network get lxdt$$ ipv6.address | cut -d/ -f1)01" lxc config device set outsider eth0 ipv4.address "${v4_addr_foo}" --project foo @@ -101,8 +102,10 @@ test_network() { lxc network list-leases lxdt$$ | grep STATIC | grep -q "${v4_addr}" lxc network list-leases lxdt$$ | grep STATIC | grep -q "${v6_addr}" + lxc network list-leases lxdt$$ | grep GATEWAY | grep -q "${gateway_addr}" lxc network list-leases lxdt$$ --project foo | grep STATIC | grep -q "${v4_addr_foo}" lxc network list-leases lxdt$$ --project foo | grep STATIC | grep -q "${v6_addr_foo}" + lxc network list-leases lxdt$$ --project foo | grep GATEWAY | grep -q "${gateway_addr}" # Request DHCPv6 lease (if udhcpc6 is in busybox image). busyboxUdhcpc6=1 From 0dc8a928980817e027d3f66b6bb75efb720b313b Mon Sep 17 00:00:00 2001 From: hamistao Date: Wed, 23 Oct 2024 09:29:48 -0300 Subject: [PATCH 5/6] lxd/network/zone: Deduplicate logic to get PTR records Signed-off-by: hamistao --- lxd/network/zone/zone.go | 58 +++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/lxd/network/zone/zone.go b/lxd/network/zone/zone.go index 924de2689395..5ec75747ce9f 100644 --- a/lxd/network/zone/zone.go +++ b/lxd/network/zone/zone.go @@ -261,6 +261,30 @@ func (d *zone) validateConfigMap(config map[string]string, rules map[string]func return nil } +func (d *zone) getProjectRecords(projectName string, n network.Network, recordGenerator func(name string, ip net.IP) map[string]string) ([]map[string]string, error) { + var records []map[string]string + + leases, err := n.Leases(projectName, request.ClientTypeNormal) + if err != nil { + return nil, err + } + + // Convert leases to usable PTR records. + for _, lease := range leases { + ip := net.ParseIP(lease.Address) + + // Get the record. + record := recordGenerator(fmt.Sprintf("%s.%s", lease.Hostname, projectName), ip) + if record == nil { + continue + } + + records = append(records, record) + } + + return records, nil +} + // Update applies the supplied config to the zone. func (d *zone) Update(config *api.NetworkZonePut, clientType request.ClientType) error { err := d.validateConfig(config) @@ -442,6 +466,8 @@ func (d *zone) Content() (*strings.Builder, error) { return record } + var leaseRecords []map[string]string + if isReverse { // Load network leases in correct project context for each forward zone referenced. for _, forwardZoneName := range shared.SplitNTrimSpace(n.Config()["dns.zone.forward"], ",", -1, true) { @@ -452,44 +478,20 @@ func (d *zone) Content() (*strings.Builder, error) { } // Load the leases for the forward zone project. - leases, err := n.Leases(forwardZoneProjectName, request.ClientTypeNormal) + leaseRecords, err = d.getProjectRecords(d.projectName, n, genRecord) if err != nil { return nil, err } - - // Convert leases to usable PTR records. - for _, lease := range leases { - ip := net.ParseIP(lease.Address) - - // Get the record. - record := genRecord(fmt.Sprintf("%s.%s", lease.Hostname, forwardZoneName), ip) - if record == nil { - continue - } - - records = append(records, record) - } } } else { // Load the leases in the forward zone's project. - leases, err := n.Leases(d.projectName, request.ClientTypeNormal) + leaseRecords, err = d.getProjectRecords(d.projectName, n, genRecord) if err != nil { return nil, err } - - // Convert leases to usable records. - for _, lease := range leases { - ip := net.ParseIP(lease.Address) - - // Get the record. - record := genRecord(lease.Hostname, ip) - if record == nil { - continue - } - - records = append(records, record) - } } + + records = append(records, leaseRecords...) } } From 521b255918b0764c72842b931d6988e4fad2dfd0 Mon Sep 17 00:00:00 2001 From: hamistao Date: Wed, 23 Oct 2024 09:38:41 -0300 Subject: [PATCH 6/6] lxd/network/zone: Ignore gateway leases when necessary We do want gateway Leases to show when listing them for a project if the network is visible from that project. However, when dealing with DNS zone configuration, we only want to consider these leases when dealing with the network's original project. Signed-off-by: hamistao --- lxd/network/zone/zone.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lxd/network/zone/zone.go b/lxd/network/zone/zone.go index 5ec75747ce9f..ee5a38009320 100644 --- a/lxd/network/zone/zone.go +++ b/lxd/network/zone/zone.go @@ -271,6 +271,12 @@ func (d *zone) getProjectRecords(projectName string, n network.Network, recordGe // Convert leases to usable PTR records. for _, lease := range leases { + // Since networks can be visible from more than one project + // We don't want to consider gateway leases unless dealing with the network's project, + if projectName != n.Project() && lease.Type == "gateway" { + continue + } + ip := net.ParseIP(lease.Address) // Get the record.