The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/8183

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
Will be useful for external consumption by MAAS.

Also improves error handling slightly.

Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
From 52e73d97455e075b5791e1448fbe0c9115ed1cf7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com>
Date: Tue, 24 Nov 2020 14:10:55 -0500
Subject: [PATCH] lxd/resources: Add GetNetworkState and GetNetworkCounters
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Will be useful for external consumption by MAAS.

Also improves error handling slightly.

Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
---
 lxd/device/nic_bridged.go |   7 +-
 lxd/device/nic_ovn.go     |   7 +-
 lxd/networks.go           |  12 +-
 lxd/networks_utils.go     | 180 ---------------------------
 lxd/resources/network.go  | 248 ++++++++++++++++++++++++++++++++++++++
 shared/network.go         |  51 --------
 6 files changed, 265 insertions(+), 240 deletions(-)

diff --git a/lxd/device/nic_bridged.go b/lxd/device/nic_bridged.go
index f79fd3549c..21f70b8a3d 100644
--- a/lxd/device/nic_bridged.go
+++ b/lxd/device/nic_bridged.go
@@ -26,6 +26,7 @@ import (
        "github.com/lxc/lxd/lxd/network"
        "github.com/lxc/lxd/lxd/network/openvswitch"
        "github.com/lxc/lxd/lxd/project"
+       "github.com/lxc/lxd/lxd/resources"
        "github.com/lxc/lxd/lxd/revert"
        "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
@@ -1192,7 +1193,11 @@ func (d *nicBridged) State() (*api.InstanceStateNetwork, 
error) {
 
        // Retrieve the host counters, as we report the values from the 
instance's point of view,
        // those counters need to be reversed below.
-       hostCounters := shared.NetworkGetCounters(d.config["host_name"])
+       hostCounters, err := resources.GetNetworkCounters(d.config["host_name"])
+       if err != nil {
+               return nil, errors.Wrapf(err, "Failed getting network interface 
counters")
+       }
+
        network := api.InstanceStateNetwork{
                Addresses: addresses,
                Counters: api.InstanceStateNetworkCounters{
diff --git a/lxd/device/nic_ovn.go b/lxd/device/nic_ovn.go
index 8669939e9a..415f5271cc 100644
--- a/lxd/device/nic_ovn.go
+++ b/lxd/device/nic_ovn.go
@@ -17,6 +17,7 @@ import (
        "github.com/lxc/lxd/lxd/network"
        "github.com/lxc/lxd/lxd/network/openvswitch"
        "github.com/lxc/lxd/lxd/project"
+       "github.com/lxc/lxd/lxd/resources"
        "github.com/lxc/lxd/lxd/revert"
        "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
@@ -586,7 +587,11 @@ func (d *nicOVN) State() (*api.InstanceStateNetwork, 
error) {
 
        // Retrieve the host counters, as we report the values from the 
instance's point of view,
        // those counters need to be reversed below.
-       hostCounters := shared.NetworkGetCounters(d.config["host_name"])
+       hostCounters, err := resources.GetNetworkCounters(d.config["host_name"])
+       if err != nil {
+               return nil, errors.Wrapf(err, "Failed getting network interface 
counters")
+       }
+
        network := api.InstanceStateNetwork{
                Addresses: addresses,
                Counters: api.InstanceStateNetworkCounters{
diff --git a/lxd/networks.go b/lxd/networks.go
index 09ea358629..dc444a9892 100644
--- a/lxd/networks.go
+++ b/lxd/networks.go
@@ -23,6 +23,7 @@ import (
        "github.com/lxc/lxd/lxd/network"
        "github.com/lxc/lxd/lxd/network/openvswitch"
        "github.com/lxc/lxd/lxd/project"
+       "github.com/lxc/lxd/lxd/resources"
        "github.com/lxc/lxd/lxd/response"
        "github.com/lxc/lxd/lxd/revert"
        "github.com/lxc/lxd/lxd/state"
@@ -1134,13 +1135,10 @@ func networkStateGet(d *Daemon, r *http.Request) 
response.Response {
 
        name := mux.Vars(r)["name"]
 
-       // Get some information
-       osInfo, _ := net.InterfaceByName(name)
-
-       // Sanity check
-       if osInfo == nil {
-               return response.NotFound(fmt.Errorf("Interface '%s' not found", 
name))
+       state, err := resources.GetNetworkState(name)
+       if err != nil {
+               return response.SmartError(err)
        }
 
-       return response.SyncResponse(true, networkGetState(*osInfo))
+       return response.SyncResponse(true, state)
 }
diff --git a/lxd/networks_utils.go b/lxd/networks_utils.go
index dc8e834353..35f4c16748 100644
--- a/lxd/networks_utils.go
+++ b/lxd/networks_utils.go
@@ -1,10 +1,7 @@
 package main
 
 import (
-       "fmt"
        "io/ioutil"
-       "net"
-       "path/filepath"
        "strconv"
        "strings"
 
@@ -13,8 +10,6 @@ import (
        "github.com/lxc/lxd/lxd/network"
        "github.com/lxc/lxd/lxd/project"
        "github.com/lxc/lxd/lxd/state"
-       "github.com/lxc/lxd/shared"
-       "github.com/lxc/lxd/shared/api"
        "github.com/lxc/lxd/shared/logger"
 )
 
@@ -70,178 +65,3 @@ func networkUpdateForkdnsServersTask(s *state.State, 
heartbeatData *cluster.APIH
 
        return nil
 }
-
-func networkGetState(netIf net.Interface) api.NetworkState {
-       netState := "down"
-       netType := "unknown"
-
-       if netIf.Flags&net.FlagBroadcast > 0 {
-               netType = "broadcast"
-       }
-
-       if netIf.Flags&net.FlagPointToPoint > 0 {
-               netType = "point-to-point"
-       }
-
-       if netIf.Flags&net.FlagLoopback > 0 {
-               netType = "loopback"
-       }
-
-       if netIf.Flags&net.FlagUp > 0 {
-               netState = "up"
-       }
-
-       network := api.NetworkState{
-               Addresses: []api.NetworkStateAddress{},
-               Counters:  api.NetworkStateCounters{},
-               Hwaddr:    netIf.HardwareAddr.String(),
-               Mtu:       netIf.MTU,
-               State:     netState,
-               Type:      netType,
-       }
-
-       // Populate address information.
-       addrs, err := netIf.Addrs()
-       if err == nil {
-               for _, addr := range addrs {
-                       fields := strings.SplitN(addr.String(), "/", 2)
-                       if len(fields) != 2 {
-                               continue
-                       }
-
-                       family := "inet"
-                       if strings.Contains(fields[0], ":") {
-                               family = "inet6"
-                       }
-
-                       scope := "global"
-                       if strings.HasPrefix(fields[0], "127") {
-                               scope = "local"
-                       }
-
-                       if fields[0] == "::1" {
-                               scope = "local"
-                       }
-
-                       if strings.HasPrefix(fields[0], "169.254") {
-                               scope = "link"
-                       }
-
-                       if strings.HasPrefix(fields[0], "fe80:") {
-                               scope = "link"
-                       }
-
-                       address := api.NetworkStateAddress{}
-                       address.Family = family
-                       address.Address = fields[0]
-                       address.Netmask = fields[1]
-                       address.Scope = scope
-
-                       network.Addresses = append(network.Addresses, address)
-               }
-       }
-
-       // Populate bond details.
-       bondPath := fmt.Sprintf("/sys/class/net/%s/bonding", netIf.Name)
-       if shared.PathExists(bondPath) {
-               bonding := api.NetworkStateBond{}
-
-               // Bond mode.
-               strValue, err := ioutil.ReadFile(filepath.Join(bondPath, 
"mode"))
-               if err == nil {
-                       bonding.Mode = 
strings.Split(strings.TrimSpace(string(strValue)), " ")[0]
-               }
-
-               // Bond transmit policy.
-               strValue, err = ioutil.ReadFile(filepath.Join(bondPath, 
"xmit_hash_policy"))
-               if err == nil {
-                       bonding.TransmitPolicy = 
strings.Split(strings.TrimSpace(string(strValue)), " ")[0]
-               }
-
-               // Up delay.
-               uintValue, err := readUint(filepath.Join(bondPath, "updelay"))
-               if err == nil {
-                       bonding.UpDelay = uintValue
-               }
-
-               // Down delay.
-               uintValue, err = readUint(filepath.Join(bondPath, "downdelay"))
-               if err == nil {
-                       bonding.DownDelay = uintValue
-               }
-
-               // MII frequency.
-               uintValue, err = readUint(filepath.Join(bondPath, "miimon"))
-               if err == nil {
-                       bonding.MIIFrequency = uintValue
-               }
-
-               // MII state.
-               strValue, err = ioutil.ReadFile(filepath.Join(bondPath, 
"mii_status"))
-               if err == nil {
-                       bonding.MIIState = strings.TrimSpace(string(strValue))
-               }
-
-               // Lower devices.
-               strValue, err = ioutil.ReadFile(filepath.Join(bondPath, 
"slaves"))
-               if err == nil {
-                       bonding.LowerDevices = 
strings.Split(strings.TrimSpace(string(strValue)), " ")
-               }
-
-               network.Bond = &bonding
-       }
-
-       // Populate bridge details.
-       bridgePath := fmt.Sprintf("/sys/class/net/%s/bridge", netIf.Name)
-       if shared.PathExists(bridgePath) {
-               bridge := api.NetworkStateBridge{}
-
-               // Bridge ID.
-               strValue, err := ioutil.ReadFile(filepath.Join(bridgePath, 
"bridge_id"))
-               if err == nil {
-                       bridge.ID = strings.TrimSpace(string(strValue))
-               }
-
-               // Bridge STP.
-               uintValue, err := readUint(filepath.Join(bridgePath, 
"stp_state"))
-               if err == nil {
-                       bridge.STP = uintValue == 1
-               }
-
-               // Bridge forward delay.
-               uintValue, err = readUint(filepath.Join(bridgePath, 
"forward_delay"))
-               if err == nil {
-                       bridge.ForwardDelay = uintValue
-               }
-
-               // Bridge default VLAN.
-               uintValue, err = readUint(filepath.Join(bridgePath, 
"default_pvid"))
-               if err == nil {
-                       bridge.VLANDefault = uintValue
-               }
-
-               // Bridge VLAN filtering.
-               uintValue, err = readUint(filepath.Join(bridgePath, 
"vlan_filtering"))
-               if err == nil {
-                       bridge.VLANFiltering = uintValue == 1
-               }
-
-               // Upper devices.
-               bridgeIfPath := fmt.Sprintf("/sys/class/net/%s/brif", 
netIf.Name)
-               if shared.PathExists(bridgeIfPath) {
-                       entries, err := ioutil.ReadDir(bridgeIfPath)
-                       if err == nil {
-                               bridge.UpperDevices = []string{}
-                               for _, entry := range entries {
-                                       bridge.UpperDevices = 
append(bridge.UpperDevices, entry.Name())
-                               }
-                       }
-               }
-
-               network.Bridge = &bridge
-       }
-
-       // Get counters.
-       network.Counters = shared.NetworkGetCounters(netIf.Name)
-       return network
-}
diff --git a/lxd/resources/network.go b/lxd/resources/network.go
index 3ab64405be..034e5b8190 100644
--- a/lxd/resources/network.go
+++ b/lxd/resources/network.go
@@ -1,8 +1,12 @@
 package resources
 
 import (
+       "fmt"
        "io/ioutil"
+       "net"
+       "os"
        "path/filepath"
+       "strconv"
        "strings"
 
        "github.com/jaypipes/pcidb"
@@ -428,3 +432,247 @@ func GetNetwork() (*api.ResourcesNetwork, error) {
 
        return &network, nil
 }
+
+// GetNetworkState returns the OS configuration for the network interface.
+func GetNetworkState(name string) (*api.NetworkState, error) {
+       // Get some information
+       netIf, err := net.InterfaceByName(name)
+       if err != nil {
+               return nil, fmt.Errorf("Network interface %q not found", name)
+       }
+
+       netState := "down"
+       netType := "unknown"
+
+       if netIf.Flags&net.FlagBroadcast > 0 {
+               netType = "broadcast"
+       }
+
+       if netIf.Flags&net.FlagPointToPoint > 0 {
+               netType = "point-to-point"
+       }
+
+       if netIf.Flags&net.FlagLoopback > 0 {
+               netType = "loopback"
+       }
+
+       if netIf.Flags&net.FlagUp > 0 {
+               netState = "up"
+       }
+
+       network := api.NetworkState{
+               Addresses: []api.NetworkStateAddress{},
+               Counters:  api.NetworkStateCounters{},
+               Hwaddr:    netIf.HardwareAddr.String(),
+               Mtu:       netIf.MTU,
+               State:     netState,
+               Type:      netType,
+       }
+
+       // Populate address information.
+       addrs, err := netIf.Addrs()
+       if err == nil {
+               for _, addr := range addrs {
+                       fields := strings.SplitN(addr.String(), "/", 2)
+                       if len(fields) != 2 {
+                               continue
+                       }
+
+                       family := "inet"
+                       if strings.Contains(fields[0], ":") {
+                               family = "inet6"
+                       }
+
+                       scope := "global"
+                       if strings.HasPrefix(fields[0], "127") {
+                               scope = "local"
+                       }
+
+                       if fields[0] == "::1" {
+                               scope = "local"
+                       }
+
+                       if strings.HasPrefix(fields[0], "169.254") {
+                               scope = "link"
+                       }
+
+                       if strings.HasPrefix(fields[0], "fe80:") {
+                               scope = "link"
+                       }
+
+                       address := api.NetworkStateAddress{}
+                       address.Family = family
+                       address.Address = fields[0]
+                       address.Netmask = fields[1]
+                       address.Scope = scope
+
+                       network.Addresses = append(network.Addresses, address)
+               }
+       }
+
+       // Populate bond details.
+       bondPath := fmt.Sprintf("/sys/class/net/%s/bonding", name)
+       if sysfsExists(bondPath) {
+               bonding := api.NetworkStateBond{}
+
+               // Bond mode.
+               strValue, err := ioutil.ReadFile(filepath.Join(bondPath, 
"mode"))
+               if err == nil {
+                       bonding.Mode = 
strings.Split(strings.TrimSpace(string(strValue)), " ")[0]
+               }
+
+               // Bond transmit policy.
+               strValue, err = ioutil.ReadFile(filepath.Join(bondPath, 
"xmit_hash_policy"))
+               if err == nil {
+                       bonding.TransmitPolicy = 
strings.Split(strings.TrimSpace(string(strValue)), " ")[0]
+               }
+
+               // Up delay.
+               uintValue, err := readUint(filepath.Join(bondPath, "updelay"))
+               if err == nil {
+                       bonding.UpDelay = uintValue
+               }
+
+               // Down delay.
+               uintValue, err = readUint(filepath.Join(bondPath, "downdelay"))
+               if err == nil {
+                       bonding.DownDelay = uintValue
+               }
+
+               // MII frequency.
+               uintValue, err = readUint(filepath.Join(bondPath, "miimon"))
+               if err == nil {
+                       bonding.MIIFrequency = uintValue
+               }
+
+               // MII state.
+               strValue, err = ioutil.ReadFile(filepath.Join(bondPath, 
"mii_status"))
+               if err == nil {
+                       bonding.MIIState = strings.TrimSpace(string(strValue))
+               }
+
+               // Lower devices.
+               strValue, err = ioutil.ReadFile(filepath.Join(bondPath, 
"slaves"))
+               if err == nil {
+                       bonding.LowerDevices = 
strings.Split(strings.TrimSpace(string(strValue)), " ")
+               }
+
+               network.Bond = &bonding
+       }
+
+       // Populate bridge details.
+       bridgePath := fmt.Sprintf("/sys/class/net/%s/bridge", name)
+       if sysfsExists(bridgePath) {
+               bridge := api.NetworkStateBridge{}
+
+               // Bridge ID.
+               strValue, err := ioutil.ReadFile(filepath.Join(bridgePath, 
"bridge_id"))
+               if err == nil {
+                       bridge.ID = strings.TrimSpace(string(strValue))
+               }
+
+               // Bridge STP.
+               uintValue, err := readUint(filepath.Join(bridgePath, 
"stp_state"))
+               if err == nil {
+                       bridge.STP = uintValue == 1
+               }
+
+               // Bridge forward delay.
+               uintValue, err = readUint(filepath.Join(bridgePath, 
"forward_delay"))
+               if err == nil {
+                       bridge.ForwardDelay = uintValue
+               }
+
+               // Bridge default VLAN.
+               uintValue, err = readUint(filepath.Join(bridgePath, 
"default_pvid"))
+               if err == nil {
+                       bridge.VLANDefault = uintValue
+               }
+
+               // Bridge VLAN filtering.
+               uintValue, err = readUint(filepath.Join(bridgePath, 
"vlan_filtering"))
+               if err == nil {
+                       bridge.VLANFiltering = uintValue == 1
+               }
+
+               // Upper devices.
+               bridgeIfPath := fmt.Sprintf("/sys/class/net/%s/brif", name)
+               if sysfsExists(bridgeIfPath) {
+                       entries, err := ioutil.ReadDir(bridgeIfPath)
+                       if err == nil {
+                               bridge.UpperDevices = []string{}
+                               for _, entry := range entries {
+                                       bridge.UpperDevices = 
append(bridge.UpperDevices, entry.Name())
+                               }
+                       }
+               }
+
+               network.Bridge = &bridge
+       }
+
+       // Get counters.
+       counters, err := GetNetworkCounters(name)
+       if err != nil {
+               return nil, err
+       }
+
+       network.Counters = *counters
+
+       return &network, nil
+}
+
+// GetNetworkCounters returns the current packet counters for the network 
interface.
+func GetNetworkCounters(name string) (*api.NetworkStateCounters, error) {
+       counters := api.NetworkStateCounters{}
+
+       // Get counters
+       content, err := ioutil.ReadFile("/proc/net/dev")
+       if err != nil {
+               if os.IsNotExist(err) {
+                       return &counters, nil
+               }
+
+               return nil, err
+       }
+
+       for _, line := range strings.Split(string(content), "\n") {
+               fields := strings.Fields(line)
+
+               if len(fields) != 17 {
+                       continue
+               }
+
+               intName := strings.TrimSuffix(fields[0], ":")
+               if intName != name {
+                       continue
+               }
+
+               rxBytes, err := strconv.ParseInt(fields[1], 10, 64)
+               if err != nil {
+                       return nil, err
+               }
+
+               rxPackets, err := strconv.ParseInt(fields[2], 10, 64)
+               if err != nil {
+                       return nil, err
+               }
+
+               txBytes, err := strconv.ParseInt(fields[9], 10, 64)
+               if err != nil {
+                       return nil, err
+               }
+
+               txPackets, err := strconv.ParseInt(fields[10], 10, 64)
+               if err != nil {
+                       return nil, err
+               }
+
+               counters.BytesSent = txBytes
+               counters.BytesReceived = rxBytes
+               counters.PacketsSent = txPackets
+               counters.PacketsReceived = rxPackets
+               break
+       }
+
+       return &counters, nil
+}
diff --git a/shared/network.go b/shared/network.go
index 3a49052850..c1ab480de9 100644
--- a/shared/network.go
+++ b/shared/network.go
@@ -9,14 +9,11 @@ import (
        "io/ioutil"
        "net"
        "net/http"
-       "strconv"
-       "strings"
        "sync"
        "time"
 
        "github.com/gorilla/websocket"
 
-       "github.com/lxc/lxd/shared/api"
        "github.com/lxc/lxd/shared/logger"
 )
 
@@ -501,51 +498,3 @@ func AllocatePort() (int, error) {
        defer l.Close()
        return l.Addr().(*net.TCPAddr).Port, nil
 }
-
-func NetworkGetCounters(ifName string) api.NetworkStateCounters {
-       counters := api.NetworkStateCounters{}
-       // Get counters
-       content, err := ioutil.ReadFile("/proc/net/dev")
-       if err == nil {
-               for _, line := range strings.Split(string(content), "\n") {
-                       fields := strings.Fields(line)
-
-                       if len(fields) != 17 {
-                               continue
-                       }
-
-                       intName := strings.TrimSuffix(fields[0], ":")
-                       if intName != ifName {
-                               continue
-                       }
-
-                       rxBytes, err := strconv.ParseInt(fields[1], 10, 64)
-                       if err != nil {
-                               continue
-                       }
-
-                       rxPackets, err := strconv.ParseInt(fields[2], 10, 64)
-                       if err != nil {
-                               continue
-                       }
-
-                       txBytes, err := strconv.ParseInt(fields[9], 10, 64)
-                       if err != nil {
-                               continue
-                       }
-
-                       txPackets, err := strconv.ParseInt(fields[10], 10, 64)
-                       if err != nil {
-                               continue
-                       }
-
-                       counters.BytesSent = txBytes
-                       counters.BytesReceived = rxBytes
-                       counters.PacketsSent = txPackets
-                       counters.PacketsReceived = rxPackets
-                       break
-               }
-       }
-
-       return counters
-}
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to