Skip to content

Commit a9d872e

Browse files
authored
Merge pull request #2815 from nikParasyr/issue-2763
🐛 Ensure pool member reach active state
2 parents ee82a04 + bd31bfc commit a9d872e

File tree

4 files changed

+84
-7
lines changed

4 files changed

+84
-7
lines changed

pkg/clients/loadbalancer.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ type LbClient interface {
5151
DeletePool(id string) error
5252
CreatePoolMember(poolID string, opts pools.CreateMemberOptsBuilder) (*pools.Member, error)
5353
ListPoolMember(poolID string, opts pools.ListMembersOptsBuilder) ([]pools.Member, error)
54+
GetPoolMember(poolID string, lbMemberID string) (*pools.Member, error)
5455
DeletePoolMember(poolID string, lbMemberID string) error
5556
CreateMonitor(opts monitors.CreateOptsBuilder) (*monitors.Monitor, error)
5657
ListMonitors(opts monitors.ListOptsBuilder) ([]monitors.Monitor, error)
@@ -213,6 +214,15 @@ func (l lbClient) ListPoolMember(poolID string, opts pools.ListMembersOptsBuilde
213214
return pools.ExtractMembers(allPages)
214215
}
215216

217+
func (l lbClient) GetPoolMember(poolID string, lbMemberID string) (*pools.Member, error) {
218+
mc := metrics.NewMetricPrometheusContext("loadbalancer_member", "get")
219+
member, err := pools.GetMember(context.TODO(), l.serviceClient, poolID, lbMemberID).Extract()
220+
if mc.ObserveRequest(err) != nil {
221+
return nil, fmt.Errorf("error getting lbmember: %s", err)
222+
}
223+
return member, nil
224+
}
225+
216226
func (l lbClient) DeletePoolMember(poolID string, lbMemberID string) error {
217227
mc := metrics.NewMetricPrometheusContext("loadbalancer_member", "delete")
218228
err := pools.DeleteMember(context.TODO(), l.serviceClient, poolID, lbMemberID).ExtractErr()

pkg/clients/mock/loadbalancer.go

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

pkg/cloud/services/loadbalancer/loadbalancer.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ const (
5252
const (
5353
loadBalancerProvisioningStatusActive = "ACTIVE"
5454
loadBalancerProvisioningStatusPendingDelete = "PENDING_DELETE"
55+
poolMemberProvisioningStatusActive = "ACTIVE"
5556
)
5657

5758
// Default values for Monitor, sync with `kubebuilder:default` annotations on APIServerLoadBalancerMonitor object.
@@ -718,7 +719,12 @@ func (s *Service) ReconcileLoadBalancerMember(openStackCluster *infrav1.OpenStac
718719
return err
719720
}
720721

721-
if _, err := s.loadbalancerClient.CreatePoolMember(pool.ID, lbMemberOpts); err != nil {
722+
member, err := s.loadbalancerClient.CreatePoolMember(pool.ID, lbMemberOpts)
723+
if err != nil {
724+
return err
725+
}
726+
727+
if _, err := s.waitForPoolMemberActive(pool.ID, member.ID); err != nil {
722728
return err
723729
}
724730

@@ -932,6 +938,25 @@ func (s *Service) waitForLoadBalancerActive(id string) (*loadbalancers.LoadBalan
932938
return lb, nil
933939
}
934940

941+
// Possible Pool Member states are documented here: https://docs.openstack.org/api-ref/load-balancer/v2/#prov-status
942+
func (s *Service) waitForPoolMemberActive(poolID, memberID string) (*pools.Member, error) {
943+
var member *pools.Member
944+
945+
s.scope.Logger().Info("Waiting for pool member", "pool_id", poolID, "member_id", memberID, "targetStatus", "ACTIVE")
946+
err := wait.ExponentialBackoff(backoff, func() (bool, error) {
947+
var err error
948+
member, err = s.loadbalancerClient.GetPoolMember(poolID, memberID)
949+
if err != nil {
950+
return false, err
951+
}
952+
return member.ProvisioningStatus == poolMemberProvisioningStatusActive, nil
953+
})
954+
if err != nil {
955+
return nil, err
956+
}
957+
return member, nil
958+
}
959+
935960
func (s *Service) waitForListener(id, target string) error {
936961
s.scope.Logger().Info("Waiting for load balancer listener", "id", id, "targetStatus", target)
937962
return wait.ExponentialBackoff(backoff, func() (bool, error) {

pkg/cloud/services/loadbalancer/loadbalancer_test.go

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,8 +1052,19 @@ func Test_ReconcileLoadBalancerMember(t *testing.T) {
10521052
).DoAndReturn(func(_ string, got pools.CreateMemberOpts) (*pools.Member, error) {
10531053
// SubnetID must be empty here
10541054
g.Expect(got.SubnetID).To(Equal(""))
1055-
return &pools.Member{ID: "member-2"}, nil
1055+
return &pools.Member{ID: memberID}, nil
10561056
})
1057+
1058+
pendingMember := pools.Member{
1059+
ID: memberID,
1060+
Name: poolMemberName,
1061+
ProvisioningStatus: "PENDING_CREATE",
1062+
}
1063+
m.GetPoolMember(poolID, memberID).Return(&pendingMember, nil)
1064+
1065+
activeMember := pendingMember
1066+
activeMember.ProvisioningStatus = "ACTIVE"
1067+
m.GetPoolMember(poolID, memberID).Return(&activeMember, nil)
10571068
},
10581069
wantError: nil,
10591070
},
@@ -1092,8 +1103,10 @@ func Test_ReconcileLoadBalancerMember(t *testing.T) {
10921103
}
10931104
m.ListPools(pools.ListOpts{Name: pool.Name}).Return([]pools.Pool{pool}, nil)
10941105

1106+
poolMemberName := fmt.Sprintf("%s-kubeapi-%d-%s", clusterResourceName, port, machineName)
1107+
10951108
member := pools.Member{
1096-
Name: fmt.Sprintf("%s-kubeapi-%d-%s", clusterResourceName, port, machineName),
1109+
Name: poolMemberName,
10971110
Address: wrongMemberIP,
10981111
ID: memberID,
10991112
}
@@ -1107,8 +1120,15 @@ func Test_ReconcileLoadBalancerMember(t *testing.T) {
11071120
).DoAndReturn(func(_ string, got pools.CreateMemberOpts) (*pools.Member, error) {
11081121
// SubnetID must be empty here
11091122
g.Expect(got.SubnetID).To(Equal(""))
1110-
return &pools.Member{ID: "member-2"}, nil
1123+
return &pools.Member{ID: memberID}, nil
11111124
})
1125+
1126+
activeMember := pools.Member{
1127+
ID: memberID,
1128+
Name: poolMemberName,
1129+
ProvisioningStatus: "ACTIVE",
1130+
}
1131+
m.GetPoolMember(poolID, memberID).Return(&activeMember, nil).AnyTimes()
11121132
},
11131133
wantError: nil,
11141134
},
@@ -1133,8 +1153,8 @@ func Test_ReconcileLoadBalancerMember(t *testing.T) {
11331153
}
11341154
m.ListPools(pools.ListOpts{Name: pool.Name}).Return([]pools.Pool{pool}, nil)
11351155

1136-
memberName := fmt.Sprintf("%s-kubeapi-%d-%s", clusterResourceName, port, machineName)
1137-
m.ListPoolMember(poolID, pools.ListMembersOpts{Name: memberName}).Return([]pools.Member{}, nil)
1156+
poolMemberName := fmt.Sprintf("%s-kubeapi-%d-%s", clusterResourceName, port, machineName)
1157+
m.ListPoolMember(poolID, pools.ListMembersOpts{Name: poolMemberName}).Return([]pools.Member{}, nil)
11381158

11391159
// Expect CreatePoolMember; capture opts to assert SubnetID is set
11401160
m.CreatePoolMember(
@@ -1148,8 +1168,15 @@ func Test_ReconcileLoadBalancerMember(t *testing.T) {
11481168
g.Expect(got.SubnetID).To(Equal(subnetID))
11491169
// Tags should pass through
11501170
g.Expect(got.Tags).To(ConsistOf("k8s", "clusterapi"))
1151-
return &pools.Member{ID: "member-1", Address: memberIP, ProtocolPort: port}, nil
1171+
return &pools.Member{ID: memberID, Address: memberIP, ProtocolPort: port}, nil
11521172
})
1173+
1174+
activeMember := pools.Member{
1175+
ID: memberID,
1176+
Name: poolMemberName,
1177+
ProvisioningStatus: "ACTIVE",
1178+
}
1179+
m.GetPoolMember(poolID, memberID).Return(&activeMember, nil).AnyTimes()
11531180
},
11541181
wantError: nil,
11551182
},

0 commit comments

Comments
 (0)