Skip to content

Commit

Permalink
Merge pull request #12623 from simondeziel/from-incus
Browse files Browse the repository at this point in the history
Add new ServerClustered field
  • Loading branch information
tomponline authored Dec 6, 2023
2 parents 6306811 + d2d26de commit ca2a4e7
Show file tree
Hide file tree
Showing 16 changed files with 85 additions and 234 deletions.
12 changes: 8 additions & 4 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
API:
- doc/api-extensions.md
- doc/rest-api.yaml
- shared/api/**/*
- changed-files:
- any-glob-to-any-file:
- doc/api-extensions.md
- doc/rest-api.yaml
- shared/api/**/*
Documentation:
- doc/**/*
- changed-files:
- any-glob-to-any-file:
- doc/**/*
20 changes: 4 additions & 16 deletions lxd/acme.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,7 @@ func acmeProvideChallenge(d *Daemon, r *http.Request) response.Response {
return response.SmartError(err)
}

// If we're clustered, forwared the request to the leader if necessary.
// That is because only the leader knows the token, and any other node will return 404.
clustered, err := cluster.Enabled(s.DB.Node)
if err != nil {
return response.SmartError(err)
}

if clustered {
if s.ServerClustered {
leader, err := d.gateway.LeaderAddress()
if err != nil {
return response.SmartError(err)
Expand Down Expand Up @@ -89,13 +82,8 @@ func autoRenewCertificate(ctx context.Context, d *Daemon, force bool) error {
return nil
}

clustered, err := cluster.Enabled(s.DB.Node)
if err != nil {
return err
}

// If we are clustered, let the leader handle the certificate renewal.
if clustered {
if s.ServerClustered {
leader, err := d.gateway.LeaderAddress()
if err != nil {
return err
Expand All @@ -110,7 +98,7 @@ func autoRenewCertificate(ctx context.Context, d *Daemon, force bool) error {
}

opRun := func(op *operations.Operation) error {
newCert, err := acme.UpdateCertificate(s, d.http01Provider, clustered, domain, email, caURL, force)
newCert, err := acme.UpdateCertificate(s, d.http01Provider, s.ServerClustered, domain, email, caURL, force)
if err != nil {
return err
}
Expand All @@ -120,7 +108,7 @@ func autoRenewCertificate(ctx context.Context, d *Daemon, force bool) error {
return nil
}

if clustered {
if s.ServerClustered {
req := api.ClusterCertificatePut{
ClusterCertificate: string(newCert.Certificate),
ClusterCertificateKey: string(newCert.PrivateKey),
Expand Down
18 changes: 4 additions & 14 deletions lxd/api_1.0.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,14 +257,9 @@ func api10Get(d *Daemon, r *http.Request) response.Response {
return response.InternalError(err)
}

clustered, err := cluster.Enabled(s.DB.Node)
if err != nil {
return response.SmartError(err)
}

// When clustered, use the node name, otherwise use the hostname.
var serverName string
if clustered {
if s.ServerClustered {
serverName = s.ServerName
} else {
hostname, err := os.Hostname()
Expand Down Expand Up @@ -314,7 +309,7 @@ func api10Get(d *Daemon, r *http.Request) response.Response {
Server: "lxd",
ServerPid: os.Getpid(),
ServerVersion: version.Version,
ServerClustered: clustered,
ServerClustered: s.ServerClustered,
ServerEventMode: string(cluster.ServerEventMode()),
ServerName: serverName,
Firewall: s.Firewall.String(),
Expand Down Expand Up @@ -576,16 +571,11 @@ func doApi10Update(d *Daemon, r *http.Request, req api.ServerPut, patch bool) re
}
}

clustered, err := cluster.Enabled(s.DB.Node)
if err != nil {
return response.InternalError(fmt.Errorf("Failed to check for cluster state: %w", err))
}

nodeChanged := map[string]string{}
var newNodeConfig *node.Config
oldNodeConfig := make(map[string]any)

err = s.DB.Node.Transaction(r.Context(), func(ctx context.Context, tx *db.NodeTx) error {
err := s.DB.Node.Transaction(r.Context(), func(ctx context.Context, tx *db.NodeTx) error {
var err error
newNodeConfig, err = node.ConfigLoad(ctx, tx)
if err != nil {
Expand All @@ -598,7 +588,7 @@ func doApi10Update(d *Daemon, r *http.Request, req api.ServerPut, patch bool) re
}

// We currently don't allow changing the cluster.https_address once it's set.
if clustered {
if s.ServerClustered {
curConfig, err := tx.Config(ctx)
if err != nil {
return fmt.Errorf("Cannot fetch node config from database: %w", err)
Expand Down
82 changes: 22 additions & 60 deletions lxd/api_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ func clusterPutBootstrap(d *Daemon, r *http.Request, req api.ClusterPut) respons
// Update server name.
d.globalConfigMu.Lock()
d.serverName = req.ServerName
d.serverClustered = true
d.globalConfigMu.Unlock()

// Start clustering tasks
Expand Down Expand Up @@ -449,12 +450,7 @@ func clusterPutJoin(d *Daemon, r *http.Request, req api.ClusterPut) response.Res
return response.BadRequest(fmt.Errorf("No target cluster member certificate provided"))
}

clustered, err := cluster.Enabled(s.DB.Node)
if err != nil {
return response.SmartError(err)
}

if clustered {
if s.ServerClustered {
return response.BadRequest(fmt.Errorf("This server is already clustered"))
}

Expand All @@ -475,12 +471,12 @@ func clusterPutJoin(d *Daemon, r *http.Request, req api.ClusterPut) response.Res

// First try to listen to the provided address. If we fail, we
// won't actually update the database config.
err = s.Endpoints.NetworkUpdateAddress(req.ServerAddress)
err := s.Endpoints.NetworkUpdateAddress(req.ServerAddress)
if err != nil {
return response.SmartError(err)
}

err := s.DB.Node.Transaction(context.TODO(), func(ctx context.Context, tx *db.NodeTx) error {
err = s.DB.Node.Transaction(context.TODO(), func(ctx context.Context, tx *db.NodeTx) error {
config, err = node.ConfigLoad(ctx, tx)
if err != nil {
return fmt.Errorf("Failed to load cluster config: %w", err)
Expand Down Expand Up @@ -512,6 +508,8 @@ func clusterPutJoin(d *Daemon, r *http.Request, req api.ClusterPut) response.Res

// Update the cluster.https_address config key.
err := s.DB.Node.Transaction(context.TODO(), func(ctx context.Context, tx *db.NodeTx) error {
var err error

config, err = node.ConfigLoad(ctx, tx)
if err != nil {
return fmt.Errorf("Failed to load cluster config: %w", err)
Expand Down Expand Up @@ -548,15 +546,15 @@ func clusterPutJoin(d *Daemon, r *http.Request, req api.ClusterPut) response.Res
// If the user has provided a cluster password, setup the trust
// relationship by adding our own certificate to the cluster.
if req.ClusterPassword != "" {
err = cluster.SetupTrust(serverCert, req.ServerName, req.ClusterAddress, req.ClusterCertificate, req.ClusterPassword)
err := cluster.SetupTrust(serverCert, req.ServerName, req.ClusterAddress, req.ClusterCertificate, req.ClusterPassword)
if err != nil {
return fmt.Errorf("Failed to setup cluster trust: %w", err)
}
}

// Now we are in the remote trust store, ensure our name and type are correct to allow the cluster
// to associate our member name to the server certificate.
err = cluster.UpdateTrust(serverCert, req.ServerName, req.ClusterAddress, req.ClusterCertificate)
err := cluster.UpdateTrust(serverCert, req.ServerName, req.ClusterAddress, req.ClusterCertificate)
if err != nil {
return fmt.Errorf("Failed to update cluster trust: %w", err)
}
Expand All @@ -581,10 +579,12 @@ func clusterPutJoin(d *Daemon, r *http.Request, req api.ClusterPut) response.Res
// Update server name.
d.globalConfigMu.Lock()
d.serverName = req.ServerName
d.serverClustered = true
d.globalConfigMu.Unlock()
revert.Add(func() {
d.globalConfigMu.Lock()
d.serverName = ""
d.serverClustered = false
d.globalConfigMu.Unlock()
})

Expand Down Expand Up @@ -1285,12 +1285,7 @@ func clusterNodesPost(d *Daemon, r *http.Request) response.Response {
return response.BadRequest(err)
}

clustered, err := cluster.Enabled(s.DB.Node)
if err != nil {
return response.SmartError(err)
}

if !clustered {
if !s.ServerClustered {
return response.BadRequest(fmt.Errorf("This server is not clustered"))
}

Expand Down Expand Up @@ -2565,12 +2560,7 @@ func changeMemberRole(s *state.State, r *http.Request, address string, nodes []d
// Try to handover the role of this member to another one.
func handoverMemberRole(s *state.State, gateway *cluster.Gateway) error {
// If we aren't clustered, there's nothing to do.
clustered, err := cluster.Enabled(s.DB.Node)
if err != nil {
return err
}

if !clustered {
if !s.ServerClustered {
return nil
}

Expand Down Expand Up @@ -3580,19 +3570,14 @@ func restoreClusterMember(d *Daemon, r *http.Request) response.Response {
func clusterGroupsPost(d *Daemon, r *http.Request) response.Response {
s := d.State()

clustered, err := cluster.Enabled(s.DB.Node)
if err != nil {
return response.SmartError(err)
}

if !clustered {
if !s.ServerClustered {
return response.BadRequest(fmt.Errorf("This server is not clustered"))
}

req := api.ClusterGroupsPost{}

// Parse the request.
err = json.NewDecoder(r.Body).Decode(&req)
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
return response.BadRequest(err)
}
Expand Down Expand Up @@ -3718,20 +3703,17 @@ func clusterGroupsPost(d *Daemon, r *http.Request) response.Response {
func clusterGroupsGet(d *Daemon, r *http.Request) response.Response {
s := d.State()

clustered, err := cluster.Enabled(s.DB.Node)
if err != nil {
return response.SmartError(err)
}

if !clustered {
if !s.ServerClustered {
return response.BadRequest(fmt.Errorf("This server is not clustered"))
}

recursion := util.IsRecursionRequest(r)

var result any

err = s.DB.Cluster.Transaction(context.TODO(), func(ctx context.Context, tx *db.ClusterTx) error {
err := s.DB.Cluster.Transaction(context.TODO(), func(ctx context.Context, tx *db.ClusterTx) error {
var err error

if recursion {
clusterGroups, err := dbCluster.GetClusterGroups(ctx, tx.Tx())
if err != nil {
Expand Down Expand Up @@ -3816,12 +3798,7 @@ func clusterGroupGet(d *Daemon, r *http.Request) response.Response {
return response.SmartError(err)
}

clustered, err := cluster.Enabled(s.DB.Node)
if err != nil {
return response.SmartError(err)
}

if !clustered {
if !s.ServerClustered {
return response.BadRequest(fmt.Errorf("This server is not clustered"))
}

Expand Down Expand Up @@ -3897,12 +3874,7 @@ func clusterGroupPost(d *Daemon, r *http.Request) response.Response {
return response.Forbidden(errors.New(`The "default" group cannot be renamed`))
}

clustered, err := cluster.Enabled(s.DB.Node)
if err != nil {
return response.SmartError(err)
}

if !clustered {
if !s.ServerClustered {
return response.BadRequest(fmt.Errorf("This server is not clustered"))
}

Expand Down Expand Up @@ -3981,12 +3953,7 @@ func clusterGroupPut(d *Daemon, r *http.Request) response.Response {
return response.SmartError(err)
}

clustered, err := cluster.Enabled(s.DB.Node)
if err != nil {
return response.SmartError(err)
}

if !clustered {
if !s.ServerClustered {
return response.BadRequest(fmt.Errorf("This server is not clustered"))
}

Expand Down Expand Up @@ -4106,12 +4073,7 @@ func clusterGroupPatch(d *Daemon, r *http.Request) response.Response {
return response.SmartError(err)
}

clustered, err := cluster.Enabled(s.DB.Node)
if err != nil {
return response.SmartError(err)
}

if !clustered {
if !s.ServerClustered {
return response.BadRequest(fmt.Errorf("This server is not clustered"))
}

Expand Down
8 changes: 1 addition & 7 deletions lxd/api_internal_recover.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/canonical/lxd/lxd/auth"
"github.com/canonical/lxd/lxd/backup"
backupConfig "github.com/canonical/lxd/lxd/backup/config"
"github.com/canonical/lxd/lxd/cluster"
"github.com/canonical/lxd/lxd/db"
dbCluster "github.com/canonical/lxd/lxd/db/cluster"
deviceConfig "github.com/canonical/lxd/lxd/device/config"
Expand Down Expand Up @@ -131,11 +130,6 @@ func internalRecoverScan(s *state.State, userPools []api.StoragePoolsPost, valid
return response.SmartError(fmt.Errorf("Failed getting validate dependency check info: %w", err))
}

isClustered, err := cluster.Enabled(s.DB.Node)
if err != nil {
return response.SmartError(err)
}

res := internalRecoverValidateResult{}

revert := revert.New()
Expand Down Expand Up @@ -163,7 +157,7 @@ func internalRecoverScan(s *state.State, userPools []api.StoragePoolsPost, valid
if response.IsNotFoundError(err) {
// If the pool DB record doesn't exist, and we are clustered, then don't proceed
// any further as we do not support pool DB record recovery when clustered.
if isClustered {
if s.ServerClustered {
return response.BadRequest(fmt.Errorf("Storage pool recovery not supported when clustered"))
}

Expand Down
Loading

0 comments on commit ca2a4e7

Please sign in to comment.