@@ -462,6 +462,10 @@ func GetSecurityGroups(is *InstanceService, sg_param []openstackconfigv1.Securit
462462// If ServerGroupName is nonempty and no server group exists with that name,
463463// then InstanceCreate creates a server group with that name.
464464func (is * InstanceService ) InstanceCreate (clusterName string , name string , clusterSpec * openstackconfigv1.OpenstackClusterProviderSpec , config * openstackconfigv1.OpenstackProviderSpec , cmd string , keyName string , configClient configclient.ConfigV1Interface ) (instance * Instance , err error ) {
465+ // This variable is used in early returns to trigger the deletion of
466+ // associated resources in case of failure to create the server.
467+ needsCleanup := true
468+
465469 if config == nil {
466470 return nil , fmt .Errorf ("create Options need be specified to create instace" )
467471 }
@@ -475,8 +479,6 @@ func (is *InstanceService) InstanceCreate(clusterName string, name string, clust
475479 }
476480 }
477481
478- var cleanupOperationsInCaseOfServerCreationFailure []func () error
479-
480482 // Set default Tags
481483 machineTags := []string {
482484 "cluster-api-provider-openstack" ,
@@ -713,7 +715,7 @@ func (is *InstanceService) InstanceCreate(clusterName string, name string, clust
713715 volumeName := name
714716
715717 // if source type is "image" then we have to create a volume from the image first
716- klog .Infof ("Creating bootable volume with name %q from image %v ." , volumeName , config .RootVolume .SourceUUID )
718+ klog .Infof ("Creating bootable volume with name %q from image %q ." , volumeName , config .RootVolume .SourceUUID )
717719
718720 // Deleting any volumes with the same name, as they may
719721 // be leftovers from a previous failed try.
@@ -750,21 +752,23 @@ func (is *InstanceService) InstanceCreate(clusterName string, name string, clust
750752 if err != nil {
751753 return nil , fmt .Errorf ("Create bootable volume err: %v" , err )
752754 }
753-
754- cleanupOperationsInCaseOfServerCreationFailure = append (cleanupOperationsInCaseOfServerCreationFailure , func () error {
755- return volumes .Delete (is .volumeClient , volume .ID , nil ).ExtractErr ()
756- })
757755 volumeID = volume .ID
758756
759- err = volumes .WaitForStatus (is .volumeClient , volumeID , "available" , 300 )
760- if err != nil {
761- klog .Infof ("Bootable volume %v creation failed. Removing..." , volumeID )
762- err = volumes .Delete (is .volumeClient , volumeID , volumes.DeleteOpts {}).ExtractErr ()
763- if err != nil {
764- return nil , fmt .Errorf ("Bootable volume deletion err: %v" , err )
757+ defer func () {
758+ // If the server is created in Nova, the lifetime of the associated volume will be
759+ // bound to it. This deferred cleanup function tackles the case where a volume was created
760+ // but never attached to a server. In that case, the volume must be removed manually.
761+ if needsCleanup == true {
762+ if err := volumes .Delete (is .volumeClient , volumeID , nil ).ExtractErr (); err != nil {
763+ klog .Infof ("Failed to delete stale volume %q" , volumeID )
764+ } else {
765+ klog .Infof ("Deleted stale volume %q" , volumeID )
766+ }
765767 }
768+ }()
766769
767- return nil , fmt .Errorf ("Bootable volume %v is not available err: %v" , volumeID , err )
770+ if err := volumes .WaitForStatus (is .volumeClient , volumeID , "available" , 300 ); err != nil {
771+ return nil , fmt .Errorf ("bootable volume is not available: %v" , err )
768772 }
769773
770774 klog .Infof ("Bootable volume %v was created successfully." , volumeID )
@@ -839,19 +843,17 @@ func (is *InstanceService) InstanceCreate(clusterName string, name string, clust
839843 }
840844 }
841845
842- server , err : = servers .Create (is .computeClient , keypairs.CreateOptsExt {
846+ server , err = servers .Create (is .computeClient , keypairs.CreateOptsExt {
843847 CreateOptsBuilder : serverCreateOpts ,
844848 KeyName : keyName ,
845849 }).Extract ()
846850 if err != nil {
847- for _ , cleanup := range cleanupOperationsInCaseOfServerCreationFailure {
848- if e := cleanup (); e != nil {
849- err = fmt .Errorf ("%w. Additionally: %v" , err , e )
850- }
851- }
852851 return nil , err
853852 }
854853
854+ // Disabling cleanup functions because server creation was successful.
855+ needsCleanup = false
856+
855857 is .computeClient .Microversion = ""
856858 return serverToInstance (server ), nil
857859}
0 commit comments