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

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) ===
Supersedes #6380.
From f3bd7c13964ca90f8510fbff7eeb08e954a5501b Mon Sep 17 00:00:00 2001
From: Dinah Baum <dinahbaum...@gmail.com>
Date: Fri, 6 Dec 2019 13:18:41 -0600
Subject: [PATCH 1/5] api: Add clustering_architecture extension

Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com>
---
 doc/api-extensions.md | 4 ++++
 shared/version/api.go | 1 +
 2 files changed, 5 insertions(+)

diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index 632ce186ac..f8daa82a8a 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -889,3 +889,7 @@ Add virtual machine support.
 
 ## image\_profiles
 Allows a list of profiles to be applied to an image when launching a new 
container. 
+
+## clustering_architecture
+This adds a new `architecture` attribute to cluster members which indicates a 
cluster
+member's architecture.
diff --git a/shared/version/api.go b/shared/version/api.go
index 931606c8f0..ca419947db 100644
--- a/shared/version/api.go
+++ b/shared/version/api.go
@@ -180,6 +180,7 @@ var APIExtensions = []string{
        "container_disk_ceph",
        "virtual-machines",
        "image_profiles",
+       "clustering_architecture",
 }
 
 // APIExtensionsCount returns the number of available API extensions.

From 3ff31f78b584970ccb80624e4f35af0fd1e44374 Mon Sep 17 00:00:00 2001
From: Dinah Baum <dinahbaum...@gmail.com>
Date: Thu, 5 Dec 2019 01:37:28 -0600
Subject: [PATCH 2/5] shared/api: Add Architecture to ClusterMember

Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com>
---
 shared/api/cluster.go | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/shared/api/cluster.go b/shared/api/cluster.go
index c773929c8d..94ac6a5016 100644
--- a/shared/api/cluster.go
+++ b/shared/api/cluster.go
@@ -60,4 +60,7 @@ type ClusterMember struct {
 
        // API extension: clustering_roles
        Roles []string `json:"roles" yaml:"roles"`
+
+       // API extension: clustering_architecture
+       Architecture string `json:"architecture" yaml:"architecture"`
 }

From 13670ca842939433d6a395cbf3ff18ed4e0c6175 Mon Sep 17 00:00:00 2001
From: Dinah Baum <dinahbaum...@gmail.com>
Date: Thu, 5 Dec 2019 01:35:20 -0600
Subject: [PATCH 3/5] lxd/db: Add Architecture to NodeInfo

Signed-off-by: Dinah Baum <dinahbaum...@gmail.com>
---
 lxd/db/node.go | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/lxd/db/node.go b/lxd/db/node.go
index 7bbf423f3a..b8dc908d32 100644
--- a/lxd/db/node.go
+++ b/lxd/db/node.go
@@ -37,6 +37,7 @@ type NodeInfo struct {
        APIExtensions int       // Number of API extensions of the LXD code 
running on the node
        Heartbeat     time.Time // Timestamp of the last heartbeat
        Roles         []string  // List of cluster roles
+       Architecture  int       // Node architecture
 }
 
 // IsOffline returns true if the last successful heartbeat time of the node is
