Skip to content

Commit c9ee29b

Browse files
committed
openstack: Remove FIPs created by the installer
Added cleanup for bootstrap VM FIP in the insatller as part of the PostDestroyer to streamline FIP creation and deletion to be done by the installer avoiding orphan FIPs.
1 parent 93c4228 commit c9ee29b

File tree

3 files changed

+89
-5
lines changed

3 files changed

+89
-5
lines changed

pkg/infrastructure/openstack/clusterapi/clusterapi.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package clusterapi
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67

78
"github.com/sirupsen/logrus"
@@ -193,10 +194,18 @@ func (p Provider) PostDestroy(ctx context.Context, in clusterapi.PostDestroyerIn
193194
cloud := in.Metadata.OpenStack.Cloud
194195
infraID := in.Metadata.InfraID
195196

197+
// Best effort approach trying to delete SG even in case FIP fails
198+
var errs []error
199+
200+
// Delete floating IPs tagged with the cluster ID and bootstrap role
201+
if err := postdestroy.FloatingIPs(ctx, cloud, infraID); err != nil {
202+
errs = append(errs, err)
203+
}
204+
196205
// Delete security groups tagged with the cluster ID and bootstrap role
197206
if err := postdestroy.SecurityGroups(ctx, cloud, infraID); err != nil {
198-
return fmt.Errorf("failed to destroy bootstrap security groups: %w", err)
207+
errs = append(errs, err)
199208
}
200209

201-
return nil
210+
return errors.Join(errs...)
202211
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package postdestroy
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
"net/http"
8+
9+
"github.com/gophercloud/gophercloud/v2"
10+
"github.com/gophercloud/gophercloud/v2/openstack/networking/v2/extensions/layer3/floatingips"
11+
"github.com/sirupsen/logrus"
12+
13+
openstackdefaults "github.com/openshift/installer/pkg/types/openstack/defaults"
14+
)
15+
16+
// FloatingIPs deletes the bootstrap floating IP that was previously disassociated
17+
// (but not deleted) when the bootstrap machine was destroyed by CAPO.
18+
func FloatingIPs(ctx context.Context, cloud string, infraID string) error {
19+
clusterTag := fmt.Sprintf("openshiftClusterID=%s", infraID)
20+
roleTag := "openshiftRole=bootstrap"
21+
logrus.Debugf("Searching for bootstrap floating IP with tags: %s, %s", clusterTag, roleTag)
22+
23+
networkClient, err := openstackdefaults.NewServiceClient(ctx, "network", openstackdefaults.DefaultClientOpts(cloud))
24+
if err != nil {
25+
return fmt.Errorf("failed to create network client: %w", err)
26+
}
27+
28+
// Search for floating IPs with both cluster ID and role tags
29+
// OpenStack tags filter requires ALL specified tags to match (AND logic)
30+
allPages, err := floatingips.List(networkClient, floatingips.ListOpts{
31+
Tags: fmt.Sprintf("%s,%s", clusterTag, roleTag),
32+
}).AllPages(ctx)
33+
if err != nil {
34+
return fmt.Errorf("failed to list floating IPs: %w", err)
35+
}
36+
37+
fips, err := floatingips.ExtractFloatingIPs(allPages)
38+
if err != nil {
39+
return fmt.Errorf("failed to extract floating IPs: %w", err)
40+
}
41+
42+
if len(fips) == 0 {
43+
logrus.Debug("No bootstrap floating IP found (may have already been deleted)")
44+
return nil
45+
}
46+
47+
// Should only find one FIP with both tags, but delete all if multiple exist
48+
var errs []error
49+
for _, fip := range fips {
50+
logrus.Infof("Deleting bootstrap floating IP %s (ID: %s)", fip.FloatingIP, fip.ID)
51+
52+
err = floatingips.Delete(ctx, networkClient, fip.ID).ExtractErr()
53+
if err != nil {
54+
// Check if it's a "not found" error, which is acceptable
55+
if gophercloud.ResponseCodeIs(err, http.StatusNotFound) {
56+
logrus.Debugf("Bootstrap floating IP %s already deleted", fip.ID)
57+
continue
58+
}
59+
logrus.Errorf("Failed to delete bootstrap floating IP %s: %v", fip.FloatingIP, err)
60+
errs = append(errs, fmt.Errorf("failed to delete bootstrap floating IP %s: %w", fip.FloatingIP, err))
61+
continue
62+
}
63+
64+
logrus.Infof("Successfully deleted bootstrap floating IP %s", fip.FloatingIP)
65+
}
66+
67+
return errors.Join(errs...)
68+
}

pkg/infrastructure/openstack/postprovision/floatingips.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,18 @@ func createAndAttachFIP(ctx context.Context, client *gophercloud.ServiceClient,
8585
return nil, err
8686
}
8787

88-
tag := fmt.Sprintf("openshiftClusterID=%s", infraID)
89-
err = attributestags.Add(ctx, client, "floatingips", floatingIP.ID, tag).ExtractErr()
88+
// Tag the floating IP with cluster ID and role for proper lifecycle management
89+
clusterTag := fmt.Sprintf("openshiftClusterID=%s", infraID)
90+
err = attributestags.Add(ctx, client, "floatingips", floatingIP.ID, clusterTag).ExtractErr()
9091
if err != nil {
9192
return nil, err
9293
}
9394

94-
return floatingIP, err
95+
roleTag := fmt.Sprintf("openshiftRole=%s", role)
96+
err = attributestags.Add(ctx, client, "floatingips", floatingIP.ID, roleTag).ExtractErr()
97+
if err != nil {
98+
return nil, err
99+
}
100+
101+
return floatingIP, nil
95102
}

0 commit comments

Comments
 (0)