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

Commit 0ae2170

Browse files
committed
Add local storage
1 parent 2936045 commit 0ae2170

File tree

7 files changed

+94
-39
lines changed

7 files changed

+94
-39
lines changed

api/v1beta1/scalewaymachine_types.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package v1beta1
22

33
import (
4+
"fmt"
5+
6+
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
47
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
58
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
69
)
@@ -23,6 +26,12 @@ type ScalewayMachineSpec struct {
2326
// +optional
2427
RootVolumeSize *int64 `json:"rootVolumeSize,omitempty"`
2528

29+
// Type of the root volume. Can be local or block. Note that not all types
30+
// of instances support local volumes.
31+
// +kubebuilder:validation:Enum=local;block
32+
// +optional
33+
RootVolumeType *string `json:"rootVolumeType,omitempty"`
34+
2635
// Set to true to create and attach a public IP to the instance.
2736
// Defaults to false.
2837
// +optional
@@ -34,6 +43,22 @@ type ScalewayMachineSpec struct {
3443
SecurityGroupName *string `json:"securityGroupName,omitempty"`
3544
}
3645

46+
// ScalewayRootVolumeType returns the volume type to use for the root volume.
47+
func (s *ScalewayMachineSpec) ScalewayRootVolumeType() (instance.VolumeVolumeType, error) {
48+
if s.RootVolumeType == nil {
49+
return instance.VolumeVolumeTypeBSSD, nil
50+
}
51+
52+
switch *s.RootVolumeType {
53+
case "local":
54+
return instance.VolumeVolumeTypeLSSD, nil
55+
case "block":
56+
return instance.VolumeVolumeTypeBSSD, nil
57+
default:
58+
return "", fmt.Errorf("unsupported root volume type: %s", *s.RootVolumeType)
59+
}
60+
}
61+
3762
// ScalewayMachineStatus defines the observed state of ScalewayMachine
3863
type ScalewayMachineStatus struct {
3964
// Ready is true when the provider resource is ready.

api/v1beta1/scalewaymachine_webhook.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,14 @@ func (r *ScalewayMachine) enforceImmutability(old *ScalewayMachine) error {
5656
allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "type"), r.Spec.Type, "field is immutable"))
5757
}
5858

59-
if old.Spec.RootVolumeSize != nil && r.Spec.RootVolumeSize != nil && *r.Spec.RootVolumeSize != *old.Spec.RootVolumeSize {
59+
if !reflect.DeepEqual(old.Spec.RootVolumeSize, r.Spec.RootVolumeSize) {
6060
allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "rootVolumeSize"), r.Spec.RootVolumeSize, "field is immutable"))
6161
}
6262

63+
if !reflect.DeepEqual(old.Spec.RootVolumeType, r.Spec.RootVolumeType) {
64+
allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "rootVolumeType"), r.Spec.RootVolumeType, "field is immutable"))
65+
}
66+
6367
// Once PublicIP is set, it is immutable.
6468
if old.Spec.PublicIP != nil && !reflect.DeepEqual(old.Spec.PublicIP, r.Spec.PublicIP) {
6569
allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "publicIP"), r.Spec.PublicIP, "field is immutable"))

api/v1beta1/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/infrastructure.cluster.x-k8s.io_scalewaymachines.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ spec:
4848
description: Size of the root volume in GB. Defaults to 20 GB.
4949
format: int64
5050
type: integer
51+
rootVolumeType:
52+
description: Type of the root volume. Can be local or block. Note
53+
that not all types of instances support local volumes.
54+
enum:
55+
- local
56+
- block
57+
type: string
5158
securityGroupName:
5259
description: Name of the security group as specified in the ScalewayCluster
5360
object. If not set, the instance will be attached to the default

config/crd/bases/infrastructure.cluster.x-k8s.io_scalewaymachinetemplates.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ spec:
6464
GB.
6565
format: int64
6666
type: integer
67+
rootVolumeType:
68+
description: Type of the root volume. Can be local or block.
69+
Note that not all types of instances support local volumes.
70+
enum:
71+
- local
72+
- block
73+
type: string
6774
securityGroupName:
6875
description: Name of the security group as specified in the
6976
ScalewayCluster object. If not set, the instance will be

internal/controller/scalewaymachine_controller.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -153,14 +153,7 @@ func (r *ScalewayMachineReconciler) reconcileNormal(ctx context.Context, machine
153153
}
154154

