[lxc-devel] [lxd/master] Add network state API

monstermunchkin on Github lxc-bot at linuxcontainers.org
Fri Jun 22 08:48:38 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180622/4a5cdaa3/attachment.bin>
-------------- next part --------------
From 2613eb60df419c1854610cceacf06bb83c3804d1 Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Fri, 22 Jun 2018 09:38:14 +0200
Subject: [PATCH 1/2] lxd,shared: Move parseNumberFromFile to shared

Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
 lxd/util/resources.go | 32 +++++++++-----------------------
 shared/util.go        | 15 +++++++++++++++
 2 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/lxd/util/resources.go b/lxd/util/resources.go
index 708062693..2b1f2b99a 100644
--- a/lxd/util/resources.go
+++ b/lxd/util/resources.go
@@ -8,6 +8,7 @@ import (
 	"strconv"
 	"strings"
 
+	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/api"
 )
 
@@ -21,21 +22,6 @@ type thread struct {
 	frequencyTurbo uint64
 }
 
-func parseNumberFromFile(file string) (int64, error) {
-	buf, err := ioutil.ReadFile(file)
-	if err != nil {
-		return int64(0), err
-	}
-
-	str := strings.TrimSpace(string(buf))
-	nr, err := strconv.Atoi(str)
-	if err != nil {
-		return int64(0), err
-	}
-
-	return int64(nr), nil
-}
-
 func parseCpuinfo() ([]thread, error) {
 	f, err := os.Open("/proc/cpuinfo")
 	if err != nil {
@@ -67,7 +53,7 @@ func parseCpuinfo() ([]thread, error) {
 			t.ID = uint64(id)
 
 			path := fmt.Sprintf("/sys/devices/system/cpu/cpu%d/topology/core_id", t.ID)
-			coreID, err := parseNumberFromFile(path)
+			coreID, err := shared.ParseNumberFromFile(path)
 			if err != nil {
 				return nil, err
 			}
@@ -75,7 +61,7 @@ func parseCpuinfo() ([]thread, error) {
 			t.coreID = uint64(coreID)
 
 			path = fmt.Sprintf("/sys/devices/system/cpu/cpu%d/topology/physical_package_id", t.ID)
-			sockID, err := parseNumberFromFile(path)
+			sockID, err := shared.ParseNumberFromFile(path)
 			if err != nil {
 				return nil, err
 			}
@@ -83,7 +69,7 @@ func parseCpuinfo() ([]thread, error) {
 			t.socketID = uint64(sockID)
 
 			path = fmt.Sprintf("/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", t.ID)
-			freq, err := parseNumberFromFile(path)
+			freq, err := shared.ParseNumberFromFile(path)
 			if err != nil {
 				if !os.IsNotExist(err) {
 					return nil, err
@@ -93,7 +79,7 @@ func parseCpuinfo() ([]thread, error) {
 			}
 
 			path = fmt.Sprintf("/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", t.ID)
-			freq, err = parseNumberFromFile(path)
+			freq, err = shared.ParseNumberFromFile(path)
 			if err != nil {
 				if !os.IsNotExist(err) {
 					return nil, err
@@ -179,7 +165,7 @@ func parseSysDevSystemCPU() ([]thread, error) {
 		t := thread{}
 		t.ID = uint64(idx)
 		path := fmt.Sprintf("/sys/devices/system/cpu/cpu%d/topology/core_id", t.ID)
-		coreID, err := parseNumberFromFile(path)
+		coreID, err := shared.ParseNumberFromFile(path)
 		if err != nil {
 			return nil, err
 		}
@@ -187,7 +173,7 @@ func parseSysDevSystemCPU() ([]thread, error) {
 		t.coreID = uint64(coreID)
 
 		path = fmt.Sprintf("/sys/devices/system/cpu/cpu%d/topology/physical_package_id", t.ID)
-		sockID, err := parseNumberFromFile(path)
+		sockID, err := shared.ParseNumberFromFile(path)
 		if err != nil {
 			return nil, err
 		}
@@ -195,7 +181,7 @@ func parseSysDevSystemCPU() ([]thread, error) {
 		t.socketID = uint64(sockID)
 
 		path = fmt.Sprintf("/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", t.ID)
-		freq, err := parseNumberFromFile(path)
+		freq, err := shared.ParseNumberFromFile(path)
 		if err != nil {
 			if !os.IsNotExist(err) {
 				return nil, err
@@ -205,7 +191,7 @@ func parseSysDevSystemCPU() ([]thread, error) {
 		}
 
 		path = fmt.Sprintf("/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", t.ID)
-		freq, err = parseNumberFromFile(path)
+		freq, err = shared.ParseNumberFromFile(path)
 		if err != nil {
 			if !os.IsNotExist(err) {
 				return nil, err
diff --git a/shared/util.go b/shared/util.go
index 8b264081a..61a834324 100644
--- a/shared/util.go
+++ b/shared/util.go
@@ -1047,3 +1047,18 @@ func downloadFileSha(httpClient *http.Client, useragent string, progress func(pr
 
 	return size, nil
 }
+
+func ParseNumberFromFile(file string) (int64, error) {
+	buf, err := ioutil.ReadFile(file)
+	if err != nil {
+		return int64(0), err
+	}
+
+	str := strings.TrimSpace(string(buf))
+	nr, err := strconv.Atoi(str)
+	if err != nil {
+		return int64(0), err
+	}
+
+	return int64(nr), nil
+}

From 44f9e0ffc35d5a09d8fa7a9e7ca1b66f956f0ea4 Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Fri, 22 Jun 2018 09:45:04 +0200
Subject: [PATCH 2/2] lxd,shared: Add network state API

Resolves #4665

Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
 lxd/api_1.0.go        |  1 +
 lxd/networks.go       | 84 +++++++++++++++++++++++++++++++++++++++++++++++----
 shared/api/network.go | 20 ++++++++++++
 shared/version/api.go |  1 +
 4 files changed, 100 insertions(+), 6 deletions(-)

diff --git a/lxd/api_1.0.go b/lxd/api_1.0.go
index ad2bc7050..4853226c8 100644
--- a/lxd/api_1.0.go
+++ b/lxd/api_1.0.go
@@ -51,6 +51,7 @@ var api10 = []Command{
 	networksCmd,
 	networkCmd,
 	networkLeasesCmd,
+	networkStateCmd,
 	api10Cmd,
 	certificatesCmd,
 	certificateFingerprintCmd,
diff --git a/lxd/networks.go b/lxd/networks.go
index b3589c39a..cb06ae5e3 100644
--- a/lxd/networks.go
+++ b/lxd/networks.go
@@ -30,6 +30,31 @@ import (
 // Lock to prevent concurent networks creation
 var networkCreateLock sync.Mutex
 
+var networksCmd = Command{
+	name: "networks",
+	get:  networksGet,
+	post: networksPost,
+}
+
+var networkCmd = Command{
+	name:   "networks/{name}",
+	get:    networkGet,
+	delete: networkDelete,
+	post:   networkPost,
+	put:    networkPut,
+	patch:  networkPatch,
+}
+
+var networkLeasesCmd = Command{
+	name: "networks/{name}/leases",
+	get:  networkLeasesGet,
+}
+
+var networkStateCmd = Command{
+	name: "networks/{name}/state",
+	get:  networkStateGet,
+}
+
 // API endpoints
 func networksGet(d *Daemon, r *http.Request) Response {
 	recursion := util.IsRecursionRequest(r)
@@ -313,8 +338,6 @@ func doNetworksCreate(d *Daemon, req api.NetworksPost, withDatabase bool) error
 	return nil
 }
 
-var networksCmd = Command{name: "networks", get: networksGet, post: networksPost}
-
 func networkGet(d *Daemon, r *http.Request) Response {
 	// If a target was specified, forward the request to the relevant node.
 	response := ForwardedResponseIfTargetIsRemote(d, r)
@@ -626,8 +649,6 @@ func doNetworkUpdate(d *Daemon, name string, oldConfig map[string]string, req ap
 	return EmptySyncResponse
 }
 
-var networkCmd = Command{name: "networks/{name}", get: networkGet, delete: networkDelete, post: networkPost, put: networkPut, patch: networkPatch}
-
 func networkLeasesGet(d *Daemon, r *http.Request) Response {
 	name := mux.Vars(r)["name"]
 	leaseFile := shared.VarPath("networks", name, "dnsmasq.leases")
@@ -741,8 +762,6 @@ func networkLeasesGet(d *Daemon, r *http.Request) Response {
 	return SyncResponse(true, leases)
 }
 
-var networkLeasesCmd = Command{name: "networks/{name}/leases", get: networkLeasesGet}
-
 // The network structs and functions
 func networkLoadByName(s *state.State, name string) (*network, error) {
 	id, dbInfo, err := s.Cluster.NetworkGet(name)
@@ -806,6 +825,59 @@ func networkShutdown(s *state.State) error {
 	return nil
 }
 
+func networkStateGet(d *Daemon, r *http.Request) Response {
+	name := mux.Vars(r)["name"]
+
+	// Get some information
+	osInfo, _ := net.InterfaceByName(name)
+	_, dbInfo, _ := d.cluster.NetworkGet(name)
+
+	// Sanity check
+	if osInfo == nil && dbInfo == nil {
+		return NotFound(fmt.Errorf("Interface '%s' not found", name))
+	}
+
+	// Prepare the response
+	n := api.NetworkState{
+		MTU:    osInfo.MTU,
+		Hwaddr: osInfo.HardwareAddr.String(),
+	}
+	addrs, err := osInfo.Addrs()
+	if err != nil {
+		return SmartError(err)
+	}
+
+	for _, addr := range addrs {
+		n.Addresses = append(n.Addresses, addr.String())
+	}
+
+	n.Stats.BytesTransmitted, err = shared.ParseNumberFromFile(
+		fmt.Sprintf("/sys/class/net/%s/statistics/tx_bytes", name))
+	if err != nil {
+		return SmartError(err)
+	}
+
+	n.Stats.BytesReceived, err = shared.ParseNumberFromFile(
+		fmt.Sprintf("/sys/class/net/%s/statistics/rx_bytes", name))
+	if err != nil {
+		return SmartError(err)
+	}
+
+	n.Stats.PacketsTransmitted, err = shared.ParseNumberFromFile(
+		fmt.Sprintf("/sys/class/net/%s/statistics/tx_packets", name))
+	if err != nil {
+		return SmartError(err)
+	}
+
+	n.Stats.PacketsReceived, err = shared.ParseNumberFromFile(
+		fmt.Sprintf("/sys/class/net/%s/statistics/rx_packets", name))
+	if err != nil {
+		return SmartError(err)
+	}
+
+	return SyncResponse(true, n)
+}
+
 type network struct {
 	// Properties
 	db          *db.Node
diff --git a/shared/api/network.go b/shared/api/network.go
index 19a0eae19..d26208262 100644
--- a/shared/api/network.go
+++ b/shared/api/network.go
@@ -58,3 +58,23 @@ type NetworkLease struct {
 	Address  string `json:"address" yaml:"address"`
 	Type     string `json:"type" yaml:"type"`
 }
+
+// NetworkStateStats represents statistics about an interface
+//
+// API extension: network_state
+type NetworkStateStats struct {
+	BytesTransmitted   int64 `json:"bytes_transmitted" yaml:"bytes_transmitted"`
+	BytesReceived      int64 `json:"bytes_received" yaml:"bytes_received"`
+	PacketsTransmitted int64 `json:"packets_transmitted" yaml:"packets_transmitted"`
+	PacketsReceived    int64 `json:"packets_received" yaml:"packets_received"`
+}
+
+// NetworkState represents the state of an interface
+//
+// API extension: network_state
+type NetworkState struct {
+	MTU       int               `json:"mtu" yaml:"mtu"`
+	Hwaddr    string            `json:"hwaddr" yaml:"hwaddr"`
+	Addresses []string          `json:"addresses" yaml:"addresses"`
+	Stats     NetworkStateStats `json:"stats" yaml:"stats"`
+}
diff --git a/shared/version/api.go b/shared/version/api.go
index 2acf2831d..3c23bf0dc 100644
--- a/shared/version/api.go
+++ b/shared/version/api.go
@@ -110,6 +110,7 @@ var APIExtensions = []string{
 	"proxy_udp",
 	"clustering_join",
 	"proxy_tcp_udp_multi_port_handling",
+	"network_state",
 }
 
 // APIExtensionsCount returns the number of available API extensions.


More information about the lxc-devel mailing list