@@ -270,6 +271,7 @@ func (c *ClusterTx) nodes(pending bool, where string, args 
...interface{}) ([]No
                        &nodes[i].Schema,
                        &nodes[i].APIExtensions,
                        &nodes[i].Heartbeat,
+                       &nodes[i].Architecture,
                }
        }
        if pending {
@@ -279,7 +281,7 @@ func (c *ClusterTx) nodes(pending bool, where string, args 
...interface{}) ([]No
        }
 
        // Get the node entries
-       sql = "SELECT id, name, address, description, schema, api_extensions, 
heartbeat FROM nodes WHERE pending=?"
+       sql = "SELECT id, name, address, description, schema, api_extensions, 
heartbeat, arch FROM nodes WHERE pending=?"
        if where != "" {
                sql += fmt.Sprintf("AND %s ", where)
        }
@@ -584,6 +586,7 @@ func (c *ClusterTx) NodeWithLeastContainers() (string, 
error) {
        if err != nil {
                return "", errors.Wrap(err, "failed to get offline threshold")
        }
+
        nodes, err := c.Nodes()
        if err != nil {
                return "", errors.Wrap(err, "failed to get current nodes")

From 5862ac84f864bf43fba7709ae89c87389fb5b0cf Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanay...@canonical.com>
Date: Tue, 14 Jan 2020 12:12:00 +0000
Subject: [PATCH 4/5] lxd/cluster: Track member architecture

Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com>
---
 lxd/api_cluster.go             | 10 +++++++++-
 lxd/cluster/heartbeat_test.go  |  3 ++-
 lxd/cluster/membership.go      |  9 +--------
 lxd/cluster/membership_test.go |  7 ++++---
 4 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/lxd/api_cluster.go b/lxd/api_cluster.go
index bf96d39774..f37f8bf3ab 100644
--- a/lxd/api_cluster.go
+++ b/lxd/api_cluster.go
@@ -26,6 +26,7 @@ import (
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
        "github.com/lxc/lxd/shared/logger"
+       "github.com/lxc/lxd/shared/osarch"
        "github.com/lxc/lxd/shared/version"
 )
 
@@ -807,6 +808,11 @@ func clusterAcceptMember(
        name, address string, schema, apiExt int,
        pools []api.StoragePool, networks []api.Network) 
(*internalClusterPostAcceptResponse, error) {
 
+       architecture, err := osarch.ArchitectureGetLocalID()
+       if err != nil {
+               return nil, err
+       }
+
        req := internalClusterPostAcceptRequest{
                Name:         name,
                Address:      address,
@@ -814,6 +820,7 @@ func clusterAcceptMember(
                API:          apiExt,
                StoragePools: pools,
                Networks:     networks,
+               Architecture: architecture,
        }
        info := &internalClusterPostAcceptResponse{}
        resp, _, err := client.RawQuery("POST", "/internal/cluster/accept", 
req, "")
@@ -1047,7 +1054,7 @@ func internalClusterPostAccept(d *Daemon, r 
*http.Request) response.Response {
                return response.SmartError(err)
        }
 
-       nodes, err := cluster.Accept(d.State(), d.gateway, req.Name, 
req.Address, req.Schema, req.API)
+       nodes, err := cluster.Accept(d.State(), d.gateway, req.Name, 
req.Address, req.Schema, req.API, req.Architecture)
        if err != nil {
                return response.BadRequest(err)
        }
@@ -1070,6 +1077,7 @@ type internalClusterPostAcceptRequest struct {
        API          int               `json:"api" yaml:"api"`
        StoragePools []api.StoragePool `json:"storage_pools" 
yaml:"storage_pools"`
        Networks     []api.Network     `json:"networks" yaml:"networks"`
+       Architecture int               `json:"architecture" yaml:"architecture"`
 }
 
 // A Response for the /internal/cluster/accept endpoint.
diff --git a/lxd/cluster/heartbeat_test.go b/lxd/cluster/heartbeat_test.go
index 4b4e247dc0..b310e71b18 100644
--- a/lxd/cluster/heartbeat_test.go
+++ b/lxd/cluster/heartbeat_test.go
@@ -12,6 +12,7 @@ import (
        "github.com/lxc/lxd/lxd/db"
        "github.com/lxc/lxd/lxd/state"
        "github.com/lxc/lxd/shared"
+       "github.com/lxc/lxd/shared/osarch"
        "github.com/lxc/lxd/shared/version"
        "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/require"
@@ -144,7 +145,7 @@ func (f *heartbeatFixture) Grow() *cluster.Gateway {
        name := address
 
        nodes, err := cluster.Accept(
-               targetState, target, name, address, cluster.SchemaVersion, 
len(version.APIExtensions))
+               targetState, target, name, address, cluster.SchemaVersion, 
len(version.APIExtensions), osarch.ARCH_64BIT_INTEL_X86)
        require.NoError(f.t, err)
 
        err = cluster.Join(state, gateway, target.Cert(), name, nodes)
diff --git a/lxd/cluster/membership.go b/lxd/cluster/membership.go
index f2bd48eb72..9f447e41e4 100644
--- a/lxd/cluster/membership.go
+++ b/lxd/cluster/membership.go
@@ -156,7 +156,7 @@ func Bootstrap(state *state.State, gateway *Gateway, name 
string) error {
 //
 // Return an updated list raft database nodes (possibly including the newly
 // accepted node).
-func Accept(state *state.State, gateway *Gateway, name, address string, 
schema, api int) ([]db.RaftNode, error) {
+func Accept(state *state.State, gateway *Gateway, name, address string, 
schema, api, arch int) ([]db.RaftNode, error) {
        // Check parameters
        if name == "" {
                return nil, fmt.Errorf("node name must not be empty")
@@ -173,13 +173,6 @@ func Accept(state *state.State, gateway *Gateway, name, 
address string, schema,
                        return err
                }
 
-               // TODO: when fixing #6380 this should be replaced with the
-               // actual architecture of the foreign node.
-               arch, err := osarch.ArchitectureGetLocalID()
-               if err != nil {
-                       return err
-               }
-
                // Add the new node
                id, err := tx.NodeAddWithArch(name, address, arch)
                if err != nil {
diff --git a/lxd/cluster/membership_test.go b/lxd/cluster/membership_test.go
index 5462f7fc3e..bf7934b105 100644
--- a/lxd/cluster/membership_test.go
+++ b/lxd/cluster/membership_test.go
@@ -13,6 +13,7 @@ import (
        "github.com/lxc/lxd/lxd/db"
        "github.com/lxc/lxd/lxd/state"
        "github.com/lxc/lxd/shared"
+       "github.com/lxc/lxd/shared/osarch"
        "github.com/lxc/lxd/shared/version"
        "github.com/mpvl/subtest"
        "github.com/stretchr/testify/assert"
@@ -204,7 +205,7 @@ func TestAccept_UnmetPreconditions(t *testing.T) {
 
                        c.setup(&membershipFixtures{t: t, state: state})
 
-                       _, err := cluster.Accept(state, gateway, c.name, 
c.address, c.schema, c.api)
+                       _, err := cluster.Accept(state, gateway, c.name, 
c.address, c.schema, c.api, osarch.ARCH_64BIT_INTEL_X86)
                        assert.EqualError(t, err, c.error)
                })
        }
@@ -224,7 +225,7 @@ func TestAccept(t *testing.T) {
        f.ClusterNode("1.2.3.4:666")
 
        nodes, err := cluster.Accept(
-               state, gateway, "buzz", "5.6.7.8:666", cluster.SchemaVersion, 
len(version.APIExtensions))
+               state, gateway, "buzz", "5.6.7.8:666", cluster.SchemaVersion, 
len(version.APIExtensions), osarch.ARCH_64BIT_INTEL_X86)
        assert.NoError(t, err)
        assert.Len(t, nodes, 2)
        assert.Equal(t, int64(1), nodes[0].ID)
@@ -306,7 +307,7 @@ func TestJoin(t *testing.T) {
 
        // Accept the joining node.
        raftNodes, err := cluster.Accept(
-               targetState, targetGateway, "rusp", address, 
cluster.SchemaVersion, len(version.APIExtensions))
+               targetState, targetGateway, "rusp", address, 
cluster.SchemaVersion, len(version.APIExtensions), osarch.ARCH_64BIT_INTEL_X86)
        require.NoError(t, err)
 
        // Actually join the cluster.

From 777660eb18b8aedd9aee6bc6600549716799ff15 Mon Sep 17 00:00:00 2001
From: Dinah Baum <dinahbaum...@gmail.com>
Date: Thu, 5 Dec 2019 01:33:20 -0600
Subject: [PATCH 5/5] lxc/cluster: Add architecture column in list

Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com>
---
 lxc/cluster.go            | 3 ++-
 lxd/cluster/membership.go | 5 +++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/lxc/cluster.go b/lxc/cluster.go
index 6b0b01d879..6d013ca54e 100644
--- a/lxc/cluster.go
+++ b/lxc/cluster.go
@@ -117,7 +117,7 @@ func (c *cmdClusterList) Run(cmd *cobra.Command, args 
[]string) error {
                if member.Database {
                        database = "YES"
                }
-               line := []string{member.ServerName, member.URL, database, 
strings.ToUpper(member.Status), member.Message}
+               line := []string{member.ServerName, member.URL, database, 
strings.ToUpper(member.Status), member.Message, member.Architecture}
                data = append(data, line)
        }
        sort.Sort(byName(data))
@@ -128,6 +128,7 @@ func (c *cmdClusterList) Run(cmd *cobra.Command, args 
[]string) error {
                i18n.G("DATABASE"),
                i18n.G("STATE"),
                i18n.G("MESSAGE"),
+               i18n.G("ARCHITECTURE"),
        }
 
        return utils.RenderTable(c.flagFormat, header, data, members)
diff --git a/lxd/cluster/membership.go b/lxd/cluster/membership.go
index 9f447e41e4..c857bb7788 100644
--- a/lxd/cluster/membership.go
+++ b/lxd/cluster/membership.go
@@ -811,6 +811,11 @@ func List(state *state.State) ([]api.ClusterMember, error) 
{
                result[i].URL = fmt.Sprintf("https://%s";, node.Address)
                result[i].Database = 
shared.StringInSlice(string(db.ClusterRoleDatabase), node.Roles)
                result[i].Roles = node.Roles
+               result[i].Architecture, err = 
osarch.ArchitectureName(node.Architecture)
+               if err != nil {
+                       return nil, err
+               }
+
                if node.IsOffline(offlineThreshold) {
                        result[i].Status = "Offline"
                        result[i].Message = fmt.Sprintf(
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to