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