[lxc-devel] [lxd/master] Network: Adds state column to networks_nodes table
tomponline on Github
lxc-bot at linuxcontainers.org
Mon Nov 23 17:34:36 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 553 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20201123/8b5875c9/attachment-0001.bin>
-------------- next part --------------
From 4694b1a5955b131848b26db418720f126cc8b6e1 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 20 Nov 2020 11:44:34 +0000
Subject: [PATCH 01/35] lxd/storage/pools/utils: Updates comment and error for
storagePoolCreateLocal
Makes more accurate.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage_pools_utils.go | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/lxd/storage_pools_utils.go b/lxd/storage_pools_utils.go
index 57cc08b74f..6ea29eb5c2 100644
--- a/lxd/storage_pools_utils.go
+++ b/lxd/storage_pools_utils.go
@@ -3,6 +3,8 @@ package main
import (
"fmt"
+ "github.com/pkg/errors"
+
"github.com/lxc/lxd/lxd/state"
storagePools "github.com/lxc/lxd/lxd/storage"
"github.com/lxc/lxd/shared"
@@ -95,7 +97,7 @@ func storagePoolCreateGlobal(state *state.State, req api.StoragePoolsPost) error
return nil
}
-// This performs all non-db related work needed to create the pool.
+// This performs local pool setup and updates DB record if config was changed during pool setup.
func storagePoolCreateLocal(state *state.State, id int64, req api.StoragePoolsPost, isNotification bool) (map[string]string, error) {
tryUndo := true
@@ -145,7 +147,7 @@ func storagePoolCreateLocal(state *state.State, id int64, req api.StoragePoolsPo
// Create the database entry for the storage pool.
err = state.Cluster.UpdateStoragePool(req.Name, req.Description, updatedConfig)
if err != nil {
- return nil, fmt.Errorf("Error inserting %s into database: %s", req.Name, err)
+ return nil, errors.Wrapf(err, "Error updating storage pool config after local create for %q", req.Name)
}
}
From f30c166a542ef2fa98a7d570dc2850b668e6c2d6 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 20 Nov 2020 11:46:21 +0000
Subject: [PATCH 02/35] lxd/storage/pools: Error quoting
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage_pools.go | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lxd/storage_pools.go b/lxd/storage_pools.go
index c631d7cbc7..2e3631e676 100644
--- a/lxd/storage_pools.go
+++ b/lxd/storage_pools.go
@@ -182,7 +182,7 @@ func storagePoolsPost(d *Daemon, r *http.Request) response.Response {
// storage config are the ones in StoragePoolNodeConfigKeys.
for key := range req.Config {
if !shared.StringInSlice(key, db.StoragePoolNodeConfigKeys) {
- return response.SmartError(fmt.Errorf("Config key '%s' may not be used as node-specific key", key))
+ return response.SmartError(fmt.Errorf("Config key %q may not be used as node-specific key", key))
}
}
@@ -196,7 +196,7 @@ func storagePoolsPost(d *Daemon, r *http.Request) response.Response {
})
if err != nil {
if err == db.ErrAlreadyDefined {
- return response.BadRequest(fmt.Errorf("The storage pool already defined on node %s", targetNode))
+ return response.BadRequest(fmt.Errorf("The storage pool already defined on node %q", targetNode))
}
return response.SmartError(err)
@@ -209,7 +209,7 @@ func storagePoolsPostCluster(d *Daemon, req api.StoragePoolsPost) error {
// Check that no node-specific config key has been defined.
for key := range req.Config {
if shared.StringInSlice(key, db.StoragePoolNodeConfigKeys) {
- return fmt.Errorf("Config key '%s' is node-specific", key)
+ return fmt.Errorf("Config key %q is node-specific", key)
}
}
@@ -525,7 +525,7 @@ func storagePoolPatch(d *Daemon, r *http.Request) response.Response {
func storagePoolValidateClusterConfig(reqConfig map[string]string) error {
for key := range reqConfig {
if shared.StringInSlice(key, db.StoragePoolNodeConfigKeys) {
- return fmt.Errorf("node-specific config key %s can't be changed", key)
+ return fmt.Errorf("Node-specific config key %q can't be changed", key)
}
}
return nil
From e2481e8abce41ebc3ddee524aa4164863b102715 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 20 Nov 2020 14:37:47 +0000
Subject: [PATCH 03/35] lxd/db/cluster: Adds state column to
storage_pools_nodes and networks_nodes table and set existing rows to state=1
(created)
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/db/cluster/schema.go | 4 +++-
lxd/db/cluster/update.go | 13 +++++++++++++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/lxd/db/cluster/schema.go b/lxd/db/cluster/schema.go
index 3e9227899b..8d0c38bdb8 100644
--- a/lxd/db/cluster/schema.go
+++ b/lxd/db/cluster/schema.go
@@ -299,6 +299,7 @@ CREATE TABLE "networks_nodes" (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
network_id INTEGER NOT NULL,
node_id INTEGER NOT NULL,
+ state INTEGER NOT NULL DEFAULT 0,
UNIQUE (network_id, node_id),
FOREIGN KEY (network_id) REFERENCES "networks" (id) ON DELETE CASCADE,
FOREIGN KEY (node_id) REFERENCES nodes (id) ON DELETE CASCADE
@@ -489,6 +490,7 @@ CREATE TABLE storage_pools_nodes (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
storage_pool_id INTEGER NOT NULL,
node_id INTEGER NOT NULL,
+ state INTEGER NOT NULL DEFAULT 0,
UNIQUE (storage_pool_id, node_id),
FOREIGN KEY (storage_pool_id) REFERENCES storage_pools (id) ON DELETE CASCADE,
FOREIGN KEY (node_id) REFERENCES nodes (id) ON DELETE CASCADE
@@ -589,5 +591,5 @@ CREATE TABLE storage_volumes_snapshots_config (
UNIQUE (storage_volume_snapshot_id, key)
);
-INSERT INTO schema (version, updated_at) VALUES (39, strftime("%s"))
+INSERT INTO schema (version, updated_at) VALUES (40, strftime("%s"))
`
diff --git a/lxd/db/cluster/update.go b/lxd/db/cluster/update.go
index 750097c693..cfb300b95d 100644
--- a/lxd/db/cluster/update.go
+++ b/lxd/db/cluster/update.go
@@ -76,6 +76,19 @@ var updates = map[int]schema.Update{
37: updateFromV36,
38: updateFromV37,
39: updateFromV38,
+ 40: updateFromV39,
+}
+
+// Add state column to storage_pools_nodes and networks_nodes tables. Set existing row's state to 1 ("created").
+func updateFromV39(tx *sql.Tx) error {
+ stmt := `
+ ALTER TABLE storage_pools_nodes ADD COLUMN state INTEGER NOT NULL DEFAULT 0;
+ UPDATE storage_pools_nodes SET state = 1;
+ ALTER TABLE networks_nodes ADD COLUMN state INTEGER NOT NULL DEFAULT 0;
+ UPDATE networks_nodes SET state = 1;
+ `
+ _, err := tx.Exec(stmt)
+ return err
}
// Add storage_volumes_backups table.
From 530e9e2db125ab06784a14386241d84ae01f18cd Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 11:17:12 +0000
Subject: [PATCH 04/35] lxd/db/networks: Populate node state column in
NetworkNodeJoin
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/db/networks.go | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/lxd/db/networks.go b/lxd/db/networks.go
index b2549cabd5..c0fecfc5ce 100644
--- a/lxd/db/networks.go
+++ b/lxd/db/networks.go
@@ -171,8 +171,9 @@ func (c *ClusterTx) CreateNetworkConfig(networkID, nodeID int64, config map[stri
// assume that the relevant network has already been created on the joining node,
// and we just need to track it.
func (c *ClusterTx) NetworkNodeJoin(networkID, nodeID int64) error {
- columns := []string{"network_id", "node_id"}
- values := []interface{}{networkID, nodeID}
+ columns := []string{"network_id", "node_id", "state"}
+ // Create network node with "created" state as we expect the network to already be setup.
+ values := []interface{}{networkID, nodeID, networkCreated}
_, err := query.UpsertObject(c.tx, "networks_nodes", columns, values)
return err
}
From 2bd4e3b69bb0779f015d0ec7581c8658c110a705 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 11:17:36 +0000
Subject: [PATCH 05/35] lxd/db/networks: Populate node state column in
CreatePendingNetwork
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/db/networks.go | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lxd/db/networks.go b/lxd/db/networks.go
index c0fecfc5ce..f4964a99da 100644
--- a/lxd/db/networks.go
+++ b/lxd/db/networks.go
@@ -299,9 +299,9 @@ func (c *ClusterTx) CreatePendingNetwork(node string, projectName string, name s
return ErrAlreadyDefined
}
- // Insert the node-specific configuration.
- columns := []string{"network_id", "node_id"}
- values := []interface{}{networkID, nodeInfo.ID}
+ // Insert the node-specific configuration with state "pending".
+ columns := []string{"network_id", "node_id", "state"}
+ values := []interface{}{networkID, nodeInfo.ID, networkPending}
_, err = query.UpsertObject(c.tx, "networks_nodes", columns, values)
if err != nil {
return err
From d18d739b06fa9cc0e29fb6a6ccdc21c9b2aca1a3 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 11:18:01 +0000
Subject: [PATCH 06/35] lxd/db/networks: Adds networkNodeState and
NetworkNodeCreated functiond
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/db/networks.go | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/lxd/db/networks.go b/lxd/db/networks.go
index f4964a99da..ba74ef7d72 100644
--- a/lxd/db/networks.go
+++ b/lxd/db/networks.go
@@ -341,6 +341,29 @@ func (c *ClusterTx) networkState(project string, name string, state int) error {
return nil
}
+// NetworkNodeCreated sets the state of the given network for the local member to "Created".
+func (c *ClusterTx) NetworkNodeCreated(networkID int64) error {
+ return c.networkNodeState(networkID, networkCreated)
+}
+
+// networkNodeState updates the network member state for the local member and specified network ID.
+func (c *ClusterTx) networkNodeState(networkID int64, state int) error {
+ stmt := "UPDATE networks_nodes SET state=? WHERE network_id = ? and node_id = ?"
+ result, err := c.tx.Exec(stmt, state, networkID, c.nodeID)
+ if err != nil {
+ return err
+ }
+ n, err := result.RowsAffected()
+ if err != nil {
+ return err
+ }
+ if n != 1 {
+ return ErrNoSuchObject
+ }
+
+ return nil
+}
+
// UpdateNetwork updates the network with the given ID.
func (c *ClusterTx) UpdateNetwork(id int64, description string, config map[string]string) error {
err := updateNetworkDescription(c.tx, id, description)
From 2d1c8354a520550b546528aadbc5891938631bfb Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 11:18:37 +0000
Subject: [PATCH 07/35] lxd/db/networks: Comments
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/db/networks.go | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/lxd/db/networks.go b/lxd/db/networks.go
index ba74ef7d72..b06411e610 100644
--- a/lxd/db/networks.go
+++ b/lxd/db/networks.go
@@ -456,15 +456,12 @@ const (
NetworkTypePhysical // Network type physical.
)
-// GetNetworkInAnyState returns the network with the given name.
-//
-// The network can be in any state.
+// GetNetworkInAnyState returns the network with the given name. The network can be in any state.
func (c *Cluster) GetNetworkInAnyState(project string, name string) (int64, *api.Network, error) {
return c.getNetwork(project, name, false)
}
-// Get the network with the given name. If onlyCreated is true, only return
-// networks in the created state.
+// Get the network with the given name. If onlyCreated is true, only return networks in the created state.
func (c *Cluster) getNetwork(project string, name string, onlyCreated bool) (int64, *api.Network, error) {
description := sql.NullString{}
id := int64(-1)
@@ -562,8 +559,7 @@ func (c *Cluster) networkNodes(networkID int64) ([]string, error) {
return nodes, nil
}
-// GetNetworkWithInterface returns the network associated with the interface with
-// the given name.
+// GetNetworkWithInterface returns the network associated with the interface with the given name.
func (c *Cluster) GetNetworkWithInterface(devName string) (int64, *api.Network, error) {
id := int64(-1)
name := ""
@@ -656,6 +652,7 @@ func (c *Cluster) getNetworkConfig(id int64) (map[string]string, error) {
func (c *Cluster) CreateNetwork(projectName string, name string, description string, netType NetworkType, config map[string]string) (int64, error) {
var id int64
err := c.Transaction(func(tx *ClusterTx) error {
+ // Insert a new network record with state "created".
result, err := tx.tx.Exec("INSERT INTO networks (project_id, name, description, state, type) VALUES ((SELECT id FROM projects WHERE name = ?), ?, ?, ?, ?)",
projectName, name, description, networkCreated, netType)
if err != nil {
From ab72fd14c9bd1f32a8262651daac3b85f1bb2323 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 11:18:49 +0000
Subject: [PATCH 08/35] lxd/db/networks: Populate node state column in
CreateNetwork
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/db/networks.go | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lxd/db/networks.go b/lxd/db/networks.go
index b06411e610..a879a23728 100644
--- a/lxd/db/networks.go
+++ b/lxd/db/networks.go
@@ -664,9 +664,9 @@ func (c *Cluster) CreateNetwork(projectName string, name string, description str
return err
}
- // Insert a node-specific entry pointing to ourselves.
- columns := []string{"network_id", "node_id"}
- values := []interface{}{id, c.nodeID}
+ // Insert a node-specific entry pointing to ourselves with state "pending".
+ columns := []string{"network_id", "node_id", "state"}
+ values := []interface{}{id, c.nodeID, networkPending}
_, err = query.UpsertObject(tx.tx, "networks_nodes", columns, values)
if err != nil {
return err
From 9ef2f1f485c6ae85e5f31345541825618d893233 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 11:19:31 +0000
Subject: [PATCH 09/35] lxd/network/driver: Remove check that prevents starting
network in pending state
This is needed as we now need to check if the network can start OK before marking the network created.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/driver_bridge.go | 4 ----
lxd/network/driver_macvlan.go | 6 ------
lxd/network/driver_ovn.go | 4 ----
lxd/network/driver_physical.go | 4 ----
lxd/network/driver_sriov.go | 6 ------
5 files changed, 24 deletions(-)
diff --git a/lxd/network/driver_bridge.go b/lxd/network/driver_bridge.go
index ec30df98ca..8014bdb256 100644
--- a/lxd/network/driver_bridge.go
+++ b/lxd/network/driver_bridge.go
@@ -487,10 +487,6 @@ func (n *bridge) setup(oldConfig map[string]string) error {
n.logger.Debug("Setting up network")
- if n.status == api.NetworkStatusPending {
- return fmt.Errorf("Cannot start pending network")
- }
-
// Create directory.
if !shared.PathExists(shared.VarPath("networks", n.name)) {
err := os.MkdirAll(shared.VarPath("networks", n.name), 0711)
diff --git a/lxd/network/driver_macvlan.go b/lxd/network/driver_macvlan.go
index 09c15a174f..9c9a159cc5 100644
--- a/lxd/network/driver_macvlan.go
+++ b/lxd/network/driver_macvlan.go
@@ -1,8 +1,6 @@
package network
import (
- "fmt"
-
"github.com/lxc/lxd/lxd/cluster"
"github.com/lxc/lxd/lxd/db"
"github.com/lxc/lxd/lxd/revert"
@@ -67,10 +65,6 @@ func (n *macvlan) Rename(newName string) error {
func (n *macvlan) Start() error {
n.logger.Debug("Start")
- if n.status == api.NetworkStatusPending {
- return fmt.Errorf("Cannot start pending network")
- }
-
return nil
}
diff --git a/lxd/network/driver_ovn.go b/lxd/network/driver_ovn.go
index 03dd522eb7..097aaeb011 100644
--- a/lxd/network/driver_ovn.go
+++ b/lxd/network/driver_ovn.go
@@ -1836,10 +1836,6 @@ func (n *ovn) Rename(newName string) error {
func (n *ovn) Start() error {
n.logger.Debug("Start")
- if n.status == api.NetworkStatusPending {
- return fmt.Errorf("Cannot start pending network")
- }
-
// Add local node's OVS chassis ID to logical chassis group.
err := n.addChassisGroupEntry()
if err != nil {
diff --git a/lxd/network/driver_physical.go b/lxd/network/driver_physical.go
index 3d24584924..4ee105c8f2 100644
--- a/lxd/network/driver_physical.go
+++ b/lxd/network/driver_physical.go
@@ -143,10 +143,6 @@ func (n *physical) Rename(newName string) error {
func (n *physical) Start() error {
n.logger.Debug("Start")
- if n.status == api.NetworkStatusPending {
- return fmt.Errorf("Cannot start pending network")
- }
-
revert := revert.New()
defer revert.Fail()
diff --git a/lxd/network/driver_sriov.go b/lxd/network/driver_sriov.go
index 299e2dd2df..6a745cbb18 100644
--- a/lxd/network/driver_sriov.go
+++ b/lxd/network/driver_sriov.go
@@ -1,8 +1,6 @@
package network
import (
- "fmt"
-
"github.com/lxc/lxd/lxd/cluster"
"github.com/lxc/lxd/lxd/db"
"github.com/lxc/lxd/lxd/revert"
@@ -67,10 +65,6 @@ func (n *sriov) Rename(newName string) error {
func (n *sriov) Start() error {
n.logger.Debug("Start")
- if n.status == api.NetworkStatusPending {
- return fmt.Errorf("Cannot start pending network")
- }
-
return nil
}
From 9d4fd2e90d2bf3b984aa184ba072e4844117eef5 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 11:20:38 +0000
Subject: [PATCH 10/35] lxd/networks: Whitespace
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/networks.go | 1 -
1 file changed, 1 deletion(-)
diff --git a/lxd/networks.go b/lxd/networks.go
index 09ea358629..a4fec44216 100644
--- a/lxd/networks.go
+++ b/lxd/networks.go
@@ -279,7 +279,6 @@ func networksPost(d *Daemon, r *http.Request) response.Response {
}
// Non-clustered network creation.
-
networks, err := d.cluster.GetNetworks(projectName)
if err != nil {
return response.InternalError(err)
From 46040063f8c01765ce14fe5d84b785ba240c55dd Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:02:25 +0000
Subject: [PATCH 11/35] lxd/network/network/interface: Updates init to take
api.Network and network nodes map
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/network_interface.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lxd/network/network_interface.go b/lxd/network/network_interface.go
index b9ba1e89d1..1df3fe001c 100644
--- a/lxd/network/network_interface.go
+++ b/lxd/network/network_interface.go
@@ -24,7 +24,7 @@ type Network interface {
Type
// Load.
- init(state *state.State, id int64, projectName string, name string, netType string, description string, config map[string]string, status string)
+ init(state *state.State, id int64, projectName string, netInfo *api.Network, netNodes map[int64]db.NetworkNode)
// Config.
Validate(config map[string]string) error
From 96da9ddd37fcfee0e45f9baf7fe1bb8c666360c5 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:02:57 +0000
Subject: [PATCH 12/35] lxd/network/network/interface: Adds LocalStatus
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/network_interface.go | 1 +
1 file changed, 1 insertion(+)
diff --git a/lxd/network/network_interface.go b/lxd/network/network_interface.go
index 1df3fe001c..c5f60ca4ca 100644
--- a/lxd/network/network_interface.go
+++ b/lxd/network/network_interface.go
@@ -32,6 +32,7 @@ type Network interface {
Name() string
Description() string
Status() string
+ LocalStatus() string
Config() map[string]string
IsUsed() (bool, error)
DHCPv4Subnet() *net.IPNet
From a897d04a10651bce3cbac3933d2d873d792ed6d1 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:03:26 +0000
Subject: [PATCH 13/35] lxd/network/network/load: Updates LoadByName to pass
network nodes from s.Cluster.GetNetworkInAnyState to init()
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/network_load.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lxd/network/network_load.go b/lxd/network/network_load.go
index 7098181a57..0b165b63cc 100644
--- a/lxd/network/network_load.go
+++ b/lxd/network/network_load.go
@@ -26,7 +26,7 @@ func LoadByType(driverType string) (Type, error) {
// LoadByName loads an instantiated network from the database by project and name.
func LoadByName(s *state.State, projectName string, name string) (Network, error) {
- id, netInfo, err := s.Cluster.GetNetworkInAnyState(projectName, name)
+ id, netInfo, netNodes, err := s.Cluster.GetNetworkInAnyState(projectName, name)
if err != nil {
return nil, err
}
@@ -37,7 +37,7 @@ func LoadByName(s *state.State, projectName string, name string) (Network, error
}
n := driverFunc()
- n.init(s, id, projectName, name, netInfo.Type, netInfo.Description, netInfo.Config, netInfo.Status)
+ n.init(s, id, projectName, netInfo, netNodes)
return n, nil
}
From 2d44f1ce305fb3a9d8970486ed6d19b80c988b81 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:05:56 +0000
Subject: [PATCH 14/35] lxd/db/networks: Adds NetworkState type and uses it in
place of int
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/db/networks.go | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/lxd/db/networks.go b/lxd/db/networks.go
index a879a23728..66e57968d2 100644
--- a/lxd/db/networks.go
+++ b/lxd/db/networks.go
@@ -94,7 +94,7 @@ func (c *ClusterTx) GetNonPendingNetworks() (map[string]map[int64]api.Network, e
var projectName string
var networkID int64
var networkType NetworkType
- var networkState int
+ var networkState NetworkState
var network api.Network
err := rows.Scan(&projectName, &networkID, &network.Name, &network.Description, &networkType, &networkState)
@@ -230,7 +230,7 @@ func (c *ClusterTx) CreatePendingNetwork(node string, projectName string, name s
// First check if a network with the given name exists, and, if so, that it's in the pending state.
network := struct {
id int64
- state int
+ state NetworkState
netType NetworkType
}{}
@@ -325,7 +325,7 @@ func (c *ClusterTx) NetworkErrored(project string, name string) error {
return c.networkState(project, name, networkErrored)
}
-func (c *ClusterTx) networkState(project string, name string, state int) error {
+func (c *ClusterTx) networkState(project string, name string, state NetworkState) error {
stmt := "UPDATE networks SET state=? WHERE project_id = (SELECT id FROM projects WHERE name = ?) AND name=?"
result, err := c.tx.Exec(stmt, state, project, name)
if err != nil {
@@ -347,7 +347,7 @@ func (c *ClusterTx) NetworkNodeCreated(networkID int64) error {
}
// networkNodeState updates the network member state for the local member and specified network ID.
-func (c *ClusterTx) networkNodeState(networkID int64, state int) error {
+func (c *ClusterTx) networkNodeState(networkID int64, state NetworkState) error {
stmt := "UPDATE networks_nodes SET state=? WHERE network_id = ? and node_id = ?"
result, err := c.tx.Exec(stmt, state, networkID, c.nodeID)
if err != nil {
@@ -437,11 +437,14 @@ func (c *Cluster) networks(project string, where string, args ...interface{}) ([
return response, nil
}
+// NetworkState indicates the state of the network or network node.
+type NetworkState int
+
// Network state.
const (
- networkPending int = iota // Network defined but not yet created.
- networkCreated // Network created on all nodes.
- networkErrored // Network creation failed on some nodes
+ networkPending NetworkState = iota // Network defined but not yet created.
+ networkCreated // Network created on all nodes.
+ networkErrored // Network creation failed on some nodes
)
// NetworkType indicates type of network.
@@ -465,7 +468,7 @@ func (c *Cluster) GetNetworkInAnyState(project string, name string) (int64, *api
func (c *Cluster) getNetwork(project string, name string, onlyCreated bool) (int64, *api.Network, error) {
description := sql.NullString{}
id := int64(-1)
- state := 0
+ var state NetworkState
var netType NetworkType
q := "SELECT id, description, state, type FROM networks WHERE project_id = (SELECT id FROM projects WHERE name = ?) AND name=?"
From dad43ff1fea7efaf9be1dc2fc9dd1421c73edef8 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:07:37 +0000
Subject: [PATCH 15/35] lxd/db/networks: Renames networkFillStatus to
NetworkStateToAPIStatus
And updates usage.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/db/networks.go | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/lxd/db/networks.go b/lxd/db/networks.go
index 66e57968d2..9fe91ec9f7 100644
--- a/lxd/db/networks.go
+++ b/lxd/db/networks.go
@@ -103,7 +103,7 @@ func (c *ClusterTx) GetNonPendingNetworks() (map[string]map[int64]api.Network, e
}
// Populate Status and Type fields by converting from DB values.
- networkFillStatus(&network, networkState)
+ network.Status = NetworkStateToAPIStatus(networkState)
networkFillType(&network, networkType)
if projectNetworks[projectName] != nil {
@@ -500,7 +500,7 @@ func (c *Cluster) getNetwork(project string, name string, onlyCreated bool) (int
network.Config = config
// Populate Status and Type fields by converting from DB values.
- networkFillStatus(&network, state)
+ network.Status = NetworkStateToAPIStatus(state)
networkFillType(&network, netType)
nodes, err := c.networkNodes(id)
@@ -512,16 +512,17 @@ func (c *Cluster) getNetwork(project string, name string, onlyCreated bool) (int
return id, &network, nil
}
-func networkFillStatus(network *api.Network, state int) {
+// NetworkStateToAPIStatus converts DB NetworkState to API status string.
+func NetworkStateToAPIStatus(state NetworkState) string {
switch state {
case networkPending:
- network.Status = api.NetworkStatusPending
+ return api.NetworkStatusPending
case networkCreated:
- network.Status = api.NetworkStatusCreated
+ return api.NetworkStatusCreated
case networkErrored:
- network.Status = api.NetworkStatusErrored
+ return api.NetworkStatusErrored
default:
- network.Status = api.NetworkStatusUnknown
+ return api.NetworkStatusUnknown
}
}
From c1621affaa329c1baa3d94ea9143dc7d8c8ec3d7 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:09:45 +0000
Subject: [PATCH 16/35] lxd/db/networks: Adds NetworkNode type
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/db/networks.go | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/lxd/db/networks.go b/lxd/db/networks.go
index 9fe91ec9f7..4b1e5d3158 100644
--- a/lxd/db/networks.go
+++ b/lxd/db/networks.go
@@ -459,6 +459,13 @@ const (
NetworkTypePhysical // Network type physical.
)
+// NetworkNode represents a network node.
+type NetworkNode struct {
+ ID int64
+ Name string
+ State NetworkState
+}
+
// GetNetworkInAnyState returns the network with the given name. The network can be in any state.
func (c *Cluster) GetNetworkInAnyState(project string, name string) (int64, *api.Network, error) {
return c.getNetwork(project, name, false)
From 44421a5f2dce648b72cfe0b33d08efa564276465 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:10:11 +0000
Subject: [PATCH 17/35] lxd/db/networks: Exports NetworkNodes and updates to
return map of NetworkNodes
Including node ID, name and state.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/db/networks.go | 35 +++++++++++++++++++++++++----------
1 file changed, 25 insertions(+), 10 deletions(-)
diff --git a/lxd/db/networks.go b/lxd/db/networks.go
index 4b1e5d3158..5ff4322ed5 100644
--- a/lxd/db/networks.go
+++ b/lxd/db/networks.go
@@ -384,20 +384,35 @@ func (c *ClusterTx) UpdateNetwork(id int64, description string, config map[strin
return nil
}
-// Return the names of the nodes the given network is defined on.
-func (c *ClusterTx) networkNodes(networkID int64) ([]string, error) {
- var err error
- stmt := `
- SELECT nodes.name FROM nodes
- JOIN networks_nodes ON networks_nodes.node_id = nodes.id
- WHERE networks_nodes.network_id = ?
- `
- nodes, err := query.SelectStrings(c.tx, stmt, networkID)
+// NetworkNodes returns the nodes keyed by node ID that the given network is defined on.
+func (c *ClusterTx) NetworkNodes(networkID int64) (map[int64]NetworkNode, error) {
+ nodes := []NetworkNode{}
+ dest := func(i int) []interface{} {
+ nodes = append(nodes, NetworkNode{})
+ return []interface{}{&nodes[i].ID, &nodes[i].Name, &nodes[i].State}
+ }
+
+ stmt, err := c.tx.Prepare(`
+ SELECT nodes.id, nodes.name, networks_nodes.state FROM nodes
+ JOIN networks_nodes ON networks_nodes.node_id = nodes.id
+ WHERE networks_nodes.network_id = ?
+ `)
+ if err != nil {
+ return nil, err
+ }
+ defer stmt.Close()
+
+ err = query.SelectObjects(stmt, dest, networkID)
if err != nil {
return nil, err
}
- return nodes, nil
+ netNodes := map[int64]NetworkNode{}
+ for _, node := range nodes {
+ netNodes[node.ID] = node
+ }
+
+ return netNodes, nil
}
// GetNetworks returns the names of existing networks.
From f661562e100b7edda869e8c710e57709ffbf355c Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:11:41 +0000
Subject: [PATCH 18/35] lxd/db/networks: Updates GetNonPendingNetworks usage of
NetworkNodes()
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/db/networks.go | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/lxd/db/networks.go b/lxd/db/networks.go
index 5ff4322ed5..ddeee25093 100644
--- a/lxd/db/networks.go
+++ b/lxd/db/networks.go
@@ -130,11 +130,14 @@ func (c *ClusterTx) GetNonPendingNetworks() (map[string]map[int64]api.Network, e
network.Config = networkConfig
- nodes, err := c.networkNodes(networkID)
+ nodes, err := c.NetworkNodes(networkID)
if err != nil {
return nil, err
}
- network.Locations = nodes
+
+ for _, node := range nodes {
+ network.Locations = append(network.Locations, node.Name)
+ }
projectNetworks[projectName][networkID] = network
}
From 3f2003d784e30478c71bff21848f890e6c525f90 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:12:10 +0000
Subject: [PATCH 19/35] lxd/db/networks: Modifies getNetwork and
GetNetworkInAnyState to return map of NetworkNodes for network
We run the query anyway to populate Network's Location field so cheap to return at same time.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/db/networks.go | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/lxd/db/networks.go b/lxd/db/networks.go
index ddeee25093..9c086d0f37 100644
--- a/lxd/db/networks.go
+++ b/lxd/db/networks.go
@@ -485,12 +485,13 @@ type NetworkNode struct {
}
// GetNetworkInAnyState returns the network with the given name. The network can be in any state.
-func (c *Cluster) GetNetworkInAnyState(project string, name string) (int64, *api.Network, error) {
+func (c *Cluster) GetNetworkInAnyState(project string, name string) (int64, *api.Network, map[int64]NetworkNode, error) {
return c.getNetwork(project, name, false)
}
-// Get the network with the given name. If onlyCreated is true, only return networks in the created state.
-func (c *Cluster) getNetwork(project string, name string, onlyCreated bool) (int64, *api.Network, error) {
+// Get the network with the given name. If onlyCreated is true, only return networks in the networkCreated state.
+// Also returns a map of the network's nodes keyed by node ID.
+func (c *Cluster) getNetwork(project string, name string, onlyCreated bool) (int64, *api.Network, map[int64]NetworkNode, error) {
description := sql.NullString{}
id := int64(-1)
var state NetworkState
@@ -506,15 +507,15 @@ func (c *Cluster) getNetwork(project string, name string, onlyCreated bool) (int
err := dbQueryRowScan(c, q, arg1, arg2)
if err != nil {
if err == sql.ErrNoRows {
- return -1, nil, ErrNoSuchObject
+ return -1, nil, nil, ErrNoSuchObject
}
- return -1, nil, err
+ return -1, nil, nil, err
}
config, err := c.getNetworkConfig(id)
if err != nil {
- return -1, nil, err
+ return -1, nil, nil, err
}
network := api.Network{
@@ -528,13 +529,16 @@ func (c *Cluster) getNetwork(project string, name string, onlyCreated bool) (int
network.Status = NetworkStateToAPIStatus(state)
networkFillType(&network, netType)
- nodes, err := c.networkNodes(id)
+ nodes, err := c.NetworkNodes(id)
if err != nil {
- return -1, nil, err
+ return -1, nil, nil, err
}
- network.Locations = nodes
- return id, &network, nil
+ for _, node := range nodes {
+ network.Locations = append(network.Locations, node.Name)
+ }
+
+ return id, &network, nodes, nil
}
// NetworkStateToAPIStatus converts DB NetworkState to API status string.
From 2eecd37616e851b694c70f33ffd6bb71ad399f7e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:13:07 +0000
Subject: [PATCH 20/35] lxd/db/networks: Exports NetworkNodes
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/db/networks.go | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lxd/db/networks.go b/lxd/db/networks.go
index 9c086d0f37..d0fd2a14b1 100644
--- a/lxd/db/networks.go
+++ b/lxd/db/networks.go
@@ -572,13 +572,13 @@ func networkFillType(network *api.Network, netType NetworkType) {
}
}
-// Return the names of the nodes the given network is defined on.
-func (c *Cluster) networkNodes(networkID int64) ([]string, error) {
- var nodes []string
+// NetworkNodes returns the nodes keyed by node ID that the given network is defined on.
+func (c *Cluster) NetworkNodes(networkID int64) (map[int64]NetworkNode, error) {
+ var nodes map[int64]NetworkNode
var err error
err = c.Transaction(func(tx *ClusterTx) error {
- nodes, err = tx.networkNodes(networkID)
+ nodes, err = tx.NetworkNodes(networkID)
if err != nil {
return err
}
From 8518b15362caf714185d4832b06d82d329b382c1 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:13:49 +0000
Subject: [PATCH 21/35] lxd/db/networks: c.GetNetworkInAnyState usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/db/networks.go | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lxd/db/networks.go b/lxd/db/networks.go
index d0fd2a14b1..12866e0344 100644
--- a/lxd/db/networks.go
+++ b/lxd/db/networks.go
@@ -720,7 +720,7 @@ func (c *Cluster) CreateNetwork(projectName string, name string, description str
// UpdateNetwork updates the network with the given name.
func (c *Cluster) UpdateNetwork(project string, name, description string, config map[string]string) error {
- id, netInfo, err := c.GetNetworkInAnyState(project, name)
+ id, netInfo, _, err := c.GetNetworkInAnyState(project, name)
if err != nil {
return err
}
@@ -794,7 +794,7 @@ func clearNetworkConfig(tx *sql.Tx, networkID, nodeID int64) error {
// DeleteNetwork deletes the network with the given name.
func (c *Cluster) DeleteNetwork(project string, name string) error {
- id, _, err := c.GetNetworkInAnyState(project, name)
+ id, _, _, err := c.GetNetworkInAnyState(project, name)
if err != nil {
return err
}
@@ -809,7 +809,7 @@ func (c *Cluster) DeleteNetwork(project string, name string) error {
// RenameNetwork renames a network.
func (c *Cluster) RenameNetwork(project string, oldName string, newName string) error {
- id, _, err := c.GetNetworkInAnyState(project, oldName)
+ id, _, _, err := c.GetNetworkInAnyState(project, oldName)
if err != nil {
return err
}
From 9b9249fc1edb4231d06b1c8138321e17ca9c5df9 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:14:07 +0000
Subject: [PATCH 22/35] lxd/db/networks: Updates comments to reference state
constants
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/db/networks.go | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/lxd/db/networks.go b/lxd/db/networks.go
index 12866e0344..34a75003a6 100644
--- a/lxd/db/networks.go
+++ b/lxd/db/networks.go
@@ -175,7 +175,7 @@ func (c *ClusterTx) CreateNetworkConfig(networkID, nodeID int64, config map[stri
// and we just need to track it.
func (c *ClusterTx) NetworkNodeJoin(networkID, nodeID int64) error {
columns := []string{"network_id", "node_id", "state"}
- // Create network node with "created" state as we expect the network to already be setup.
+ // Create network node with networkCreated state as we expect the network to already be setup.
values := []interface{}{networkID, nodeID, networkCreated}
_, err := query.UpsertObject(c.tx, "networks_nodes", columns, values)
return err
@@ -276,7 +276,7 @@ func (c *ClusterTx) CreatePendingNetwork(node string, projectName string, name s
return err
}
} else {
- // Check that the existing network is in the pending state.
+ // Check that the existing network is in the networkPending or networkErrored state.
if network.state != networkPending && network.state != networkErrored {
return fmt.Errorf("Network is not in pending or errored state")
}
@@ -302,7 +302,7 @@ func (c *ClusterTx) CreatePendingNetwork(node string, projectName string, name s
return ErrAlreadyDefined
}
- // Insert the node-specific configuration with state "pending".
+ // Insert the node-specific configuration with state networkPending.
columns := []string{"network_id", "node_id", "state"}
values := []interface{}{networkID, nodeInfo.ID, networkPending}
_, err = query.UpsertObject(c.tx, "networks_nodes", columns, values)
@@ -318,12 +318,12 @@ func (c *ClusterTx) CreatePendingNetwork(node string, projectName string, name s
return nil
}
-// NetworkCreated sets the state of the given network to "Created".
+// NetworkCreated sets the state of the given network to networkCreated.
func (c *ClusterTx) NetworkCreated(project string, name string) error {
return c.networkState(project, name, networkCreated)
}
-// NetworkErrored sets the state of the given network to "Errored".
+// NetworkErrored sets the state of the given network to networkErrored.
func (c *ClusterTx) NetworkErrored(project string, name string) error {
return c.networkState(project, name, networkErrored)
}
@@ -344,7 +344,7 @@ func (c *ClusterTx) networkState(project string, name string, state NetworkState
return nil
}
-// NetworkNodeCreated sets the state of the given network for the local member to "Created".
+// NetworkNodeCreated sets the state of the given network for the local member to networkCreated.
func (c *ClusterTx) NetworkNodeCreated(networkID int64) error {
return c.networkNodeState(networkID, networkCreated)
}
@@ -423,7 +423,7 @@ func (c *Cluster) GetNetworks(project string) ([]string, error) {
return c.networks(project, "")
}
-// GetNonPendingNetworks returns the names of all networks that are not pending.
+// GetNonPendingNetworks returns the names of all networks that are not in state networkPending.
func (c *Cluster) GetNonPendingNetworks(project string) ([]string, error) {
return c.networks(project, "NOT state=?", networkPending)
}
@@ -685,7 +685,7 @@ func (c *Cluster) getNetworkConfig(id int64) (map[string]string, error) {
func (c *Cluster) CreateNetwork(projectName string, name string, description string, netType NetworkType, config map[string]string) (int64, error) {
var id int64
err := c.Transaction(func(tx *ClusterTx) error {
- // Insert a new network record with state "created".
+ // Insert a new network record with state networkCreated.
result, err := tx.tx.Exec("INSERT INTO networks (project_id, name, description, state, type) VALUES ((SELECT id FROM projects WHERE name = ?), ?, ?, ?, ?)",
projectName, name, description, networkCreated, netType)
if err != nil {
@@ -697,7 +697,7 @@ func (c *Cluster) CreateNetwork(projectName string, name string, description str
return err
}
- // Insert a node-specific entry pointing to ourselves with state "pending".
+ // Insert a node-specific entry pointing to ourselves with state networkPending.
columns := []string{"network_id", "node_id", "state"}
values := []interface{}{id, c.nodeID, networkPending}
_, err = query.UpsertObject(tx.tx, "networks_nodes", columns, values)
From 50cbd073f9eab83122a05a604c6b529767e1b795 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:14:44 +0000
Subject: [PATCH 23/35] lxd/patches: d.cluster.GetNetworkInAnyState usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/patches.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lxd/patches.go b/lxd/patches.go
index 194a5695c9..1e6fa8183c 100644
--- a/lxd/patches.go
+++ b/lxd/patches.go
@@ -3787,7 +3787,7 @@ func patchNetworkCearBridgeVolatileHwaddr(name string, d *Daemon) error {
}
for _, networkName := range networks {
- _, net, err := d.cluster.GetNetworkInAnyState(projectName, networkName)
+ _, net, _, err := d.cluster.GetNetworkInAnyState(projectName, networkName)
if err != nil {
return errors.Wrapf(err, "Failed loading network %q for network_clear_bridge_volatile_hwaddr patch", networkName)
}
From 197c40fc772588292f7e1ce05ef89bd6a790d227 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:16:31 +0000
Subject: [PATCH 24/35] lxd/api/cluster: d.cluster.GetNetworkInAnyState usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/api_cluster.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lxd/api_cluster.go b/lxd/api_cluster.go
index 7e88bcce2f..3167c0d83f 100644
--- a/lxd/api_cluster.go
+++ b/lxd/api_cluster.go
@@ -436,7 +436,7 @@ func clusterPutJoin(d *Daemon, req api.ClusterPut) response.Response {
}
for _, name := range networkNames {
- _, network, err := d.cluster.GetNetworkInAnyState(p.Name, name)
+ _, network, _, err := d.cluster.GetNetworkInAnyState(p.Name, name)
if err != nil {
return err
}
@@ -1628,7 +1628,7 @@ func clusterCheckNetworksMatch(cluster *db.Cluster, reqNetworks []internalCluste
found = true
- _, network, err := cluster.GetNetworkInAnyState(networkProjectName, networkName)
+ _, network, _, err := cluster.GetNetworkInAnyState(networkProjectName, networkName)
if err != nil {
return err
}
From c1d5bfed2eb8963255b3f8f9d126270af5f8d7d2 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:16:43 +0000
Subject: [PATCH 25/35] lxd/api/project: s.Cluster.GetNetworkInAnyState usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/api_project.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lxd/api_project.go b/lxd/api_project.go
index 85de1f61b2..cbb088cb85 100644
--- a/lxd/api_project.go
+++ b/lxd/api_project.go
@@ -624,7 +624,7 @@ func projectValidateRestrictedSubnets(s *state.State, value string) error {
}
// Check uplink exists and load config to compare subnets.
- _, uplink, err := s.Cluster.GetNetworkInAnyState(project.Default, uplinkName)
+ _, uplink, _, err := s.Cluster.GetNetworkInAnyState(project.Default, uplinkName)
if err != nil {
return errors.Wrapf(err, "Invalid uplink network %q", uplinkName)
}
From ac5ac8373ccbd3983a58117881900ad086d7a6a1 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:16:53 +0000
Subject: [PATCH 26/35] lxd/device/nic: d.state.Cluster.GetNetworkInAnyState
usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/device/nic_bridged.go | 2 +-
lxd/device/nictype/nictype.go | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/lxd/device/nic_bridged.go b/lxd/device/nic_bridged.go
index f79fd3549c..83e78ed092 100644
--- a/lxd/device/nic_bridged.go
+++ b/lxd/device/nic_bridged.go
@@ -492,7 +492,7 @@ func (d *nicBridged) rebuildDnsmasqEntry() error {
defer dnsmasq.ConfigMutex.Unlock()
// Use project.Default here as bridge networks don't support projects.
- _, dbInfo, err := d.state.Cluster.GetNetworkInAnyState(project.Default, d.config["parent"])
+ _, dbInfo, _, err := d.state.Cluster.GetNetworkInAnyState(project.Default, d.config["parent"])
if err != nil {
return err
}
diff --git a/lxd/device/nictype/nictype.go b/lxd/device/nictype/nictype.go
index 5c8ef08209..3848864855 100644
--- a/lxd/device/nictype/nictype.go
+++ b/lxd/device/nictype/nictype.go
@@ -26,7 +26,7 @@ func NICType(s *state.State, deviceProjectName string, d deviceConfig.Device) (s
return "", errors.Wrapf(err, "Failed to translate device project %q into network project", deviceProjectName)
}
- _, netInfo, err := s.Cluster.GetNetworkInAnyState(networkProjectName, d["network"])
+ _, netInfo, _, err := s.Cluster.GetNetworkInAnyState(networkProjectName, d["network"])
if err != nil {
return "", errors.Wrapf(err, "Failed to load network %q for project %q", d["network"], networkProjectName)
}
From 9f5cbbed88dc2b13d355cd468a9d021da72a50ed Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:18:19 +0000
Subject: [PATCH 27/35] lxd/network/driver/ovn:
n.state.Cluster.GetNetworkInAnyState usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/driver_ovn.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lxd/network/driver_ovn.go b/lxd/network/driver_ovn.go
index 097aaeb011..6c855330b3 100644
--- a/lxd/network/driver_ovn.go
+++ b/lxd/network/driver_ovn.go
@@ -82,7 +82,7 @@ func (n *ovn) Info() Info {
// uplinkRoutes parses ipv4.routes and ipv6.routes settings for a named uplink network into a slice of *net.IPNet.
func (n *ovn) uplinkRoutes(uplinkNetworkName string) ([]*net.IPNet, error) {
- _, uplink, err := n.state.Cluster.GetNetworkInAnyState(project.Default, uplinkNetworkName)
+ _, uplink, _, err := n.state.Cluster.GetNetworkInAnyState(project.Default, uplinkNetworkName)
if err != nil {
return nil, err
}
From 1b2c63d4f1c3e750acb692744736f2f55e04f06e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:19:29 +0000
Subject: [PATCH 28/35] lxd/network/driver/common: Adds LocalStatus function
and store node info inside network via init()
Updates init() to accept api.Network and map of NetworkNodes.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/driver_common.go | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/lxd/network/driver_common.go b/lxd/network/driver_common.go
index 23cff9a58c..6c39a6d7b2 100644
--- a/lxd/network/driver_common.go
+++ b/lxd/network/driver_common.go
@@ -36,18 +36,20 @@ type common struct {
description string
config map[string]string
status string
+ nodes map[int64]db.NetworkNode
}
// init initialise internal variables.
-func (n *common) init(state *state.State, id int64, projectName string, name string, netType string, description string, config map[string]string, status string) {
- n.logger = logging.AddContext(logger.Log, log.Ctx{"project": projectName, "driver": netType, "network": name})
+func (n *common) init(state *state.State, id int64, projectName string, netInfo *api.Network, netNodes map[int64]db.NetworkNode) {
+ n.logger = logging.AddContext(logger.Log, log.Ctx{"project": projectName, "driver": netInfo.Type, "network": netInfo.Name})
n.id = id
n.project = projectName
- n.name = name
- n.config = config
+ n.name = netInfo.Name
+ n.config = netInfo.Config
n.state = state
- n.description = description
- n.status = status
+ n.description = netInfo.Description
+ n.status = netInfo.Status
+ n.nodes = netNodes
}
// FillConfig fills requested config with any default values, by default this is a no-op.
@@ -133,6 +135,16 @@ func (n *common) Status() string {
return n.status
}
+// LocalStatus returns network status of the local cluster member.
+func (n *common) LocalStatus() string {
+ node, exists := n.nodes[n.state.Cluster.GetNodeID()]
+ if !exists {
+ return api.NetworkStatusUnknown
+ }
+
+ return db.NetworkStateToAPIStatus(node.State)
+}
+
// Config returns the network config.
func (n *common) Config() map[string]string {
return n.config
From 0768ddc46d083fa36b9fb405b8d3c90ae9c7d671 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:17:32 +0000
Subject: [PATCH 29/35] lxd/network/driver/bridge: Only perform local date if
local status is api.NetworkStatusCreated
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/driver_bridge.go | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/lxd/network/driver_bridge.go b/lxd/network/driver_bridge.go
index 8014bdb256..0175e930e3 100644
--- a/lxd/network/driver_bridge.go
+++ b/lxd/network/driver_bridge.go
@@ -414,20 +414,22 @@ func (n *bridge) isRunning() bool {
func (n *bridge) Delete(clientType cluster.ClientType) error {
n.logger.Debug("Delete", log.Ctx{"clientType": clientType})
- // Bring the network down.
- if n.isRunning() {
- err := n.Stop()
+ // Bring the local network down if created on this node.
+ if n.LocalStatus() == api.NetworkStatusCreated {
+ if n.isRunning() {
+ err := n.Stop()
+ if err != nil {
+ return err
+ }
+ }
+
+ // Delete apparmor profiles.
+ err := apparmor.NetworkDelete(n.state, n)
if err != nil {
return err
}
}
- // Delete apparmor profiles.
- err := apparmor.NetworkDelete(n.state, n)
- if err != nil {
- return err
- }
-
return n.common.delete(clientType)
}
From 62ae92fb4d2863690b441f0a28a07c02b17c6d9a Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:18:11 +0000
Subject: [PATCH 30/35] lxd/network/driver/ovn: Only perform local date if
local status is api.NetworkStatusCreated
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/driver_ovn.go | 88 ++++++++++++++++++++-------------------
1 file changed, 45 insertions(+), 43 deletions(-)
diff --git a/lxd/network/driver_ovn.go b/lxd/network/driver_ovn.go
index 6c855330b3..370104179c 100644
--- a/lxd/network/driver_ovn.go
+++ b/lxd/network/driver_ovn.go
@@ -1758,61 +1758,63 @@ func (n *ovn) deleteChassisGroupEntry() error {
func (n *ovn) Delete(clientType cluster.ClientType) error {
n.logger.Debug("Delete", log.Ctx{"clientType": clientType})
- err := n.Stop()
- if err != nil {
- return err
- }
-
- if clientType == cluster.ClientTypeNormal {
- client, err := n.getClient()
+ if n.LocalStatus() == api.NetworkStatusCreated {
+ err := n.Stop()
if err != nil {
return err
}
- err = client.LogicalRouterDelete(n.getRouterName())
- if err != nil {
- return err
- }
+ if clientType == cluster.ClientTypeNormal {
+ client, err := n.getClient()
+ if err != nil {
+ return err
+ }
- err = client.LogicalSwitchDelete(n.getExtSwitchName())
- if err != nil {
- return err
- }
+ err = client.LogicalRouterDelete(n.getRouterName())
+ if err != nil {
+ return err
+ }
- err = client.LogicalSwitchDelete(n.getIntSwitchName())
- if err != nil {
- return err
- }
+ err = client.LogicalSwitchDelete(n.getExtSwitchName())
+ if err != nil {
+ return err
+ }
- err = client.LogicalRouterPortDelete(n.getRouterExtPortName())
- if err != nil {
- return err
- }
+ err = client.LogicalSwitchDelete(n.getIntSwitchName())
+ if err != nil {
+ return err
+ }
- err = client.LogicalRouterPortDelete(n.getRouterIntPortName())
- if err != nil {
- return err
- }
+ err = client.LogicalRouterPortDelete(n.getRouterExtPortName())
+ if err != nil {
+ return err
+ }
- err = client.LogicalSwitchPortDelete(n.getExtSwitchRouterPortName())
- if err != nil {
- return err
- }
+ err = client.LogicalRouterPortDelete(n.getRouterIntPortName())
+ if err != nil {
+ return err
+ }
- err = client.LogicalSwitchPortDelete(n.getExtSwitchProviderPortName())
- if err != nil {
- return err
- }
+ err = client.LogicalSwitchPortDelete(n.getExtSwitchRouterPortName())
+ if err != nil {
+ return err
+ }
- err = client.LogicalSwitchPortDelete(n.getIntSwitchRouterPortName())
- if err != nil {
- return err
- }
+ err = client.LogicalSwitchPortDelete(n.getExtSwitchProviderPortName())
+ if err != nil {
+ return err
+ }
- // Must be done after logical router removal.
- err = client.ChassisGroupDelete(n.getChassisGroupName())
- if err != nil {
- return err
+ err = client.LogicalSwitchPortDelete(n.getIntSwitchRouterPortName())
+ if err != nil {
+ return err
+ }
+
+ // Must be done after logical router removal.
+ err = client.ChassisGroupDelete(n.getChassisGroupName())
+ if err != nil {
+ return err
+ }
}
}
From 272c6e74cffdcbd54c91a3f6e05c4f7d6467d69e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:20:08 +0000
Subject: [PATCH 31/35] lxd/network/driver/physical: Only perform local date if
local status is api.NetworkStatusCreated
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/driver_physical.go | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/lxd/network/driver_physical.go b/lxd/network/driver_physical.go
index 4ee105c8f2..09d94f59a4 100644
--- a/lxd/network/driver_physical.go
+++ b/lxd/network/driver_physical.go
@@ -118,9 +118,11 @@ func (n *physical) Create(clientType cluster.ClientType) error {
func (n *physical) Delete(clientType cluster.ClientType) error {
n.logger.Debug("Delete", log.Ctx{"clientType": clientType})
- err := n.Stop()
- if err != nil {
- return err
+ if n.LocalStatus() == api.NetworkStatusCreated {
+ err := n.Stop()
+ if err != nil {
+ return err
+ }
}
return n.common.delete(clientType)
From 9882e5f2d3a01674be19ed5075640ac82e0b983a Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:24:48 +0000
Subject: [PATCH 32/35] lxd/networks: Updates doNetworksCreate to skip creation
if node is already marked created
Updates node status to created on successful create.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/networks.go | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/lxd/networks.go b/lxd/networks.go
index a4fec44216..6f3c1817d1 100644
--- a/lxd/networks.go
+++ b/lxd/networks.go
@@ -444,6 +444,15 @@ func doNetworksCreate(d *Daemon, projectName string, req api.NetworksPost, clien
return err
}
+ if n.Status() == api.NetworkStatusCreated {
+ return fmt.Errorf("Network already created")
+ }
+
+ if n.LocalStatus() == api.NetworkStatusCreated {
+ logger.Debug("Skipping network create as already created locally", log.Ctx{"project": projectName, "network": n.Name()})
+ return nil
+ }
+
// Run initial creation setup for the network driver.
err = n.Create(clientType)
if err != nil {
@@ -457,13 +466,26 @@ func doNetworksCreate(d *Daemon, projectName string, req api.NetworksPost, clien
if err != nil {
delErr := n.Delete(clientType)
if delErr != nil {
- logger.Errorf("Failed clearing up network %q after failed create: %v", n.Name(), delErr)
+ logger.Error("Failed clearing up network after failed create", log.Ctx{"project": projectName, "network": n.Name(), "err": delErr})
}
return err
}
}
+ // Mark local node as state "created".
+ err = d.cluster.Transaction(func(tx *db.ClusterTx) error {
+ return tx.NetworkNodeCreated(n.ID())
+ })
+ if err != nil {
+ delErr := n.Delete(clientType)
+ if delErr != nil {
+ logger.Error("Failed clearing up network after failed local status update", log.Ctx{"project": projectName, "network": n.Name(), "err": delErr})
+ }
+ return err
+ }
+ logger.Debug("Marked network local status as created", log.Ctx{"project": projectName, "network": req.Name})
+
return nil
}
From d4181329e595c2c58ce857572d4d08576f507404 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:25:32 +0000
Subject: [PATCH 33/35] lxd/networks: d.cluster.GetNetworkInAnyState usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/networks.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lxd/networks.go b/lxd/networks.go
index 6f3c1817d1..e19d11b9ae 100644
--- a/lxd/networks.go
+++ b/lxd/networks.go
@@ -533,7 +533,7 @@ func doNetworkGet(d *Daemon, projectName string, name string) (api.Network, erro
}
// Get some information.
- _, dbInfo, _ := d.cluster.GetNetworkInAnyState(projectName, name)
+ _, dbInfo, _, _ := d.cluster.GetNetworkInAnyState(projectName, name)
// Don't allow retrieving info about the local node interfaces when not using default project.
if projectName != project.Default && dbInfo == nil {
From 1dde572bb720b2b25745e3f49681ab0f81f12baa Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:26:00 +0000
Subject: [PATCH 34/35] lxd/networks: Don't skip network clean up if network is
pending in networkDelete()
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/networks.go | 15 +--------------
1 file changed, 1 insertion(+), 14 deletions(-)
diff --git a/lxd/networks.go b/lxd/networks.go
index e19d11b9ae..be10a2ade4 100644
--- a/lxd/networks.go
+++ b/lxd/networks.go
@@ -605,19 +605,6 @@ func networkDelete(d *Daemon, r *http.Request) response.Response {
name := mux.Vars(r)["name"]
state := d.State()
- // Check if the network is pending, if so we just need to delete it from the database.
- _, dbNetwork, err := d.cluster.GetNetworkInAnyState(projectName, name)
- if err != nil {
- return response.SmartError(err)
- }
- if dbNetwork.Status == api.NetworkStatusPending {
- err := d.cluster.DeleteNetwork(projectName, name)
- if err != nil {
- return response.SmartError(err)
- }
- return response.EmptySyncResponse
- }
-
// Get the existing network.
n, err := network.LoadByName(state, projectName, name)
if err != nil {
@@ -639,7 +626,7 @@ func networkDelete(d *Daemon, r *http.Request) response.Response {
}
}
- // Delete the network.
+ // Delete the network from each member.
err = n.Delete(clientType)
if err != nil {
return response.SmartError(err)
From 2623f054c30aa8dc759afa8629fe5a24c8c5a60f Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 23 Nov 2020 17:26:34 +0000
Subject: [PATCH 35/35] lxd/networks: d.cluster.GetNetworkInAnyState usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/networks.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lxd/networks.go b/lxd/networks.go
index be10a2ade4..9fa0b799b0 100644
--- a/lxd/networks.go
+++ b/lxd/networks.go
@@ -322,7 +322,7 @@ func networksPostCluster(d *Daemon, projectName string, req api.NetworksPost, cl
// Check that the requested network type matches the type created when adding the local node config.
// If network doesn't exist yet, ignore not found error, as this will be checked by NetworkNodeConfigs().
- _, netInfo, err := d.cluster.GetNetworkInAnyState(projectName, req.Name)
+ _, netInfo, _, err := d.cluster.GetNetworkInAnyState(projectName, req.Name)
if err != nil && err != db.ErrNoSuchObject {
return err
}
@@ -730,7 +730,7 @@ func networkPut(d *Daemon, r *http.Request) response.Response {
name := mux.Vars(r)["name"]
// Get the existing network.
- _, dbInfo, err := d.cluster.GetNetworkInAnyState(projectName, name)
+ _, dbInfo, _, err := d.cluster.GetNetworkInAnyState(projectName, name)
if err != nil {
return response.SmartError(err)
}
More information about the lxc-devel
mailing list