Skip to content
This repository was archived by the owner on Apr 18, 2025. It is now read-only.

Commit e3f60eb

Browse files
authored
Merge pull request #607 from CS-SI/bug/circuitbreaker
Bugfixes: cluster
2 parents fc763dd + ddffcad commit e3f60eb

File tree

17 files changed

+180
-205
lines changed

17 files changed

+180
-205
lines changed

cli/safescale/commands/cluster.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -514,10 +514,6 @@ var clusterCreateCommand = cli.Command{
514514
}
515515
}
516516
if c.IsSet("master-sizing") {
517-
if strings.Contains(c.String("master-sizing"), "count") {
518-
return clitools.FailureResponse(clitools.ExitOnInvalidArgument("the number of masters cannot be changed yet: count cannot be included in 'master-sizing' flag"))
519-
}
520-
521517
mastersDef, err = constructHostDefinitionStringFromCLI(c, "master-sizing")
522518
if err != nil {
523519
return err

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ require (
3737
github.com/schollz/progressbar/v3 v3.9.0
3838
github.com/sethvargo/go-password v0.2.0
3939
github.com/sirupsen/logrus v1.9.0
40+
github.com/sony/gobreaker v0.5.0
4041
github.com/spf13/viper v1.11.0
4142
github.com/stretchr/testify v1.8.1
4243
github.com/urfave/cli v1.22.10
@@ -50,7 +51,7 @@ require (
5051
golang.org/x/text v0.6.0
5152
gomodules.xyz/stow v0.2.4
5253
google.golang.org/api v0.107.0
53-
google.golang.org/grpc v1.51.0
54+
google.golang.org/grpc v1.52.3
5455
google.golang.org/protobuf v1.28.1
5556
gopkg.in/fsnotify.v1 v1.4.7
5657
)

go.sum

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,8 @@ github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0
484484
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
485485
github.com/smartystreets/assertions v1.13.0 h1:Dx1kYM01xsSqKPno3aqLnrwac2LetPvN23diwyr69Qs=
486486
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
487+
github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg=
488+
github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
487489
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
488490
github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo=
489491
github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
@@ -902,8 +904,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
902904
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
903905
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
904906
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
905-
google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
906-
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
907+
google.golang.org/grpc v1.52.3 h1:pf7sOysg4LdgBqduXveGKrcEwbStiK2rtfghdzlUYDQ=
908+
google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY=
907909
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
908910
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
909911
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=

lib/backend/resources/abstract/cluster.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
stdjson "encoding/json"
2121
"fmt"
2222
"github.com/CS-SI/SafeScale/v22/lib"
23+
uuidpkg "github.com/gofrs/uuid"
2324
"time"
2425

2526
"github.com/CS-SI/SafeScale/v22/lib/backend/resources/enums/clustercomplexity"
@@ -44,11 +45,12 @@ type ClusterRequest struct {
4445
MastersDef HostSizingRequirements // sizing of Masters
4546
NodesDef HostSizingRequirements // sizing of nodes
4647
InitialNodeCount uint // contains the initial count of nodes to create (cannot be less than flavor requirement)
47-
OS string // contains the name of the linux distribution wanted
48-
DisabledDefaultFeatures map[string]struct{} // contains the list of features that should be installed by default, but we don't want actually
49-
Force bool // set to True in order to ignore sizing recommendations
50-
FeatureParameters []string // contains parameter values of automatically installed Features
51-
DefaultSshPort uint // default ssh port for gateways // nolint
48+
InitialMasterCount uint
49+
OS string // contains the name of the linux distribution wanted
50+
DisabledDefaultFeatures map[string]struct{} // contains the list of features that should be installed by default, but we don't want actually
51+
Force bool // set to True in order to ignore sizing recommendations
52+
FeatureParameters []string // contains parameter values of automatically installed Features
53+
DefaultSshPort uint // default ssh port for gateways // nolint
5254
}
5355

5456
// ClusterIdentity contains the bare minimum information about a cluster
@@ -59,11 +61,18 @@ type ClusterIdentity struct {
5961
Keypair *KeyPair `json:"keypair"` // Keypair contains the key-pair used inside the Cluster
6062
AdminPassword string `json:"admin_password"` // contains the password of the cladm account
6163
Tags map[string]string `json:"tags,omitempty"`
64+
ID string `json:"ID"`
6265
}
6366

6467
// NewClusterIdentity ...
6568
func NewClusterIdentity() *ClusterIdentity {
69+
aid := ""
70+
if uuid, err := uuidpkg.NewV4(); err == nil {
71+
aid = uuid.String()
72+
}
73+
6674
ci := &ClusterIdentity{
75+
ID: aid,
6776
Tags: make(map[string]string),
6877
}
6978
ci.Tags["CreationDate"] = time.Now().Format(time.RFC3339)
@@ -109,10 +118,10 @@ func (instance ClusterIdentity) GetName() string {
109118
return instance.Name
110119
}
111120

112-
// GetID returns the ID of the cluster (== GetName)
121+
// GetID returns the ID of the cluster
113122
// Satisfies interface data.Identifiable
114123
func (instance ClusterIdentity) GetID() (string, error) {
115-
return instance.GetName(), nil
124+
return instance.ID, nil
116125
}
117126

118127
// OK ...

lib/backend/resources/abstract/cluster_test.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,4 @@ func TestClusterIdentity_Replace(t *testing.T) {
236236
require.EqualValues(t, result, cluster2)
237237
require.EqualValues(t, result.(*ClusterIdentity).Keypair, kp2)
238238
require.EqualValues(t, result.(*ClusterIdentity).GetName(), cluster2.Name)
239-
clid, _ := result.(*ClusterIdentity).GetID()
240-
require.EqualValues(t, clid, cluster2.Name)
241-
242239
}

lib/backend/resources/abstract/host.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func (kp *KeyPair) IsNull() bool {
5050
func NewKeyPair(name string) (*KeyPair, fail.Error) {
5151
id, err := uuid.NewV4()
5252
if err != nil {
53-
return nil, fail.Wrap(err, "failed to create host UUID")
53+
return nil, fail.Wrap(err, "failed to create keypair UUID")
5454
}
5555

5656
if name == "" {

lib/backend/resources/abstract/subnet.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ type SubnetRequest struct {
4343
ImageRef string // contains the reference (ID or name) of the image requested for gateway(s)
4444
DefaultSSHPort uint32 // contains the port to use for SSH on all hosts of the subnet by default
4545
KeepOnFailure bool // tells if resources have to be kept in case of failure (default behavior is to delete them)
46+
ClusterID string
4647
}
4748

4849
// Subnet represents a subnet

lib/backend/resources/cluster.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ type Cluster interface {
4949
DeleteSpecificNode(ctx context.Context, hostID string, selectedMasterID string) fail.Error // deletes a node identified by its ID
5050
Delete(ctx context.Context, force bool) fail.Error // deletes the cluster (Delete is not used to not collision with metadata)
5151
FindAvailableMaster(ctx context.Context) (Host, fail.Error) // returns ID of the first master available to execute order
52-
FindAvailableNode(ctx context.Context) (Host, fail.Error) // returns node instance of the first node available to execute order
5352
GetIdentity(ctx context.Context) (abstract.ClusterIdentity, fail.Error) // returns Cluster Identity
5453
GetFlavor(ctx context.Context) (clusterflavor.Enum, fail.Error) // returns the flavor of the cluster
5554
GetComplexity(ctx context.Context) (clustercomplexity.Enum, fail.Error) // returns the complexity of the cluster
@@ -62,7 +61,6 @@ type Cluster interface {
6261
ListInstalledFeatures(ctx context.Context) ([]Feature, fail.Error) // returns the list of installed features on the Cluster
6362
ListMasters(ctx context.Context) (IndexedListOfClusterNodes, fail.Error) // lists the node instances corresponding to masters (if there is such masters in the flavor...)
6463
ListNodes(ctx context.Context) (IndexedListOfClusterNodes, fail.Error) // lists node instances corresponding to the nodes in the cluster
65-
LookupNode(ctx context.Context, ref string) (bool, fail.Error) // tells if the ID of the host passed as parameter is a node
6664
RemoveFeature(ctx context.Context, name string, vars data.Map, settings FeatureSettings) (Results, fail.Error) // removes feature from cluster
6765
Shrink(ctx context.Context, name string, count uint) ([]*propertiesv3.ClusterNode, fail.Error) // reduce the size of the cluster of 'count' nodes (the last created)
6866
Start(ctx context.Context) fail.Error // starts the cluster

lib/backend/resources/operations/cluster.go

Lines changed: 7 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ import (
5959
"github.com/CS-SI/SafeScale/v22/lib/utils/retry"
6060
"github.com/CS-SI/SafeScale/v22/lib/utils/strprocess"
6161
"github.com/CS-SI/SafeScale/v22/lib/utils/template"
62+
63+
_ "github.com/sony/gobreaker"
6264
)
6365

6466
const (
@@ -1239,9 +1241,12 @@ func (instance *Cluster) AddNodes(ctx context.Context, cluName string, count uin
12391241
}
12401242
}
12411243

1244+
ctx, ca := context.WithTimeout(ctx, timeout)
1245+
defer ca()
1246+
12421247
// for OVH, we have to ignore the errors and keep trying until we have 'count'
1243-
nodesChan := make(chan StdResult, count)
1244-
err = runWindow(ctx, count, uint(math.Min(float64(count), float64(winSize))), timeout, nodesChan, instance.taskCreateNode, taskCreateNodeParameters{
1248+
nodesChan := make(chan StdResult, 4*count)
1249+
err = runWindow(ctx, count, uint(math.Min(float64(count), float64(winSize))), nodesChan, instance.taskCreateNode, taskCreateNodeParameters{
12451250
nodeDef: nodeDef,
12461251
timeout: timings.HostCreationTimeout(),
12471252
keepOnFailure: keepOnFailure,
@@ -1579,67 +1584,6 @@ func (instance *Cluster) ListNodeNames(ctx context.Context) (list data.IndexedLi
15791584
return list, nil
15801585
}
15811586

1582-
// FindAvailableNode returns node instance of the first node available to execute order
1583-
func (instance *Cluster) FindAvailableNode(ctx context.Context) (node resources.Host, ferr fail.Error) {
1584-
defer fail.OnPanic(&ferr)
1585-
1586-
if valid.IsNil(instance) {
1587-
return nil, fail.InvalidInstanceError()
1588-
}
1589-
if ctx == nil {
1590-
return nil, fail.InvalidParameterCannotBeNilError("ctx")
1591-
}
1592-
1593-
return instance.unsafeFindAvailableNode(ctx)
1594-
}
1595-
1596-
// LookupNode tells if the ID of the master passed as parameter is a node
1597-
func (instance *Cluster) LookupNode(ctx context.Context, ref string) (found bool, ferr fail.Error) {
1598-
defer fail.OnPanic(&ferr)
1599-
1600-
if valid.IsNil(instance) {
1601-
return false, fail.InvalidInstanceError()
1602-
}
1603-
if ctx == nil {
1604-
return false, fail.InvalidParameterCannotBeNilError("ctx")
1605-
}
1606-
if ref == "" {
1607-
return false, fail.InvalidParameterError("ref", "cannot be empty string")
1608-
}
1609-
1610-
xerr := instance.beingRemoved(ctx)
1611-
xerr = debug.InjectPlannedFail(xerr)
1612-
if xerr != nil {
1613-
return false, xerr
1614-
}
1615-
1616-
var hostInstance resources.Host
1617-
hostInstance, xerr = LoadHost(ctx, instance.Service(), ref)
1618-
xerr = debug.InjectPlannedFail(xerr)
1619-
if xerr != nil {
1620-
return false, xerr
1621-
}
1622-
1623-
found = false
1624-
xerr = instance.Inspect(ctx, func(_ data.Clonable, props *serialize.JSONProperties) fail.Error {
1625-
return props.Inspect(clusterproperty.NodesV3, func(clonable data.Clonable) fail.Error {
1626-
nodesV3, ok := clonable.(*propertiesv3.ClusterNodes)
1627-
if !ok {
1628-
return fail.InconsistentError("'*propertiesv3.ClusterNodes' expected, '%s' provided", reflect.TypeOf(clonable).String())
1629-
}
1630-
1631-
hid, err := hostInstance.GetID()
1632-
if err != nil {
1633-
return fail.ConvertError(err)
1634-
}
1635-
1636-
_, found = nodesV3.PrivateNodeByID[hid]
1637-
return nil
1638-
})
1639-
})
1640-
return found, xerr
1641-
}
1642-
16431587
// deleteMaster deletes the master specified by its ID
16441588
func (instance *Cluster) deleteMaster(ctx context.Context, host string) (ferr fail.Error) {
16451589
if valid.IsNil(instance) {

lib/backend/resources/operations/cluster_test.go

Lines changed: 0 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -986,74 +986,6 @@ func TestCluster_ListNodes(t *testing.T) {
986986

987987
}
988988

989-
func TestCluster_FindAvailableNode(t *testing.T) {
990-
991-
ctx := context.Background()
992-
993-
err := NewServiceTest(t, func(svc *ServiceTest) {
994-
995-
svc._setLogLevel(0)
996-
997-
_, xerr := svc._CreateCluster(ctx, createClusterRequest(), true)
998-
require.Nil(t, xerr)
999-
1000-
cluster, xerr := LoadCluster(ctx, svc, "ClusterName")
1001-
require.Nil(t, xerr)
1002-
1003-
ocluster, ok := cluster.(*Cluster)
1004-
if !ok {
1005-
t.Error("ressources.Cluster not castable to operation.Cluster")
1006-
t.FailNow()
1007-
}
1008-
1009-
node, xerr := ocluster.FindAvailableNode(ctx)
1010-
require.Nil(t, xerr)
1011-
require.EqualValues(t, node.GetName(), "ClusterName-node-1")
1012-
1013-
})
1014-
require.Nil(t, err)
1015-
1016-
}
1017-
1018-
func TestCluster_LookupNode(t *testing.T) {
1019-
1020-
ctx := context.Background()
1021-
1022-
err := NewServiceTest(t, func(svc *ServiceTest) {
1023-
1024-
svc._setLogLevel(0)
1025-
1026-
_, xerr := svc._CreateCluster(ctx, createClusterRequest(), true)
1027-
require.Nil(t, xerr)
1028-
1029-
cluster, xerr := LoadCluster(ctx, svc, "ClusterName")
1030-
require.Nil(t, xerr)
1031-
1032-
ocluster, ok := cluster.(*Cluster)
1033-
if !ok {
1034-
t.Error("ressources.Cluster not castable to operation.Cluster")
1035-
t.FailNow()
1036-
}
1037-
1038-
found, xerr := ocluster.LookupNode(nil, "ClusterName-node-1")
1039-
require.Contains(t, xerr.Error(), "invalid parameter: ctx")
1040-
1041-
found, xerr = ocluster.LookupNode(ctx, "")
1042-
require.Contains(t, xerr.Error(), "invalid parameter: ref")
1043-
1044-
found, xerr = ocluster.LookupNode(ctx, "ClusterName-node-1")
1045-
require.Nil(t, xerr)
1046-
require.True(t, found)
1047-
1048-
found, xerr = ocluster.LookupNode(ctx, "ClusterName-node-2")
1049-
require.EqualValues(t, reflect.TypeOf(xerr).String(), "*fail.ErrNotFound")
1050-
require.False(t, found)
1051-
1052-
})
1053-
require.Nil(t, err)
1054-
1055-
}
1056-
1057989
func TestCluster_Delete(t *testing.T) {}
1058990

1059991
func TestCluster_ToProtocol(t *testing.T) {

0 commit comments

Comments
 (0)