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

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) ===
Add a description field to networks. It can be changed with `lxc network edit`
From d7053f8c4e4a1c88d623710064a95fa21fda5d57 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.don...@canonical.com>
Date: Wed, 26 Apr 2017 11:05:07 +0200
Subject: [PATCH] Add description field to networks.

Signed-off-by: Alberto Donato <alberto.don...@canonical.com>
---
 doc/api-extensions.md  |  3 +++
 doc/rest-api.md        |  1 +
 lxc/network.go         |  3 ++-
 lxd/api_1.0.go         |  1 +
 lxd/db.go              |  1 +
 lxd/db_networks.go     | 23 ++++++++++++++++++-----
 lxd/db_update.go       |  6 ++++++
 lxd/networks.go        | 43 ++++++++++++++++++++++++-------------------
 shared/api/network.go  |  7 ++++---
 test/suites/network.sh | 11 +++++++++++
 10 files changed, 71 insertions(+), 28 deletions(-)
 mode change 100644 => 100755 test/suites/network.sh

diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index 8cf17f3..2c96f5d 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -264,3 +264,6 @@ places an upper limit on the amount of socket I/O allowed.
 This introduces a new tunnel.NAME.interface option for networks.
 
 This key control what host network interface is used for a VXLAN tunnel.
+
+## entity\_description
+This adds descriptions to entities like containers, snapshots, networks, 
storage pools and volumes.
diff --git a/doc/rest-api.md b/doc/rest-api.md
index 94a883c..8b92db3 100644
--- a/doc/rest-api.md
+++ b/doc/rest-api.md
@@ -1562,6 +1562,7 @@ Input:
 
     {
         "name": "my-network",
+        "description": "My network",
         "config": {
             "ipv4.address": "none",
             "ipv6.address": "2001:470:b368:4242::1/64",
diff --git a/lxc/network.go b/lxc/network.go
index 920a67e..0fdea24 100644
--- a/lxc/network.go
+++ b/lxc/network.go
@@ -447,7 +447,7 @@ func (c *networkCmd) doNetworkList(config *lxd.Config, args 
[]string) error {
                }
 
                strUsedBy := fmt.Sprintf("%d", len(network.UsedBy))
-               data = append(data, []string{network.Name, network.Type, 
strManaged, strUsedBy})
+               data = append(data, []string{network.Name, network.Type, 
strManaged, network.Description, strUsedBy})
        }
 
        table := tablewriter.NewWriter(os.Stdout)
@@ -458,6 +458,7 @@ func (c *networkCmd) doNetworkList(config *lxd.Config, args 
[]string) error {
                i18n.G("NAME"),
                i18n.G("TYPE"),
                i18n.G("MANAGED"),
+               i18n.G("DESCRIPTION"),
                i18n.G("USED BY")})
        sort.Sort(byName(data))
        table.AppendBulk(data)
diff --git a/lxd/api_1.0.go b/lxd/api_1.0.go
index bdf7c54..122a2c7 100644
--- a/lxd/api_1.0.go
+++ b/lxd/api_1.0.go
@@ -104,6 +104,7 @@ func api10Get(d *Daemon, r *http.Request) Response {
                        "storage_lvm_use_thinpool",
                        "storage_rsync_bwlimit",
                        "network_vxlan_interface",
+                       "entity_description",
                },
                APIStatus:  "stable",
                APIVersion: version.APIVersion,
