Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OVN external addresses on lxc network list-allocations #14210

Merged
merged 13 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/api-extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2501,3 +2501,9 @@ Expands APIs under `/1.0/auth` to include:
The caller must provide a base64 encoded x509 certificate in the `certificate` field of the request body.
Fine-grained TLS identities may update their own certificate.
To update the certificate of another identity, the caller must have `can_edit` on the identity.

## `network_allocations_ovn_uplink`

Includes OVN virtual routers external IPs to `/1.0/network-allocations` responses with the type `uplink`.
Introduces the `network` field on each allocation, indicating to which network each allocated address belongs.
And lastly, adds a `project` field on leases, leases can be retrieved via `/1.0/networks/<network>/leases`.
11 changes: 10 additions & 1 deletion doc/rest-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3177,6 +3177,10 @@ definitions:
description: Whether the entity comes from a network that LXD performs egress source NAT on
type: boolean
x-go-name: NAT
network:
description: Network is the name of the network the allocated address belongs to
type: string
x-go-name: Network
type:
description: Type of the entity consuming the network address
type: string
Expand Down Expand Up @@ -3327,6 +3331,11 @@ definitions:
example: lxd01
type: string
x-go-name: Location
project:
description: Name of the project of the entity related to the hostname
example: default
type: string
x-go-name: Project
type:
description: The type of record (static or dynamic)
example: dynamic
Expand Down Expand Up @@ -12199,7 +12208,7 @@ paths:
$ref: '#/responses/Forbidden'
"500":
$ref: '#/responses/InternalServerError'
summary: Get the network allocations in use (`network`, `network-forward` and `load-balancer` and `instance`)
summary: Get the network allocations in use (`network`, `network-forward`, `load-balancer`, `uplink` and `instance`)
tags:
- network-allocations
/1.0/network-zones:
Expand Down
2 changes: 2 additions & 0 deletions lxc/network_allocations.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func (c *cmdNetworkListAllocations) pretty(allocs []api.NetworkAllocations) erro
header := []string{
i18n.G("USED BY"),
i18n.G("ADDRESS"),
i18n.G("NETWORK"),
i18n.G("TYPE"),
i18n.G("NAT"),
i18n.G("HARDWARE ADDRESS"),
Expand All @@ -33,6 +34,7 @@ func (c *cmdNetworkListAllocations) pretty(allocs []api.NetworkAllocations) erro
row := []string{
alloc.UsedBy,
alloc.Address,
alloc.Network,
alloc.Type,
fmt.Sprint(alloc.NAT),
alloc.Hwaddr,
Expand Down
18 changes: 16 additions & 2 deletions lxd/network/driver_bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -3440,15 +3440,17 @@ func (n *bridge) forwardSetupFirewall() error {

// Leases returns a list of leases for the bridged network. It will reach out to other cluster members as needed.
// The projectName passed here refers to the initial project from the API request which may differ from the network's project.
// If projectName is empty, get leases from all projects.
func (n *bridge) Leases(projectName string, clientType request.ClientType) ([]api.NetworkLease, error) {
var err error
var projectMacs []string
instanceProjects := make(map[string]string)
leases := []api.NetworkLease{}

// 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 {
if projectName == n.project || projectName == "" {
// Add our own gateway IPs.
for _, addr := range []string{n.config["ipv4.address"], n.config["ipv6.address"]} {
ip, _, _ := net.ParseCIDR(addr)
Expand Down Expand Up @@ -3486,6 +3488,7 @@ func (n *bridge) Leases(projectName string, clientType request.ClientType) ([]ap
Hostname: fmt.Sprintf("%s-%s.uplink", projectName, network.Name),
Address: v,
Type: "uplink",
Project: projectName,
})
}
}
Expand All @@ -3494,13 +3497,20 @@ func (n *bridge) Leases(projectName string, clientType request.ClientType) ([]ap
}

// Get all the instances in the requested project that are connected to this network.
filter := dbCluster.InstanceFilter{Project: &projectName}
var filter dbCluster.InstanceFilter
if projectName != "" {
filter = dbCluster.InstanceFilter{Project: &projectName}
}

err = UsedByInstanceDevices(n.state, n.Project(), n.Name(), n.Type(), func(inst db.InstanceArgs, nicName string, nicConfig map[string]string) error {
// Fill in the hwaddr from volatile.
if nicConfig["hwaddr"] == "" {
nicConfig["hwaddr"] = inst.Config[fmt.Sprintf("volatile.%s.hwaddr", nicName)]
}

// Keep instance project to use on dynamic leases.
instanceProjects[inst.Name] = inst.Project

// Record the MAC.
hwAddr, _ := net.ParseMAC(nicConfig["hwaddr"])
if hwAddr != nil {
Expand All @@ -3516,6 +3526,7 @@ func (n *bridge) Leases(projectName string, clientType request.ClientType) ([]ap
Hwaddr: hwAddr.String(),
Type: "static",
Location: inst.Node,
Project: inst.Project,
})
}

Expand All @@ -3527,6 +3538,7 @@ func (n *bridge) Leases(projectName string, clientType request.ClientType) ([]ap
Hwaddr: hwAddr.String(),
Type: "static",
Location: inst.Node,
Project: inst.Project,
})
}

Expand All @@ -3541,6 +3553,7 @@ func (n *bridge) Leases(projectName string, clientType request.ClientType) ([]ap
Hwaddr: hwAddr.String(),
Type: "dynamic",
Location: inst.Node,
Project: inst.Project,
})
}
}
Expand Down Expand Up @@ -3607,6 +3620,7 @@ func (n *bridge) Leases(projectName string, clientType request.ClientType) ([]ap
Hwaddr: macStr,
Type: "dynamic",
Location: n.state.ServerName,
Project: instanceProjects[fields[3]],
})
}
}
Expand Down
11 changes: 9 additions & 2 deletions lxd/network/driver_ovn.go
Original file line number Diff line number Diff line change
Expand Up @@ -5434,12 +5434,13 @@ func (n *ovn) LoadBalancerDelete(listenAddress string, clientType request.Client
}

