6666 errNoPublicIPv4Addrs = errors .New ("no public ipv4 addresses set" )
6767 errNoPublicIPv6Addrs = errors .New ("no public IPv6 address set" )
6868 errNoPublicIPv6SLAACAddrs = errors .New ("no public SLAAC address set" )
69+
70+ // We have to account for the default swap in Linodes when calculating the root disk size.
71+ // While we don't actually use swap in any of our flavors (we set swapoff), we can't
72+ // explicitly set to swap to 0 for any created Linodes because it adds a 90 second hang on
73+ // cloud-init while it waits for swap regardless of the storage configuration.
74+ // This value only gets used if LinodeMachine.Spec.DataDisks.SDB isn't set
75+ // (swap is by default on /dev/sdb for created Linodes)
76+ defaultSwapDiskSize = int (resource .NewScaledQuantity (512 , resource .Mega ).ScaledValue (resource .Mega )) //nolint:mnd // already explained
6977)
7078
7179func retryIfTransient (err error , logger logr.Logger ) (ctrl.Result , error ) {
@@ -79,7 +87,7 @@ func retryIfTransient(err error, logger logr.Logger) (ctrl.Result, error) {
7987 return ctrl.Result {RequeueAfter : reconciler .WithJitter (reconciler .DefaultMachineControllerRetryDelay )}, nil
8088}
8189
82- func fillCreateConfig (createConfig * linodego.InstanceCreateOptions , machineScope * scope.MachineScope ) {
90+ func fillCreateConfig (ctx context. Context , createConfig * linodego.InstanceCreateOptions , machineScope * scope.MachineScope ) error {
8391 // This will only be empty if no interfaces or linodeInterfaces were specified in the LinodeMachine spec.
8492 // In that case we default to legacy interfaces.
8593 switch createConfig .InterfaceGeneration {
@@ -115,9 +123,22 @@ func fillCreateConfig(createConfig *linodego.InstanceCreateOptions, machineScope
115123 if createConfig .Image == "" {
116124 createConfig .Image = reconciler .DefaultMachineControllerLinodeImage
117125 }
118- if createConfig .RootPass == "" {
126+
127+ // You can now omit the root pass entirely during instance creation
128+ // as long as you supply at least one SSH key.
129+ if createConfig .RootPass == "" && len (createConfig .AuthorizedKeys ) == 0 {
119130 createConfig .RootPass = uuid .NewString ()
120131 }
132+
133+ // dynamically calculate root disk size unless an explicit OS disk is being set
134+ diskSize , err := calculateRootDisk (ctx , machineScope )
135+ if err != nil {
136+ return err
137+ }
138+ if diskSize != nil {
139+ createConfig .BootSize = diskSize
140+ }
141+ return nil
121142}
122143
123144func newCreateConfig (ctx context.Context , machineScope * scope.MachineScope , gzipCompressionEnabled bool , logger logr.Logger ) (* linodego.InstanceCreateOptions , error ) {
@@ -135,7 +156,9 @@ func newCreateConfig(ctx context.Context, machineScope *scope.MachineScope, gzip
135156 return nil , err
136157 }
137158
138- fillCreateConfig (createConfig , machineScope )
159+ if err := fillCreateConfig (ctx , createConfig , machineScope ); err != nil {
160+ return nil , err
161+ }
139162
140163 // Configure VPC interface if needed
141164 if err := configureVPCInterface (ctx , machineScope , createConfig , logger ); err != nil {
@@ -989,7 +1012,7 @@ func constructLinodeInterfaceCreateOpts(createOpts []infrav1alpha2.LinodeInterfa
9891012 firewallID = iface .FirewallID
9901013 }
9911014 if firewallID != nil {
992- ifaceCreateOpts .FirewallID = ptr . To ( firewallID )
1015+ ifaceCreateOpts .FirewallID = firewallID
9931016 }
9941017 // createOpts is now fully populated with the interface options
9951018 linodeInterfaces [idx ] = ifaceCreateOpts
@@ -1290,9 +1313,6 @@ func configureDisks(ctx context.Context, logger logr.Logger, machineScope *scope
12901313 return nil
12911314 }
12921315
1293- if err := resizeRootDisk (ctx , logger , machineScope , linodeInstanceID ); err != nil {
1294- return err
1295- }
12961316 if ! reconciler .ConditionTrue (machineScope .LinodeMachine .GetCondition (ConditionPreflightAdditionalDisksCreated )) {
12971317 if err := createDisks (ctx , logger , machineScope , linodeInstanceID ); err != nil {
12981318 return err
@@ -1381,94 +1401,23 @@ func configureDisk(ctx context.Context, logger logr.Logger, machineScope *scope.
13811401 return nil
13821402}
13831403
1384- func resizeRootDisk (ctx context.Context , logger logr.Logger , machineScope * scope.MachineScope , linodeInstanceID int ) error {
1385- if reconciler .ConditionTrue (machineScope .LinodeMachine .GetCondition (ConditionPreflightRootDiskResized )) {
1386- return nil
1387- }
1388-
1389- instanceConfig , err := getDefaultInstanceConfig (ctx , machineScope , linodeInstanceID )
1390- if err != nil {
1391- logger .Error (err , "Failed to get default instance configuration" )
1392-
1393- machineScope .LinodeMachine .SetCondition (metav1.Condition {
1394- Type : ConditionPreflightRootDiskResized ,
1395- Status : metav1 .ConditionFalse ,
1396- Reason : util .CreateError ,
1397- Message : err .Error (),
1398- })
1399- return err
1400- }
1401-
1402- if instanceConfig .Devices .SDA == nil {
1403- machineScope .LinodeMachine .SetCondition (metav1.Condition {
1404- Type : ConditionPreflightRootDiskResized ,
1405- Status : metav1 .ConditionFalse ,
1406- Reason : util .CreateError ,
1407- Message : "root disk not yet ready" ,
1408- })
1409-
1410- return errors .New ("root disk not yet ready" )
1411- }
1412-
1413- rootDiskID := instanceConfig .Devices .SDA .DiskID
1414-
1415- // carve out space for the etcd disk
1416- if ! reconciler .ConditionTrue (machineScope .LinodeMachine .GetCondition (ConditionPreflightRootDiskResizing )) {
1417- rootDisk , err := machineScope .LinodeClient .GetInstanceDisk (ctx , linodeInstanceID , rootDiskID )
1418- if err != nil {
1419- logger .Error (err , "Failed to get root disk for instance" )
1420-
1421- machineScope .LinodeMachine .SetCondition (metav1.Condition {
1422- Type : ConditionPreflightRootDiskResizing ,
1423- Status : metav1 .ConditionFalse ,
1424- Reason : util .CreateError ,
1425- Message : err .Error (),
1426- })
1427-
1428- return err
1429- }
1430- // dynamically calculate root disk size unless an explicit OS disk is being set
1431- diskSize := calculateRootDisk (machineScope , rootDisk )
1432-
1433- if err := machineScope .LinodeClient .ResizeInstanceDisk (ctx , linodeInstanceID , rootDiskID , diskSize ); err != nil {
1434- machineScope .LinodeMachine .SetCondition (metav1.Condition {
1435- Type : ConditionPreflightRootDiskResizing ,
1436- Status : metav1 .ConditionFalse ,
1437- Reason : util .CreateError ,
1438- Message : err .Error (),
1439- })
1440- return err
1441- }
1442- machineScope .LinodeMachine .SetCondition (metav1.Condition {
1443- Type : ConditionPreflightRootDiskResizing ,
1444- Status : metav1 .ConditionTrue ,
1445- Reason : "RootDiskResizing" ,
1446- })
1447- }
1448-
1449- machineScope .LinodeMachine .DeleteCondition (ConditionPreflightRootDiskResizing )
1450- machineScope .LinodeMachine .SetCondition (metav1.Condition {
1451- Type : ConditionPreflightRootDiskResized ,
1452- Status : metav1 .ConditionTrue ,
1453- Reason : "RootDiskResized" ,
1454- })
1455-
1456- return nil
1457- }
1458-
1459- func calculateRootDisk (machineScope * scope.MachineScope , rootDisk * linodego.InstanceDisk ) int {
1404+ func calculateRootDisk (ctx context.Context , machineScope * scope.MachineScope ) (* int , error ) {
14601405 additionalDiskSize := 0
1461- // If the user has specified an OS disk, use it's size.
1406+ // If the user has specified an OS disk, use its size.
14621407 if machineScope .LinodeMachine .Spec .OSDisk != nil {
1463- return int (machineScope .LinodeMachine .Spec .OSDisk .Size .ScaledValue (resource .Mega ))
1408+ return ptr . To ( int (machineScope .LinodeMachine .Spec .OSDisk .Size .ScaledValue (resource .Mega ))), nil
14641409 }
1465- // If no DataDisks are specified, use the default root disk size.
1410+ // If no DataDisks are specified, omit the size
14661411 if machineScope .LinodeMachine .Spec .DataDisks == nil {
1467- return rootDisk . Size
1412+ return nil , nil //nolint:nilnil // we want to let the API default the size if there are no other disks to make room for
14681413 }
1414+
14691415 // If DataDisks are specified, calculate the size of the additional disk + root disk for resizing.
14701416 if machineScope .LinodeMachine .Spec .DataDisks .SDB != nil {
14711417 additionalDiskSize += int (machineScope .LinodeMachine .Spec .DataDisks .SDB .Size .ScaledValue (resource .Mega ))
1418+ } else {
1419+ // account for the 512 MB default swap disk
1420+ additionalDiskSize += defaultSwapDiskSize
14721421 }
14731422 if machineScope .LinodeMachine .Spec .DataDisks .SDC != nil {
14741423 additionalDiskSize += int (machineScope .LinodeMachine .Spec .DataDisks .SDC .Size .ScaledValue (resource .Mega ))
@@ -1488,8 +1437,13 @@ func calculateRootDisk(machineScope *scope.MachineScope, rootDisk *linodego.Inst
14881437 if machineScope .LinodeMachine .Spec .DataDisks .SDH != nil {
14891438 additionalDiskSize += int (machineScope .LinodeMachine .Spec .DataDisks .SDH .Size .ScaledValue (resource .Mega ))
14901439 }
1491- diskSize := rootDisk .Size - additionalDiskSize
1492- return diskSize
1440+ planType , err := machineScope .LinodeClient .GetType (ctx , machineScope .LinodeMachine .Spec .Type )
1441+ if err != nil {
1442+ return nil , err
1443+ }
1444+ diskSize := planType .Disk - additionalDiskSize
1445+
1446+ return ptr .To (diskSize ), nil
14931447}
14941448
14951449func updateInstanceConfigProfile (ctx context.Context , logger logr.Logger , machineScope * scope.MachineScope , linodeInstanceID int ) error {
@@ -1638,7 +1592,7 @@ func configureFirewall(ctx context.Context, machineScope *scope.MachineScope, cr
16381592
16391593 // If using LinodeInterfaces that needs to know about the firewall ID
16401594 for i := range createConfig .LinodeInterfaces {
1641- createConfig .LinodeInterfaces [i ].FirewallID = ptr .To (ptr . To ( fwID ) )
1595+ createConfig .LinodeInterfaces [i ].FirewallID = ptr .To (fwID )
16421596 }
16431597
16441598 return nil
0 commit comments