diff --git a/lxd/db.go b/lxd/db.go
index 923c293..49461dc 100644
--- a/lxd/db.go
+++ b/lxd/db.go
@@ -128,6 +128,7 @@ CREATE TABLE IF NOT EXISTS images_source (
 CREATE TABLE IF NOT EXISTS networks (
     id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
     name VARCHAR(255) NOT NULL,
+    description TEXT,
     UNIQUE (name)
 );
 CREATE TABLE IF NOT EXISTS networks_config (
diff --git a/lxd/db_networks.go b/lxd/db_networks.go
index 3040617..425edf6 100644
--- a/lxd/db_networks.go
+++ b/lxd/db_networks.go
@@ -29,11 +29,12 @@ func dbNetworks(db *sql.DB) ([]string, error) {
 }
 
 func dbNetworkGet(db *sql.DB, name string) (int64, *api.Network, error) {
+       description := sql.NullString{}
        id := int64(-1)
 
-       q := "SELECT id FROM networks WHERE name=?"
+       q := "SELECT id, description FROM networks WHERE name=?"
        arg1 := []interface{}{name}
-       arg2 := []interface{}{&id}
+       arg2 := []interface{}{&id, &description}
        err := dbQueryRowScan(db, q, arg1, arg2)
        if err != nil {
                return -1, nil, err
@@ -49,6 +50,7 @@ func dbNetworkGet(db *sql.DB, name string) (int64, 
*api.Network, error) {
                Managed: true,
                Type:    "bridge",
        }
+       network.Description = description.String
        network.Config = config
 
        return id, &network, nil
@@ -140,13 +142,13 @@ func dbNetworkConfigGet(db *sql.DB, id int64) 
(map[string]string, error) {
        return config, nil
 }
 
-func dbNetworkCreate(db *sql.DB, name string, config map[string]string) 
(int64, error) {
+func dbNetworkCreate(db *sql.DB, name, description string, config 
map[string]string) (int64, error) {
        tx, err := dbBegin(db)
        if err != nil {
                return -1, err
        }
 
-       result, err := tx.Exec("INSERT INTO networks (name) VALUES (?)", name)
+       result, err := tx.Exec("INSERT INTO networks (name, description) VALUES 
(?, ?)", name, description)
        if err != nil {
                tx.Rollback()
                return -1, err
@@ -172,7 +174,7 @@ func dbNetworkCreate(db *sql.DB, name string, config 
map[string]string) (int64,
        return id, nil
 }
 
-func dbNetworkUpdate(db *sql.DB, name string, config map[string]string) error {
+func dbNetworkUpdate(db *sql.DB, name, description string, config 
map[string]string) error {
        id, _, err := dbNetworkGet(db, name)
        if err != nil {
                return err
@@ -183,6 +185,12 @@ func dbNetworkUpdate(db *sql.DB, name string, config 
map[string]string) error {
                return err
        }
 
+       err = dbNetworkUpdateDescription(tx, id, description)
+       if err != nil {
+               tx.Rollback()
+               return err
+       }
+
        err = dbNetworkConfigClear(tx, id)
        if err != nil {
                tx.Rollback()
@@ -198,6 +206,11 @@ func dbNetworkUpdate(db *sql.DB, name string, config 
map[string]string) error {
        return txCommit(tx)
 }
 
+func dbNetworkUpdateDescription(tx *sql.Tx, id int64, description string) 
error {
+       _, err := tx.Exec("UPDATE networks SET description=? WHERE id=?", 
description, id)
+       return err
+}
+
 func dbNetworkConfigAdd(tx *sql.Tx, id int64, config map[string]string) error {
        str := fmt.Sprintf("INSERT INTO networks_config (network_id, key, 
value) VALUES(?, ?, ?)")
        stmt, err := tx.Prepare(str)
diff --git a/lxd/db_update.go b/lxd/db_update.go
index ee1dc71..72c60d5 100644
--- a/lxd/db_update.go
+++ b/lxd/db_update.go
@@ -69,6 +69,7 @@ var dbUpdates = []dbUpdate{
        {version: 33, run: dbUpdateFromV32},
        {version: 34, run: dbUpdateFromV33},
        {version: 35, run: dbUpdateFromV34},
+       {version: 36, run: dbUpdateFromV35},
 }
 
 type dbUpdate struct {
@@ -125,6 +126,11 @@ func dbUpdatesApplyAll(d *Daemon) error {
 }
 
 // Schema updates begin here
+func dbUpdateFromV35(currentVersion int, version int, d *Daemon) error {
+       _, err := d.db.Exec("ALTER TABLE networks ADD COLUMN description TEXT;")
+       return err
+}
+
 func dbUpdateFromV34(currentVersion int, version int, d *Daemon) error {
        stmt := `
 CREATE TABLE IF NOT EXISTS storage_pools (
diff --git a/lxd/networks.go b/lxd/networks.go
index 1f54977..cefcb38 100644
--- a/lxd/networks.go
+++ b/lxd/networks.go
@@ -126,7 +126,7 @@ func networksPost(d *Daemon, r *http.Request) Response {
        }
 
        // Create the database entry
-       _, err = dbNetworkCreate(d.db, req.Name, req.Config)
+       _, err = dbNetworkCreate(d.db, req.Name, req.Description, req.Config)
        if err != nil {
                return InternalError(
                        fmt.Errorf("Error inserting %s into database: %s", 
req.Name, err))
@@ -157,7 +157,7 @@ func networkGet(d *Daemon, r *http.Request) Response {
                return SmartError(err)
        }
 
-       etag := []interface{}{n.Name, n.Managed, n.Type, n.Config}
+       etag := []interface{}{n.Name, n.Description, n.Managed, n.Type, 
n.Config}
 
        return SyncResponseETag(true, &n, etag)
 }
@@ -201,6 +201,7 @@ func doNetworkGet(d *Daemon, name string) (api.Network, 
error) {
        } else if dbInfo != nil || 
shared.PathExists(fmt.Sprintf("/sys/class/net/%s/bridge", n.Name)) {
                if dbInfo != nil {
                        n.Managed = true
+                       n.Description = dbInfo.Description
                        n.Config = dbInfo.Config
                }
 
@@ -301,7 +302,7 @@ func networkPut(d *Daemon, r *http.Request) Response {
        }
 
        // Validate the ETag
-       etag := []interface{}{dbInfo.Name, dbInfo.Managed, dbInfo.Type, 
dbInfo.Config}
+       etag := []interface{}{dbInfo.Name, dbInfo.Managed, dbInfo.Type, 
dbInfo.Description, dbInfo.Config}
 
        err = etagCheck(r, etag)
        if err != nil {
@@ -313,7 +314,7 @@ func networkPut(d *Daemon, r *http.Request) Response {
                return BadRequest(err)
        }
 
-       return doNetworkUpdate(d, name, dbInfo.Config, req.Config)
+       return doNetworkUpdate(d, name, dbInfo.Config, req)
 }
 
 func networkPatch(d *Daemon, r *http.Request) Response {
@@ -326,7 +327,7 @@ func networkPatch(d *Daemon, r *http.Request) Response {
        }
 
        // Validate the ETag
-       etag := []interface{}{dbInfo.Name, dbInfo.Managed, dbInfo.Type, 
dbInfo.Config}
+       etag := []interface{}{dbInfo.Name, dbInfo.Managed, dbInfo.Type, 
dbInfo.Description, dbInfo.Config}
 
        err = etagCheck(r, etag)
        if err != nil {
@@ -350,20 +351,20 @@ func networkPatch(d *Daemon, r *http.Request) Response {
                }
        }
 
-       return doNetworkUpdate(d, name, dbInfo.Config, req.Config)
+       return doNetworkUpdate(d, name, dbInfo.Config, req)
 }
 
-func doNetworkUpdate(d *Daemon, name string, oldConfig map[string]string, 
newConfig map[string]string) Response {
+func doNetworkUpdate(d *Daemon, name string, oldConfig map[string]string, req 
api.NetworkPut) Response {
        // Validate the configuration
-       err := networkValidateConfig(name, newConfig)
+       err := networkValidateConfig(name, req.Config)
        if err != nil {
                return BadRequest(err)
        }
 
        // When switching to a fan bridge, auto-detect the underlay
-       if newConfig["bridge.mode"] == "fan" {
-               if newConfig["fan.underlay_subnet"] == "" {
-                       newConfig["fan.underlay_subnet"] = "auto"
+       if req.Config["bridge.mode"] == "fan" {
+               if req.Config["fan.underlay_subnet"] == "" {
+                       req.Config["fan.underlay_subnet"] = "auto"
                }
        }
 
@@ -373,7 +374,7 @@ func doNetworkUpdate(d *Daemon, name string, oldConfig 
map[string]string, newCon
                return NotFound
        }
 
-       err = n.Update(api.NetworkPut{Config: newConfig})
+       err = n.Update(req)
        if err != nil {
                return SmartError(err)
        }
@@ -390,7 +391,7 @@ func networkLoadByName(d *Daemon, name string) (*network, 
error) {
                return nil, err
        }
 
-       n := network{daemon: d, id: id, name: name, config: dbInfo.Config}
+       n := network{daemon: d, id: id, name: name, description: 
dbInfo.Description, config: dbInfo.Config}
 
        return &n, nil
 }
@@ -421,9 +422,10 @@ func networkStartup(d *Daemon) error {
 
 type network struct {
        // Properties
-       daemon *Daemon
-       id     int64
-       name   string
+       daemon      *Daemon
+       id          int64
+       name        string
+       description string
 
        // config
        config map[string]string
@@ -1271,6 +1273,7 @@ func (n *network) Update(newNetwork api.NetworkPut) error 
{
 
        // Backup the current state
        oldConfig := map[string]string{}
+       oldDescription := n.description
        err = shared.DeepCopy(&n.config, &oldConfig)
        if err != nil {
                return err
@@ -1284,6 +1287,7 @@ func (n *network) Update(newNetwork api.NetworkPut) error 
{
        defer func() {
                if undoChanges {
                        n.config = oldConfig
+                       n.description = oldDescription
                }
        }()
 
@@ -1315,7 +1319,7 @@ func (n *network) Update(newNetwork api.NetworkPut) error 
{
        }
 
        // Skip on no change
-       if len(changedConfig) == 0 {
+       if len(changedConfig) == 0 && newNetwork.Description == n.description {
                return nil
        }
 
@@ -1351,11 +1355,12 @@ func (n *network) Update(newNetwork api.NetworkPut) 
error {
                }
        }
 
-       // Apply the new configuration
+       // Apply changes
        n.config = newConfig
+       n.description = newNetwork.Description
 
        // Update the database
-       err = dbNetworkUpdate(n.daemon.db, n.name, n.config)
+       err = dbNetworkUpdate(n.daemon.db, n.name, n.description, n.config)
        if err != nil {
                return err
        }
diff --git a/shared/api/network.go b/shared/api/network.go
index 21db460..d5c5590 100644
--- a/shared/api/network.go
+++ b/shared/api/network.go
@@ -22,6 +22,7 @@ type NetworkPost struct {
 //
 // API extension: network
 type NetworkPut struct {
+       Description string   `json:"description" yaml:"description"`
        Config map[string]string `json:"config" yaml:"config"`
 }
 
@@ -29,9 +30,9 @@ type NetworkPut struct {
 type Network struct {
        NetworkPut `yaml:",inline"`
 
-       Name   string   `json:"name" yaml:"name"`
-       Type   string   `json:"type" yaml:"type"`
-       UsedBy []string `json:"used_by" yaml:"used_by"`
+       Name        string   `json:"name" yaml:"name"`
+       Type        string   `json:"type" yaml:"type"`
+       UsedBy      []string `json:"used_by" yaml:"used_by"`
 
        // API extension: network
        Managed bool `json:"managed" yaml:"managed"`
diff --git a/test/suites/network.sh b/test/suites/network.sh
old mode 100644
new mode 100755
index fe66bea..6f8fc47
--- a/test/suites/network.sh
+++ b/test/suites/network.sh
@@ -1,6 +1,9 @@
 #!/bin/sh
 
 test_network() {
+  # shellcheck disable=2039
+  local config_file
+
   ensure_import_testimage
   ensure_has_localhost_remote "${LXD_ADDR}"
 
@@ -15,6 +18,14 @@ test_network() {
   lxc network set lxdt$$ ipv6.dhcp.stateful true
   lxc network delete lxdt$$
 
+  # edit network description
+  config_file=$(mktemp)
+  lxc network create lxdt$$
+  lxc network show lxdt$$ | sed 's/^description:/description: foo/' > 
"$config_file"
+  lxc network edit lxdt$$ < "$config_file"
+  lxc network show lxdt$$ | grep -q 'description: foo'
+  lxc network delete lxdt$$
+
   # Unconfigured bridge
   lxc network create lxdt$$ ipv4.address=none ipv6.address=none
   lxc network delete lxdt$$
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to