// Leases returns a list of leases for the OVN network. Those are directly extracted from the OVN database.
// If projectName is empty, get leases from all projects.
func (n *ovn) Leases(projectName string, clientType request.ClientType) ([]api.NetworkLease, error) {
var err error
leases := []api.NetworkLease{}

// If requested project matches network's project then include gateway IPs.
if projectName == n.project {
if projectName == n.project || projectName == "" {
// Add our own gateway IPs.
for _, addr := range []string{n.config["ipv4.address"], n.config["ipv6.address"]} {
ip, _, _ := net.ParseCIDR(addr)
Expand All @@ -5448,13 +5449,18 @@ func (n *ovn) Leases(projectName string, clientType request.ClientType) ([]api.N
Hostname: fmt.Sprintf("%s.gw", n.Name()),
Address: ip.String(),
Type: "gateway",
Project: n.project,
})
}
}
}

// Get all the instances in the requested project that are connected to this network.
filter := dbCluster.InstanceFilter{Project: &projectName}
var filter dbCluster.InstanceFilter
if projectName != "" {
filter = dbCluster.InstanceFilter{Project: &projectName}
}

err = UsedByInstanceDevices(n.state, n.Project(), n.Name(), n.Type(), func(inst db.InstanceArgs, nicName string, nicConfig map[string]string) error {
// Get the instance UUID needed for OVN port name generation.
instanceUUID := inst.Config["volatile.uuid"]
Expand Down Expand Up @@ -5488,6 +5494,7 @@ func (n *ovn) Leases(projectName string, clientType request.ClientType) ([]api.N
Hwaddr: hwAddr.String(),
Type: leaseType,
Location: inst.Node,
Project: inst.Project,
})
}