155155
func (r *ScalewayMachineReconciler) reconcileDelete(ctx context.Context, machineScope *scope.Machine) (ctrl.Result, error) {
156-
l := log.FromContext(ctx)
157-
158156
if err := instance.NewService(machineScope).Delete(ctx); err != nil {
159-
if errors.Is(err, instance.ErrInstanceNotStoppedYet) {
160-
l.Info("Waiting for instance to stop")
161-
return ctrl.Result{RequeueAfter: 2 * time.Second}, nil
162-
}
163-
164157
return ctrl.Result{}, err
165158
}
166159

internal/service/scaleway/instance/instance.go

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ import (
2121
)
2222

2323
var (
24-
ErrPrivateIPNotFound = errors.New("private IP not found in IPAM")
25-
ErrInstanceNotStoppedYet = errors.New("instance is being stopped")
24+
ErrPrivateIPNotFound = errors.New("private IP not found in IPAM")
2625
)
2726

2827
var errMachineHasNoIP = errors.New("machine has no IP")
@@ -104,6 +103,11 @@ func (s *Service) getOrCreateServer(ctx context.Context, ip *instance.IP) (*inst
104103
sgID = &sg.ID
105104
}
106105

106+
volType, err := s.ScalewayMachine.Spec.ScalewayRootVolumeType()
107+
if err != nil {
108+
return nil, err
109+
}
110+
107111
req := &instance.CreateServerRequest{
108112
Zone: s.Zone(),
109113
Name: s.Name(),
@@ -115,7 +119,7 @@ func (s *Service) getOrCreateServer(ctx context.Context, ip *instance.IP) (*inst
115119
Volumes: map[string]*instance.VolumeServerTemplate{
116120
"0": {
117121
Size: scw.SizePtr(rootSize),
118-
VolumeType: instance.VolumeVolumeTypeBSSD,
122+
VolumeType: instance.VolumeVolumeType(volType),
119123
Boot: scw.BoolPtr(true),
120124
},
121125
},
@@ -492,50 +496,60 @@ func (s *Service) Delete(ctx context.Context) error {
492496
if err := s.ScalewayClient.Instance.DeleteIP(&instance.DeleteIPRequest{
493497
Zone: server.Zone,
494498
IP: server.PublicIP.ID,
495-
}); err != nil {
499+
}, scw.WithContext(ctx)); err != nil {
496500
return err
497501
}
498502
}
499503

500-
switch server.State {
501-
case instance.ServerStateRunning, instance.ServerStateStoppedInPlace:
502-
if _, err := s.ScalewayClient.Instance.ServerAction(&instance.ServerActionRequest{
503-
Zone: server.Zone,
504-
ServerID: server.ID,
505-
Action: instance.ServerActionPoweroff,
506-
}); err != nil {
507-
return fmt.Errorf("failed to poweroff server: %w", err)
504+
// Detach all non-boot volumes.
505+
for _, vol := range server.Volumes {
506+
if vol.Boot {
507+
continue
508508
}
509509

510-
return ErrInstanceNotStoppedYet
511-
case instance.ServerStateStopping:
512-
return ErrInstanceNotStoppedYet
513-
case instance.ServerStateLocked:
514-
return errors.New("instance is locked")
515-
}
516-
517-
// Remove boot volume.
518-
if v, ok := server.Volumes["0"]; ok && v.Boot {
519510
if _, err := s.ScalewayClient.Instance.DetachVolume(&instance.DetachVolumeRequest{
520511
Zone: server.Zone,
521-
VolumeID: v.ID,
522-
}); err != nil {
523-
return fmt.Errorf("failed to detach boot volume: %w", err)
512+
VolumeID: vol.ID,
513+
}, scw.WithContext(ctx)); err != nil {
514+
return fmt.Errorf("failed to detach volume %q: %w", vol.ID, err)
524515
}
516+
}
525517

526-
if err := s.ScalewayClient.Instance.DeleteVolume(&instance.DeleteVolumeRequest{
518+
// If server is stopped, remove boot volume and delete the server.
519+
if server.State == instance.ServerStateStopped {
520+
// Remove boot volume.
521+
if v, ok := server.Volumes["0"]; ok && v.Boot {
522+
if _, err := s.ScalewayClient.Instance.DetachVolume(&instance.DetachVolumeRequest{
523+
Zone: server.Zone,
524+
VolumeID: v.ID,
525+
}, scw.WithContext(ctx)); err != nil {
526+
return fmt.Errorf("failed to detach boot volume: %w", err)
527+
}
528+
529+
if err := s.ScalewayClient.Instance.DeleteVolume(&instance.DeleteVolumeRequest{
530+
Zone: server.Zone,
531+
VolumeID: v.ID,
532+
}, scw.WithContext(ctx)); err != nil {
533+
return fmt.Errorf("failed to delete instance volume: %w", err)
534+
}
535+
}
536+
537+
if err := s.ScalewayClient.Instance.DeleteServer(&instance.DeleteServerRequest{
527538
Zone: server.Zone,
528-
VolumeID: v.ID,
529-
}); err != nil {
530-
return fmt.Errorf("failed to delete instance volume: %w", err)
539+
ServerID: server.ID,
540+
}, scw.WithContext(ctx)); err != nil {
541+
return fmt.Errorf("failed to delete instance: %w", err)
531542
}
543+
544+
return nil
532545
}
533546

534-
if err := s.ScalewayClient.Instance.DeleteServer(&instance.DeleteServerRequest{
547+
if _, err := s.ScalewayClient.Instance.ServerAction(&instance.ServerActionRequest{
535548
Zone: server.Zone,
536549
ServerID: server.ID,
537-
}); err != nil {
538-
return fmt.Errorf("failed to delete instance: %w", err)
550+
Action: instance.ServerActionTerminate,
551+
}, scw.WithContext(ctx)); err != nil {
552+
return fmt.Errorf("failed to terminate server: %w", err)
539553
}
540554

541555
return nil

0 commit comments

Comments
 (0)