diff --git a/doc/api-extensions.md b/doc/api-extensions.md index c1aa436cae7c..5ae1f2ee72c9 100644 --- a/doc/api-extensions.md +++ b/doc/api-extensions.md @@ -2538,3 +2538,7 @@ Adds a new {config:option}`device-unix-hotplug-device-conf:subsystem` configurat ## `storage_ceph_osd_pool_size` This introduces the configuration keys {config:option}`storage-ceph-pool-conf:ceph.osd.pool_size`, and {config:option}`storage-cephfs-pool-conf:cephfs.osd_pool_size` to be used when adding or updating a `ceph` or `cephfs` storage pool to instruct LXD to create set the replication size for the underlying OSD pools. + +## `network_get_target` + +Adds optional `target` parameter to `GET /1.0/network`. When target is set, forward the request to the specified cluster member and return the non-managed interfaces from that member. diff --git a/doc/rest-api.yaml b/doc/rest-api.yaml index 23f3774f156b..f0e25d584aae 100644 --- a/doc/rest-api.yaml +++ b/doc/rest-api.yaml @@ -13884,6 +13884,11 @@ paths: in: query name: project type: string + - description: Cluster member name + example: lxd01 + in: query + name: target + type: string produces: - application/json responses: diff --git a/lxc/network.go b/lxc/network.go index dfaf2fc71752..738b77681ea7 100644 --- a/lxc/network.go +++ b/lxc/network.go @@ -995,6 +995,7 @@ type cmdNetworkList struct { network *cmdNetwork flagFormat string + flagTarget string } func (c *cmdNetworkList) command() *cobra.Command { @@ -1007,6 +1008,7 @@ func (c *cmdNetworkList) command() *cobra.Command { cmd.RunE = c.run cmd.Flags().StringVarP(&c.flagFormat, "format", "f", "table", i18n.G("Format (csv|json|table|yaml|compact)")+"``") + cmd.Flags().StringVar(&c.flagTarget, "target", "", i18n.G("Cluster member name")+"``") cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) != 0 { @@ -1044,7 +1046,14 @@ func (c *cmdNetworkList) run(cmd *cobra.Command, args []string) error { return errors.New(i18n.G("Filtering isn't supported yet")) } - networks, err := resource.server.GetNetworks() + client := resource.server + + // Targeting. + if c.flagTarget != "" { + client = client.UseTarget(c.flagTarget) + } + + networks, err := client.GetNetworks() if err != nil { return err } diff --git a/lxd/networks.go b/lxd/networks.go index 223c62dd1636..c32d03abbfbe 100644 --- a/lxd/networks.go +++ b/lxd/networks.go @@ -200,6 +200,11 @@ func networkAccessHandler(entitlement auth.Entitlement) func(d *Daemon, r *http. // description: Project name // type: string // example: default +// - in: query +// name: target +// description: Cluster member name +// type: string +// example: lxd01 // responses: // "200": // description: API endpoints @@ -231,6 +236,12 @@ func networkAccessHandler(entitlement auth.Entitlement) func(d *Daemon, r *http. func networksGet(d *Daemon, r *http.Request) response.Response { s := d.State() + // If a target was specified, forward the request to the relevant node. + resp := forwardedResponseIfTargetIsRemote(s, r) + if resp != nil { + return resp + } + requestProjectName := request.ProjectParam(r) effectiveProjectName, reqProject, err := project.NetworkProject(s.DB.Cluster, requestProjectName) if err != nil { diff --git a/shared/version/api.go b/shared/version/api.go index 7eff819c9332..79c5cfb41930 100644 --- a/shared/version/api.go +++ b/shared/version/api.go @@ -428,6 +428,7 @@ var APIExtensions = []string{ "unix_device_hotplug_ownership_inherit", "unix_device_hotplug_subsystem_device_option", "storage_ceph_osd_pool_size", + "network_get_target", } // APIExtensionsCount returns the number of available API extensions. diff --git a/test/includes/clustering.sh b/test/includes/clustering.sh index f963cb720559..f1bd360375a5 100644 --- a/test/includes/clustering.sh +++ b/test/includes/clustering.sh @@ -82,6 +82,7 @@ ip link set dev "${veth2}" name eth0 ip link set eth0 up ip addr add "10.1.1.10${id}/16" dev eth0 ip route add default via 10.1.1.1 +ip link add localBridge${id} type bridge EOF } diff --git a/test/suites/clustering.sh b/test/suites/clustering.sh index f9d101f8e0a1..16d1a42d5f94 100644 --- a/test/suites/clustering.sh +++ b/test/suites/clustering.sh @@ -1217,6 +1217,13 @@ test_clustering_network() { LXD_DIR="${LXD_ONE_DIR}" lxc config device remove c3 eth0 LXD_DIR="${LXD_ONE_DIR}" lxc config device add c3 eth0 nic hwaddr="${c1MAC}" nictype=bridged parent="${net}" + # Check networks local to a cluster member show up when targeting that member + # and hidden when targeting other cluster members. Setup is in includes/clustering.sh + LXD_DIR="${LXD_ONE_DIR}" lxc network list --target=node1 | grep localBridge1 + ! LXD_DIR="${LXD_ONE_DIR}" lxc network list --target=node1 | grep localBridge2 || false + ! LXD_DIR="${LXD_ONE_DIR}" lxc network list --target=node2 | grep localBridge1 || false + LXD_DIR="${LXD_ONE_DIR}" lxc network list --target=node2 | grep localBridge2 + # Cleanup instances and image. LXD_DIR="${LXD_ONE_DIR}" lxc delete -f c1 c2 c3 LXD_DIR="${LXD_ONE_DIR}" lxc image delete testimage