Expand Down
27 changes: 21 additions & 6 deletions lxd/network_allocations.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"net"
"net/http"
"strings"

"github.com/canonical/lxd/lxd/auth"
clusterRequest "github.com/canonical/lxd/lxd/cluster/request"
Expand All @@ -30,7 +31,7 @@ var networkAllocationsCmd = APIEndpoint{

// swagger:operation GET /1.0/network-allocations network-allocations network_allocations_get
//
// Get the network allocations in use (`network`, `network-forward` and `load-balancer` and `instance`)
// Get the network allocations in use (`network`, `network-forward`, `load-balancer`, `uplink` and `instance`)
//
// Returns a list of network allocations in use by a LXD deployment.
//
Expand Down Expand Up @@ -173,27 +174,39 @@ func networkAllocationsGet(d *Daemon, r *http.Request) response.Response {
UsedBy: api.NewURL().Path(version.APIVersion, "networks", networkName).Project(projectName).String(),
Type: "network",
NAT: shared.IsTrue(netConf[fmt.Sprintf("%s.nat", keyPrefix)]),
Network: networkName,
})
}

leases, err := n.Leases(projectName, clusterRequest.ClientTypeNormal)
leases, err := n.Leases("", clusterRequest.ClientTypeNormal)
if err != nil && !errors.Is(err, network.ErrNotImplemented) {
return response.SmartError(fmt.Errorf("Failed getting leases for network %q in project %q: %w", networkName, projectName, err))
return response.SmartError(fmt.Errorf("Failed getting leases for network %q: %w", networkName, err))
}

for _, lease := range leases {
if shared.ValueInSlice(lease.Type, []string{"static", "dynamic"}) {
if shared.ValueInSlice(lease.Type, []string{"static", "dynamic", "uplink"}) {
cidrAddr, nat, err := ipToCIDR(lease.Address, netConf)
if err != nil {
return response.SmartError(err)
}

var allocationType, usedBy string
if lease.Type == "uplink" {
allocationType = "uplink"
networkName := strings.TrimSuffix(strings.TrimPrefix(lease.Hostname, lease.Project+"-"), ".uplink")
usedBy = api.NewURL().Path(version.APIVersion, "networks", networkName).Project(lease.Project).String()
} else {
allocationType = "instance"
usedBy = api.NewURL().Path(version.APIVersion, "instances", lease.Hostname).Project(lease.Project).String()
}

result = append(result, api.NetworkAllocations{
Address: cidrAddr,
UsedBy: api.NewURL().Path(version.APIVersion, "instances", lease.Hostname).Project(projectName).String(),
Type: "instance",
UsedBy: usedBy,
Type: allocationType,
Hwaddr: lease.Hwaddr,
NAT: nat,
Network: networkName,
})
}
}
Expand Down Expand Up @@ -222,6 +235,7 @@ func networkAllocationsGet(d *Daemon, r *http.Request) response.Response {
UsedBy: api.NewURL().Path(version.APIVersion, "networks", networkName, "forwards", forward.ListenAddress).Project(projectName).String(),
Type: "network-forward",
NAT: false, // Network forwards are ingress and so aren't affected by SNAT.
Network: networkName,
},
)
}
Expand Down Expand Up @@ -250,6 +264,7 @@ func networkAllocationsGet(d *Daemon, r *http.Request) response.Response {
UsedBy: api.NewURL().Path(version.APIVersion, "networks", networkName, "load-balancers", loadBalancer.ListenAddress).Project(projectName).String(),
Type: "network-load-balancer",
NAT: false, // Network load-balancers are ingress and so aren't affected by SNAT.
Network: networkName,
},
)
}
Expand Down
22 changes: 13 additions & 9 deletions po/ar.po
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: lxd\n"
"Report-Msgid-Bugs-To: [email protected]\n"
"POT-Creation-Date: 2024-10-15 14:52+0100\n"
"POT-Creation-Date: 2024-10-15 13:13-0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
Expand Down Expand Up @@ -1704,7 +1704,7 @@ msgstr ""
#: lxc/network_acl.go:235 lxc/network_acl.go:291 lxc/network_acl.go:364
#: lxc/network_acl.go:461 lxc/network_acl.go:549 lxc/network_acl.go:592
#: lxc/network_acl.go:731 lxc/network_acl.go:788 lxc/network_acl.go:845
#: lxc/network_acl.go:860 lxc/network_acl.go:997 lxc/network_allocations.go:51
#: lxc/network_acl.go:860 lxc/network_acl.go:997 lxc/network_allocations.go:53
#: lxc/network_forward.go:33 lxc/network_forward.go:90
#: lxc/network_forward.go:179 lxc/network_forward.go:256
#: lxc/network_forward.go:404 lxc/network_forward.go:489
Expand Down Expand Up @@ -2429,7 +2429,7 @@ msgstr ""
#: lxc/cluster.go:125 lxc/cluster.go:978 lxc/cluster_group.go:442
#: lxc/config_template.go:275 lxc/config_trust.go:352 lxc/config_trust.go:434
#: lxc/image.go:1116 lxc/image_alias.go:157 lxc/list.go:133 lxc/network.go:1009
#: lxc/network.go:1108 lxc/network_acl.go:98 lxc/network_allocations.go:57
#: lxc/network.go:1108 lxc/network_acl.go:98 lxc/network_allocations.go:59
#: lxc/network_forward.go:93 lxc/network_load_balancer.go:97
#: lxc/network_peer.go:85 lxc/network_zone.go:89 lxc/network_zone.go:770
#: lxc/operation.go:109 lxc/profile.go:707 lxc/project.go:474
Expand Down Expand Up @@ -2651,7 +2651,7 @@ msgstr ""
msgid "Group ID to run the command as (default 0)"
msgstr ""

