Skip to content

Commit c27e2ee

Browse files
Bug 1983612: Make InstanceCreate idempotent
Prior to this change, if machine-controller gets reprovisioned in the middle of running InstanceCreate, stale volumes might be left on the cluster. With this change, before creating a new root volume for an instance, InstanceCreate deletes any volumes with the same name.
1 parent 53eddee commit c27e2ee

File tree

2 files changed

+53
-6
lines changed

2 files changed

+53
-6
lines changed

pkg/cloud/openstack/clients/machineservice.go

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -707,8 +707,28 @@ func (is *InstanceService) InstanceCreate(clusterName string, name string, clust
707707
}
708708

709709
if bootfromvolume.SourceType(config.RootVolume.SourceType) == bootfromvolume.SourceImage {
710+
// Name the volume after the instance
711+
volumeName := name
712+
710713
// if source type is "image" then we have to create a volume from the image first
711-
klog.Infof("Creating a bootable volume from image %v.", config.RootVolume.SourceUUID)
714+
klog.Infof("Creating bootable volume with name %q from image %v.", volumeName, config.RootVolume.SourceUUID)
715+
716+
// Deleting any volumes with the same name, as they may
717+
// be leftovers from a previous failed try.
718+
{
719+
volumeIDs, err := volumeIDsFromName(is.volumeClient, volumeName)
720+
if err != nil {
721+
klog.Infof("unable to list volumes with name %q: %v.", volumeName, err)
722+
}
723+
724+
for _, volumeID := range volumeIDs {
725+
if err := volumes.Delete(is.volumeClient, volumeID, nil).ExtractErr(); err != nil {
726+
klog.Infof("unable to delete volume with ID %q: %v.", volumeID, err)
727+
} else {
728+
klog.Infof("deleted volume with name %q and ID %q", volumeName, volumeID)
729+
}
730+
}
731+
}
712732

713733
imageID, err := imageutils.IDFromName(is.imagesClient, config.RootVolume.SourceUUID)
714734
if err != nil {
@@ -717,11 +737,10 @@ func (is *InstanceService) InstanceCreate(clusterName string, name string, clust
717737

718738
// Create a volume first
719739
volumeCreateOpts := volumes.CreateOpts{
720-
Size: config.RootVolume.Size,
721-
VolumeType: config.RootVolume.VolumeType,
722-
ImageID: imageID,
723-
// The same name as the instance
724-
Name: name,
740+
Size: config.RootVolume.Size,
741+
VolumeType: config.RootVolume.VolumeType,
742+
ImageID: imageID,
743+
Name: volumeName,
725744
AvailabilityZone: config.RootVolume.Zone,
726745
}
727746

pkg/cloud/openstack/clients/utils.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
"github.com/gophercloud/gophercloud"
1111
"github.com/gophercloud/gophercloud/openstack"
12+
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes"
1213
"github.com/gophercloud/utils/openstack/clientconfig"
1314
machinev1 "github.com/openshift/machine-api-operator/pkg/apis/machine/v1beta1"
1415

@@ -106,3 +107,30 @@ func GetProviderClient(cloud clientconfig.Cloud, cert []byte) (*gophercloud.Prov
106107

107108
return provider, nil
108109
}
110+
111+
// volumeIDsFromName returns zero or more volume IDs corresponding to a name.
112+
// The returned error is only non-nil in case of failure.
113+
func volumeIDsFromName(client *gophercloud.ServiceClient, name string) ([]string, error) {
114+
listOpts := volumes.ListOpts{
115+
Name: name,
116+
}
117+
118+
pages, err := volumes.List(client, listOpts).AllPages()
119+
if err != nil {
120+
return nil, err
121+
}
122+
123+
all, err := volumes.ExtractVolumes(pages)
124+
if err != nil {
125+
return nil, err
126+
}
127+
128+
IDs := make([]string, 0, len(all))
129+
for _, s := range all {
130+
if s.Name == name {
131+
IDs = append(IDs, s.ID)
132+
}
133+
}
134+
135+
return IDs, nil
136+
}

0 commit comments

Comments
 (0)