@@ -16,6 +16,7 @@ import (
16
16
"sync"
17
17
"time"
18
18
19
+ dqlite "github.com/canonical/go-dqlite/v3/client"
19
20
"github.com/gorilla/mux"
20
21
21
22
"github.com/canonical/lxd/client"
@@ -774,11 +775,15 @@ func clusterPutJoin(d *Daemon, r *http.Request, req api.ClusterPut) response.Res
774
775
s .UpdateIdentityCache ()
775
776
776
777
// Update local setup and possibly join the raft dqlite cluster.
777
- nodes := make ([]db.RaftNode , len (info .RaftNodes ))
778
- for i , node := range info .RaftNodes {
779
- nodes [i ].ID = node .ID
780
- nodes [i ].Address = node .Address
781
- nodes [i ].Role = db .RaftRole (node .Role )
778
+ nodes := make ([]db.RaftNode , 0 , len (info .RaftNodes ))
779
+ for _ , node := range info .RaftNodes {
780
+ nodes = append (nodes , db.RaftNode {
781
+ NodeInfo : dqlite.NodeInfo {
782
+ ID : node .ID ,
783
+ Address : node .Address ,
784
+ Role : db .RaftRole (node .Role ),
785
+ },
786
+ })
782
787
}
783
788
784
789
err = cluster .Join (s , d .gateway , networkCert , serverCert , req .ServerName , nodes )
@@ -1378,6 +1383,7 @@ func clusterNodesPost(d *Daemon, r *http.Request) response.Response {
1378
1383
}
1379
1384
1380
1385
// Filter to online members.
1386
+ onlineNodeAddresses = make ([]any , 0 , len (members ))
1381
1387
for _ , member := range members {
1382
1388
if member .State == db .ClusterMemberStateEvacuated || member .IsOffline (s .GlobalConfig .OfflineThreshold ()) {
1383
1389
continue
@@ -2481,14 +2487,16 @@ func internalClusterPostAccept(d *Daemon, r *http.Request) response.Response {
2481
2487
}
2482
2488
2483
2489
accepted := internalClusterPostAcceptResponse {
2484
- RaftNodes : make ([]internalRaftNode , len (nodes )),
2490
+ RaftNodes : make ([]internalRaftNode , 0 , len (nodes )),
2485
2491
PrivateKey : s .Endpoints .NetworkPrivateKey (),
2486
2492
}
2487
2493
2488
- for i , node := range nodes {
2489
- accepted .RaftNodes [i ].ID = node .ID
2490
- accepted .RaftNodes [i ].Address = node .Address
2491
- accepted .RaftNodes [i ].Role = int (node .Role )
2494
+ for _ , node := range nodes {
2495
+ accepted .RaftNodes = append (accepted .RaftNodes , internalRaftNode {
2496
+ ID : node .ID ,
2497
+ Address : node .Address ,
2498
+ Role : int (node .Role ),
2499
+ })
2492
2500
}
2493
2501
2494
2502
return response .SyncResponse (true , accepted )
@@ -2718,12 +2726,16 @@ func internalClusterPostAssign(d *Daemon, r *http.Request) response.Response {
2718
2726
return response .BadRequest (fmt .Errorf ("No raft members provided" ))
2719
2727
}
2720
2728
2721
- nodes := make ([]db.RaftNode , len (req .RaftNodes ))
2722
- for i , node := range req .RaftNodes {
2723
- nodes [i ].ID = node .ID
2724
- nodes [i ].Address = node .Address
2725
- nodes [i ].Role = db .RaftRole (node .Role )
2726
- nodes [i ].Name = node .Name
2729
+ nodes := make ([]db.RaftNode , 0 , len (req .RaftNodes ))
2730
+ for _ , node := range req .RaftNodes {
2731
+ nodes = append (nodes , db.RaftNode {
2732
+ NodeInfo : dqlite.NodeInfo {
2733
+ ID : node .ID ,
2734
+ Address : node .Address ,
2735
+ Role : db .RaftRole (node .Role ),
2736
+ },
2737
+ Name : node .Name ,
2738
+ })
2727
2739
}
2728
2740
2729
2741
err = cluster .Assign (s , d .gateway , nodes )
@@ -3249,15 +3261,15 @@ func evacuateClusterMember(s *state.State, gateway *cluster.Gateway, r *http.Req
3249
3261
return response .SmartError (err )
3250
3262
}
3251
3263
3252
- instances := make ([]instance.Instance , len (dbInstances ))
3264
+ instances := make ([]instance.Instance , 0 , len (dbInstances ))
3253
3265
3254
- for i , dbInst := range dbInstances {
3266
+ for _ , dbInst := range dbInstances {
3255
3267
inst , err := instance .LoadByProjectAndName (s , dbInst .Project , dbInst .Name )
3256
3268
if err != nil {
3257
3269
return response .SmartError (fmt .Errorf ("Failed to load instance: %w" , err ))
3258
3270
}
3259
3271
3260
- instances [ i ] = inst
3272
+ instances = append ( instances , inst )
3261
3273
}
3262
3274
3263
3275
run := func (op * operations.Operation ) error {
@@ -3426,8 +3438,8 @@ func restoreClusterMember(d *Daemon, r *http.Request) response.Response {
3426
3438
return response .SmartError (err )
3427
3439
}
3428
3440
3429
- instances := make ([]instance.Instance , 0 )
3430
- localInstances := make ([]instance.Instance , 0 )
3441
+ instances := make ([]instance.Instance , 0 , len ( dbInstances ) )
3442
+ localInstances := make ([]instance.Instance , 0 , len ( dbInstances ) )
3431
3443
3432
3444
for _ , dbInst := range dbInstances {
3433
3445
inst , err := instance .LoadByProjectAndName (s , dbInst .Project , dbInst .Name )
@@ -3817,26 +3829,24 @@ func clusterGroupsGet(d *Daemon, r *http.Request) response.Response {
3817
3829
return err
3818
3830
}
3819
3831
3820
- for i := range clusterGroups {
3821
- nodeClusterGroups , err := dbCluster .GetNodeClusterGroups (ctx , tx .Tx (), dbCluster.NodeClusterGroupFilter {GroupID : & clusterGroups [i ].ID })
3832
+ apiClusterGroups := make ([]* api.ClusterGroup , 0 , len (clusterGroups ))
3833
+ for _ , clusterGroup := range clusterGroups {
3834
+ nodeClusterGroups , err := dbCluster .GetNodeClusterGroups (ctx , tx .Tx (), dbCluster.NodeClusterGroupFilter {GroupID : & clusterGroup .ID })
3822
3835
if err != nil {
3823
3836
return err
3824
3837
}
3825
3838
3826
- clusterGroups [ i ] .Nodes = make ([]string , 0 , len (nodeClusterGroups ))
3839
+ clusterGroup .Nodes = make ([]string , 0 , len (nodeClusterGroups ))
3827
3840
for _ , node := range nodeClusterGroups {
3828
- clusterGroups [ i ] .Nodes = append (clusterGroups [ i ] .Nodes , node .Node )
3841
+ clusterGroup .Nodes = append (clusterGroup .Nodes , node .Node )
3829
3842
}
3830
- }
3831
3843
3832
- apiClusterGroups := make ([]* api.ClusterGroup , len (clusterGroups ))
3833
- for i , clusterGroup := range clusterGroups {
3834
- members , err := tx .GetClusterGroupNodes (ctx , clusterGroup .Name )
3844
+ apiClusterGroup , err := clusterGroup .ToAPI (ctx , tx .Tx ())
3835
3845
if err != nil {
3836
3846
return err
3837
3847
}
3838
3848
3839
- apiClusterGroups [ i ] = db . ClusterGroupToAPI ( & clusterGroup , members )
3849
+ apiClusterGroups = append ( apiClusterGroups , apiClusterGroup )
3840
3850
}
3841
3851
3842
3852
result = apiClusterGroups
@@ -3900,7 +3910,7 @@ func clusterGroupGet(d *Daemon, r *http.Request) response.Response {
3900
3910
}
3901
3911
3902
3912
var group * dbCluster.ClusterGroup
3903
-
3913
+ var apiGroup * api. ClusterGroup
3904
3914
err = s .DB .Cluster .Transaction (context .TODO (), func (ctx context.Context , tx * db.ClusterTx ) error {
3905
3915
// Get the cluster group.
3906
3916
group , err = dbCluster .GetClusterGroup (ctx , tx .Tx (), name )
@@ -3918,13 +3928,17 @@ func clusterGroupGet(d *Daemon, r *http.Request) response.Response {
3918
3928
group .Nodes = append (group .Nodes , node .Node )
3919
3929
}
3920
3930
3931
+ apiGroup , err = group .ToAPI (ctx , tx .Tx ())
3932
+ if err != nil {
3933
+ return err
3934
+ }
3935
+
3921
3936
return nil
3922
3937
})
3923
3938
if err != nil {
3924
3939
return response .SmartError (err )
3925
3940
}
3926
3941
3927
- apiGroup , err := group .ToAPI ()
3928
3942
if err != nil {
3929
3943
return response .InternalError (err )
3930
3944
}
@@ -4193,17 +4207,17 @@ func clusterGroupPatch(d *Daemon, r *http.Request) response.Response {
4193
4207
dbClusterGroup .Nodes = append (dbClusterGroup .Nodes , node .Node )
4194
4208
}
4195
4209
4210
+ clusterGroup , err = dbClusterGroup .ToAPI (ctx , tx .Tx ())
4211
+ if err != nil {
4212
+ return err
4213
+ }
4214
+
4196
4215
return nil
4197
4216
})
4198
4217
if err != nil {
4199
4218
return response .SmartError (err )
4200
4219
}
4201
4220
4202
- clusterGroup , err = dbClusterGroup .ToAPI ()
4203
- if err != nil {
4204
- return response .SmartError (err )
4205
- }
4206
-
4207
4221
req := clusterGroup .Writable ()
4208
4222
4209
4223
// Validate the ETag.
@@ -4345,7 +4359,16 @@ func clusterGroupDelete(d *Daemon, r *http.Request) response.Response {
4345
4359
}
4346
4360
4347
4361
if len (members ) > 0 {
4348
- return fmt .Errorf ("Only empty cluster groups can be removed" )
4362
+ return api .StatusErrorf (http .StatusBadRequest , "Only empty cluster groups can be removed" )
4363
+ }
4364
+
4365
+ usedBy , err := dbCluster .GetClusterGroupUsedBy (ctx , tx .Tx (), name )
4366
+ if err != nil {
4367
+ return err
4368
+ }
4369
+
4370
+ if len (usedBy ) > 0 {
4371
+ return api .StatusErrorf (http .StatusBadRequest , "Cluster group is currently in use" )
4349
4372
}
4350
4373
4351
4374
return dbCluster .DeleteClusterGroup (ctx , tx .Tx (), name )
0 commit comments