#: lxc/network_allocations.go:28
#: lxc/network_allocations.go:29
msgid "HARDWARE ADDRESS"
msgstr ""

Expand Down Expand Up @@ -3324,7 +3324,7 @@ msgid ""
" Defaults to -1 (unlimited). Use 0 to limit to the column header size."
msgstr ""

#: lxc/network_allocations.go:50 lxc/network_allocations.go:51
#: lxc/network_allocations.go:52 lxc/network_allocations.go:53
msgid "List network allocations in use"
msgstr ""

Expand Down Expand Up @@ -4035,10 +4035,14 @@ msgstr ""
msgid "NAME"
msgstr ""

#: lxc/network_allocations.go:27
#: lxc/network_allocations.go:28
msgid "NAT"
msgstr ""

#: lxc/network_allocations.go:26
msgid "NETWORK"
msgstr ""

#: lxc/project.go:573
msgid "NETWORK ZONES"
msgstr ""
Expand Down Expand Up @@ -4997,15 +5001,15 @@ msgstr ""
msgid "Role (admin or read-only)"
msgstr ""

#: lxc/network_allocations.go:58
#: lxc/network_allocations.go:60
msgid "Run again a specific project"
msgstr ""

#: lxc/action.go:138
msgid "Run against all instances"
msgstr ""

#: lxc/network_allocations.go:59
#: lxc/network_allocations.go:61
msgid "Run against all projects"
msgstr ""

Expand Down Expand Up @@ -5783,7 +5787,7 @@ msgstr ""

#: lxc/auth.go:967 lxc/config_trust.go:408 lxc/image.go:1141
#: lxc/image_alias.go:236 lxc/list.go:579 lxc/network.go:1082
#: lxc/network.go:1164 lxc/network_allocations.go:26 lxc/operation.go:172
#: lxc/network.go:1164 lxc/network_allocations.go:27 lxc/operation.go:172
#: lxc/storage_volume.go:1736 lxc/warning.go:216
msgid "TYPE"
msgstr ""
Expand Down
Loading
Loading