Skip to content

Commit 648ea6b

Browse files
author
Joshua Reed
committed
Not great, but iso net is working.
1 parent 435b863 commit 648ea6b

File tree

6 files changed

+116
-67
lines changed

6 files changed

+116
-67
lines changed

controllers/cloudstackcluster_controller.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,7 @@ func (r *CloudStackClusterReconciler) Reconcile(ctx context.Context, req ctrl.Re
100100
}
101101
defer func() {
102102
if err = patchHelper.Patch(ctx, csCluster); err != nil {
103-
msg := "error patching CloudStackCluster %s/%s"
104-
err = errors.Wrapf(err, msg, csCluster.Namespace, csCluster.Name)
103+
err = errors.Wrapf(err, "error patching CloudStackCluster %s/%s", csCluster.Namespace, csCluster.Name)
105104
retErr = multierror.Append(retErr, err)
106105
}
107106
}()
@@ -126,6 +125,9 @@ func (r *CloudStackClusterReconciler) reconcile(
126125

127126
// Prevent premature deletion of the csCluster construct from CAPI.
128127
controllerutil.AddFinalizer(csCluster, infrav1.ClusterFinalizer)
128+
// Set ready status so that a partial reconcile can be patched.
129+
// Ready is required, and patching will fail otherwise.
130+
csCluster.Status.Ready = false
129131

130132
// Create and or fetch cluster components.
131133
err := r.CS.GetOrCreateCluster(csCluster)

controllers/cloudstackmachine_controller.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ func (r *CloudStackMachineReconciler) reconcile(
199199
}
200200

201201
// Check status of machine.
202+
csMachine.Status.Ready = false
202203
if csMachine.Status.InstanceState == "Running" {
203204
log.Info("Machine instance is Running...")
204205
csMachine.Status.Ready = true

pkg/cloud/cluster.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ import (
2626
type ClusterIface interface {
2727
GetOrCreateCluster(*infrav1.CloudStackCluster) error
2828
DisposeClusterResources(cluster *infrav1.CloudStackCluster) error
29+
ResolveZones(*infrav1.CloudStackCluster) error
2930
}
3031

31-
func (c *client) resolveZones(csCluster *infrav1.CloudStackCluster) (retErr error) {
32+
func (c *client) ResolveZones(csCluster *infrav1.CloudStackCluster) (retErr error) {
3233
for _, specZone := range csCluster.Spec.Zones {
3334
if zoneID, count, err := c.cs.Zone.GetZoneID(specZone.Name); err != nil {
3435
retErr = multierror.Append(retErr, errors.Wrapf(err, "could not get Zone ID from %s", specZone))
@@ -57,14 +58,13 @@ func (c *client) GetOrCreateCluster(csCluster *infrav1.CloudStackCluster) (retEr
5758
if csCluster.Status.Zones == nil {
5859
csCluster.Status.Zones = make(map[string]infrav1.Zone)
5960
}
60-
if retErr = c.resolveZones(csCluster); retErr != nil {
61+
if retErr = c.ResolveZones(csCluster); retErr != nil {
6162
return errors.Wrapf(retErr, "error resolving Zone details for Cluster %s", csCluster.Name)
6263
}
6364

6465
csCluster.Status.FailureDomains = capiv1.FailureDomains{}
6566
for _, zone := range csCluster.Status.Zones {
6667
csCluster.Status.FailureDomains[zone.ID] = capiv1.FailureDomainSpec{ControlPlane: true}
67-
csCluster.Status.FailureDomains[zone.ID+"_workers"] = capiv1.FailureDomainSpec{ControlPlane: false}
6868
}
6969

7070
// If provided, translate Domain name to Domain ID.
@@ -85,14 +85,10 @@ func (c *client) GetOrCreateCluster(csCluster *infrav1.CloudStackCluster) (retEr
8585
return retErr
8686
}
8787

88-
if usesIsolatedNetwork(csCluster) {
88+
if UsesIsolatedNetwork(csCluster) {
8989
return c.GetOrCreateIsolatedNetwork(csCluster)
9090
}
9191

92-
// TODO: Make this tag all networks as in use. Didn't make sense in resolveNetworks.
93-
// if err := c.AddClusterTag(ResourceTypeNetwork, zoneStatus.Network.ID, csCluster, doNotAddCreatedByTag); err != nil {
94-
// }
95-
9692
return nil
9793
}
9894

pkg/cloud/instance.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ func (c *client) GetOrCreateVMInstance(
192192

193193
// If this VM instance is a control plane, consider setting its IP.
194194
_, isControlPlanceMachine := capiMachine.ObjectMeta.Labels["cluster.x-k8s.io/control-plane"]
195-
if isControlPlanceMachine && zone.Network.Type == NetworkTypeIsolated {
195+
if isControlPlanceMachine && zone.Network.Type == NetworkTypeShared {
196196
// If the specified control plane endpoint is an IP address, specify the IP address of this VM instance.
197197
if net.ParseIP(csCluster.Spec.ControlPlaneEndpoint.Host) != nil {
198198
p.SetIpaddress(csCluster.Spec.ControlPlaneEndpoint.Host)

pkg/cloud/network.go

Lines changed: 49 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,21 @@ import (
2121
"strings"
2222

2323
"github.com/apache/cloudstack-go/v2/cloudstack"
24-
infrav1 "github.com/aws/cluster-api-provider-cloudstack/api/v1beta1"
24+
capcv1 "github.com/aws/cluster-api-provider-cloudstack/api/v1beta1"
2525
"github.com/hashicorp/go-multierror"
2626
"github.com/pkg/errors"
2727
)
2828

2929
type NetworkIface interface {
30-
ResolveNetworkStatuses(*infrav1.CloudStackCluster) error
31-
ResolveNetwork(*infrav1.CloudStackCluster, *infrav1.Network) error
32-
CreateIsolatedNetwork(*infrav1.CloudStackCluster) error
33-
OpenFirewallRules(*infrav1.CloudStackCluster) error
34-
ResolvePublicIPDetails(*infrav1.CloudStackCluster) (*cloudstack.PublicIpAddress, error)
35-
ResolveLoadBalancerRuleDetails(*infrav1.CloudStackCluster) error
36-
GetOrCreateLoadBalancerRule(*infrav1.CloudStackCluster) error
37-
GetOrCreateIsolatedNetwork(*infrav1.CloudStackCluster) error
38-
AssociatePublicIPAddress(*infrav1.CloudStackCluster) error
30+
ResolveNetworkStatuses(*capcv1.CloudStackCluster) error
31+
ResolveNetwork(*capcv1.CloudStackCluster, *capcv1.Network) error
32+
CreateIsolatedNetwork(*capcv1.CloudStackCluster) error
33+
OpenFirewallRules(*capcv1.CloudStackCluster) error
34+
ResolvePublicIPDetails(*capcv1.CloudStackCluster) (*cloudstack.PublicIpAddress, error)
35+
ResolveLoadBalancerRuleDetails(*capcv1.CloudStackCluster) error
36+
GetOrCreateLoadBalancerRule(*capcv1.CloudStackCluster) error
37+
GetOrCreateIsolatedNetwork(*capcv1.CloudStackCluster) error
38+
AssociatePublicIPAddress(*capcv1.CloudStackCluster) error
3939
}
4040

4141
const (
@@ -48,12 +48,10 @@ const (
4848

4949
// usesIsolatedNetwork returns true if this cluster is specs an isolated network.
5050
// Assumes that the a fetch has been done on network statuses prior.
51-
func usesIsolatedNetwork(csCluster *infrav1.CloudStackCluster) bool {
51+
func UsesIsolatedNetwork(csCluster *capcv1.CloudStackCluster) bool {
5252
// Check for Isolated network use case.
53-
if len(csCluster.Spec.Zones) == 1 { // Where the only specced network
54-
zoneStatus := infrav1.Zone{}
55-
for _, zoneStatus = range csCluster.Status.Zones {
56-
}
53+
if len(csCluster.Status.Zones) == 1 { // Where the only specced network
54+
zoneStatus := csCluster.Status.Zones.GetOne()
5755
if zoneStatus.Network.Type == "" || // doesn't exist or
5856
zoneStatus.Network.Type == NetworkTypeIsolated { // exists and is an isolated network.
5957
return true
@@ -62,17 +60,19 @@ func usesIsolatedNetwork(csCluster *infrav1.CloudStackCluster) bool {
6260
return false
6361
}
6462

65-
// networkExists checks that the network already exists based on the presence of all fields.
63+
// NetworkExists checks that the network already exists based on the presence of all fields.
6664
// Assumes that the a fetch has been done on network statuses prior.
67-
func networkExists(net infrav1.Network) bool {
65+
func NetworkExists(net capcv1.Network) bool {
6866
if net.Name != "" && net.Type != "" && net.ID != "" {
6967
return true
7068
}
7169
return false
7270
}
7371

7472
// ResolveNetwork fetches networks' ID, Name, and Type.
75-
func (c *client) ResolveNetwork(csCluster *infrav1.CloudStackCluster, net *infrav1.Network) (retErr error) {
73+
func (c *client) ResolveNetwork(csCluster *capcv1.CloudStackCluster, net *capcv1.Network) (retErr error) {
74+
// TODO rebuild this to consider cases with networks in many zones.
75+
// Use ListNetworks instead.
7676
netName := net.Name
7777
netDetails, count, err := c.cs.Network.GetNetworkByName(netName)
7878
if err != nil {
@@ -89,19 +89,17 @@ func (c *client) ResolveNetwork(csCluster *infrav1.CloudStackCluster, net *infra
8989
// Now get network details.
9090
netDetails, count, err = c.cs.Network.GetNetworkByID(net.ID)
9191
if err != nil {
92-
return multierror.Append(retErr, errors.Wrapf(
93-
err, "could not get Network by ID %s", net.ID))
92+
return multierror.Append(retErr, errors.Wrapf(err, "could not get Network by ID %s", net.ID))
9493
} else if count != 1 {
95-
return multierror.Append(retErr, errors.Errorf(
96-
"expected 1 Network with UUID %s, but got %d", net.ID, count))
94+
return multierror.Append(retErr, errors.Errorf("expected 1 Network with UUID %s, but got %d", net.ID, count))
9795
}
9896
net.Name = netDetails.Name
9997
net.ID = netDetails.Id
10098
net.Type = netDetails.Type
10199
return nil
102100
}
103101

104-
func generateNetworkTagName(csCluster *infrav1.CloudStackCluster) string {
102+
func generateNetworkTagName(csCluster *capcv1.CloudStackCluster) string {
105103
return clusterTagNamePrefix + string(csCluster.UID)
106104
}
107105

@@ -118,8 +116,8 @@ func (c *client) getOfferingID() (string, error) {
118116

119117
// CreateIsolatedNetwork creates an isolated network in the relevant Zone.
120118
// Assumes that there is only the one zone in the cluster.
121-
func (c *client) CreateIsolatedNetwork(csCluster *infrav1.CloudStackCluster) (retErr error) {
122-
zoneStatus := csCluster.Status.Zones[csCluster.Spec.Zones[0].Network.Name]
119+
func (c *client) CreateIsolatedNetwork(csCluster *capcv1.CloudStackCluster) (retErr error) {
120+
zoneStatus := *csCluster.Status.Zones.GetOne() // Should only be the one...
123121
netStatus := zoneStatus.Network
124122

125123
// Fetch offering ID.
@@ -153,12 +151,7 @@ func (c *client) CreateIsolatedNetwork(csCluster *infrav1.CloudStackCluster) (re
153151
}
154152

155153
// ResolveNetworkStatuses fetches details on all networks specced, but will not modify ACS settings.
156-
func (c *client) ResolveNetworkStatuses(csCluster *infrav1.CloudStackCluster) (retErr error) {
157-
// Copy network spec to status in preparation for network resolution or creation.
158-
for _, specZone := range csCluster.Spec.Zones {
159-
csCluster.Status.Zones[specZone.ID] = specZone
160-
}
161-
154+
func (c *client) ResolveNetworkStatuses(csCluster *capcv1.CloudStackCluster) (retErr error) {
162155
// At this point network status should have been populated (copied) from the spec.
163156
for _, zoneStatus := range csCluster.Status.Zones {
164157
if retErr = c.ResolveNetwork(csCluster, &zoneStatus.Network); retErr == nil { // Found network
@@ -171,13 +164,12 @@ func (c *client) ResolveNetworkStatuses(csCluster *infrav1.CloudStackCluster) (r
171164
return nil
172165
}
173166

174-
func (c *client) RemoveClusterTagFromNetwork(csCluster *infrav1.CloudStackCluster, net infrav1.Network) (retError error) {
167+
func (c *client) RemoveClusterTagFromNetwork(csCluster *capcv1.CloudStackCluster, net capcv1.Network) (retError error) {
175168

176169
tags, err := c.GetTags(ResourceTypeNetwork, net.ID)
177170
if err != nil {
178171
return err
179172
}
180-
// sourceNAT := publicIP != nil && publicIP.Issourcenat
181173

182174
clusterTagName := generateNetworkTagName(csCluster)
183175
if tagValue := tags[clusterTagName]; tagValue != "" {
@@ -189,7 +181,7 @@ func (c *client) RemoveClusterTagFromNetwork(csCluster *infrav1.CloudStackCluste
189181
return nil
190182
}
191183

192-
func (c *client) DeleteNetworkIfNotInUse(csCluster *infrav1.CloudStackCluster, net infrav1.Network) (retError error) {
184+
func (c *client) DeleteNetworkIfNotInUse(csCluster *capcv1.CloudStackCluster, net capcv1.Network) (retError error) {
193185
tags, err := c.GetTags(ResourceTypeNetwork, net.ID)
194186
if err != nil {
195187
return err
@@ -209,11 +201,14 @@ func (c *client) DeleteNetworkIfNotInUse(csCluster *infrav1.CloudStackCluster, n
209201
return nil
210202
}
211203

212-
func (c *client) ResolvePublicIPDetails(csCluster *infrav1.CloudStackCluster) (*cloudstack.PublicIpAddress, error) {
204+
func (c *client) ResolvePublicIPDetails(csCluster *capcv1.CloudStackCluster) (*cloudstack.PublicIpAddress, error) {
213205
ip := csCluster.Spec.ControlPlaneEndpoint.Host
214206

207+
zoneStatus := csCluster.Status.Zones.GetOne()
208+
215209
p := c.cs.Address.NewListPublicIpAddressesParams()
216210
p.SetAllocatedonly(false)
211+
p.SetZoneid(zoneStatus.ID)
217212
setIfNotEmpty(csCluster.Spec.Account, p.SetAccount)
218213
setIfNotEmpty(csCluster.Status.DomainID, p.SetDomainid)
219214
if ip != "" {
@@ -238,7 +233,7 @@ func (c *client) ResolvePublicIPDetails(csCluster *infrav1.CloudStackCluster) (*
238233
}
239234

240235
// AssociatePublicIPAddress Gets a PublicIP and associates it.
241-
func (c *client) AssociatePublicIPAddress(csCluster *infrav1.CloudStackCluster) (retErr error) {
236+
func (c *client) AssociatePublicIPAddress(csCluster *capcv1.CloudStackCluster) (retErr error) {
242237
publicAddress, err := c.ResolvePublicIPDetails(csCluster)
243238
if err != nil {
244239
return err
@@ -247,24 +242,24 @@ func (c *client) AssociatePublicIPAddress(csCluster *infrav1.CloudStackCluster)
247242
csCluster.Spec.ControlPlaneEndpoint.Host = publicAddress.Ipaddress
248243
csCluster.Status.PublicIPID = publicAddress.Id
249244

250-
if publicAddress.Allocated != "" { // Address already allocated. Allocated is a timestamp -- not a boolean.
251-
return c.AddClusterTag(ResourceTypeIPAddress, publicAddress.Id, csCluster)
252-
} // Address not yet allocated. Allocate now.
245+
zoneStatus := csCluster.Status.Zones.GetOne()
253246

254247
// Public IP found, but not yet allocated to network.
255248
p := c.cs.Address.NewAssociateIpAddressParams()
256249
p.SetIpaddress(csCluster.Spec.ControlPlaneEndpoint.Host)
250+
p.SetNetworkid(zoneStatus.Network.ID)
257251
setIfNotEmpty(csCluster.Spec.Account, p.SetAccount)
258252
setIfNotEmpty(csCluster.Status.DomainID, p.SetDomainid)
259-
resp, err := c.cs.Address.AssociateIpAddress(p)
260-
if err != nil {
253+
if _, err := c.cs.Address.AssociateIpAddress(p); err != nil {
254+
return err
255+
}
256+
if err := c.AddClusterTag(ResourceTypeIPAddress, publicAddress.Id, csCluster); err != nil {
261257
return err
262258
}
263-
csCluster.Status.PublicIPNetworkID = resp.Networkid
264259
return nil
265260
}
266261

267-
func (c *client) OpenFirewallRules(csCluster *infrav1.CloudStackCluster) (retErr error) {
262+
func (c *client) OpenFirewallRules(csCluster *capcv1.CloudStackCluster) (retErr error) {
268263
p := c.cs.Firewall.NewCreateEgressFirewallRuleParams(csCluster.Status.PublicIPNetworkID, NetworkProtocolTCP)
269264
_, retErr = c.cs.Firewall.CreateEgressFirewallRule(p)
270265
if retErr != nil && strings.Contains(strings.ToLower(retErr.Error()), "there is already") { // Already a firewall rule here.
@@ -273,7 +268,7 @@ func (c *client) OpenFirewallRules(csCluster *infrav1.CloudStackCluster) (retErr
273268
return retErr
274269
}
275270

276-
func (c *client) DisassociatePublicIPAddress(csCluster *infrav1.CloudStackCluster) (retErr error) {
271+
func (c *client) DisassociatePublicIPAddress(csCluster *capcv1.CloudStackCluster) (retErr error) {
277272
// Remove the CAPC creation tag, so it won't be there the next time this address is associated.
278273
retErr = c.DeleteCreatedByCAPCTag(ResourceTypeIPAddress, csCluster.Status.PublicIPID)
279274
if retErr != nil {
@@ -285,7 +280,7 @@ func (c *client) DisassociatePublicIPAddress(csCluster *infrav1.CloudStackCluste
285280
return retErr
286281
}
287282

288-
func (c *client) DisassociatePublicIPAddressIfNotInUse(csCluster *infrav1.CloudStackCluster) (retError error) {
283+
func (c *client) DisassociatePublicIPAddressIfNotInUse(csCluster *capcv1.CloudStackCluster) (retError error) {
289284
tagsAllowDisposal, err := c.DoClusterTagsAllowDisposal(ResourceTypeIPAddress, csCluster.Status.PublicIPID)
290285
if err != nil {
291286
return err
@@ -305,7 +300,7 @@ func (c *client) DisassociatePublicIPAddressIfNotInUse(csCluster *infrav1.CloudS
305300
return nil
306301
}
307302

308-
func (c *client) ResolveLoadBalancerRuleDetails(csCluster *infrav1.CloudStackCluster) (retErr error) {
303+
func (c *client) ResolveLoadBalancerRuleDetails(csCluster *capcv1.CloudStackCluster) (retErr error) {
309304
p := c.cs.LoadBalancer.NewListLoadBalancerRulesParams()
310305
p.SetPublicipid(csCluster.Status.PublicIPID)
311306
setIfNotEmpty(csCluster.Spec.Account, p.SetAccount)
@@ -324,7 +319,7 @@ func (c *client) ResolveLoadBalancerRuleDetails(csCluster *infrav1.CloudStackClu
324319
}
325320

326321
// GetOrCreateLoadBalancerRule Create a load balancer rule that can be assigned to instances.
327-
func (c *client) GetOrCreateLoadBalancerRule(csCluster *infrav1.CloudStackCluster) (retErr error) {
322+
func (c *client) GetOrCreateLoadBalancerRule(csCluster *capcv1.CloudStackCluster) (retErr error) {
328323
// Check if rule exists.
329324
if err := c.ResolveLoadBalancerRuleDetails(csCluster); err == nil ||
330325
!strings.Contains(strings.ToLower(err.Error()), "no load balancer rule found") {
@@ -333,7 +328,8 @@ func (c *client) GetOrCreateLoadBalancerRule(csCluster *infrav1.CloudStackCluste
333328

334329
p := c.cs.LoadBalancer.NewCreateLoadBalancerRuleParams(
335330
"roundrobin", "Kubernetes_API_Server", K8sDefaultAPIPort, K8sDefaultAPIPort)
336-
p.SetNetworkid(csCluster.Status.PublicIPNetworkID)
331+
332+
p.SetNetworkid(csCluster.Status.Zones.GetOne().Network.ID)
337333
if csCluster.Spec.ControlPlaneEndpoint.Port != 0 { // Override default public port if endpoint port specified.
338334
p.SetPublicport(int(csCluster.Spec.ControlPlaneEndpoint.Port))
339335
}
@@ -349,12 +345,12 @@ func (c *client) GetOrCreateLoadBalancerRule(csCluster *infrav1.CloudStackCluste
349345
return nil
350346
}
351347

352-
func (c *client) DestroyNetwork(net infrav1.Network) (retErr error) {
348+
func (c *client) DestroyNetwork(net capcv1.Network) (retErr error) {
353349
_, retErr = c.cs.Network.DeleteNetwork(c.cs.Network.NewDeleteNetworkParams(net.ID))
354350
return retErr
355351
}
356352

357-
func (c *client) AssignVMToLoadBalancerRule(csCluster *infrav1.CloudStackCluster, instanceID string) (retErr error) {
353+
func (c *client) AssignVMToLoadBalancerRule(csCluster *capcv1.CloudStackCluster, instanceID string) (retErr error) {
358354

359355
// Check that the instance isn't already in LB rotation.
360356
lbRuleInstances, retErr := c.cs.LoadBalancer.ListLoadBalancerRuleInstances(
@@ -376,9 +372,9 @@ func (c *client) AssignVMToLoadBalancerRule(csCluster *infrav1.CloudStackCluster
376372
}
377373

378374
// GetOrCreateIsolatedNetwork fetches or builds out the necessary structures for isolated network use.
379-
func (c *client) GetOrCreateIsolatedNetwork(csCluster *infrav1.CloudStackCluster) error {
380-
onlyNetStatus := csCluster.Status.Zones[csCluster.Spec.Zones[0].Network.Name].Network
381-
if !networkExists(onlyNetStatus) { // create isolated network.
375+
func (c *client) GetOrCreateIsolatedNetwork(csCluster *capcv1.CloudStackCluster) error {
376+
onlyNetStatus := csCluster.Status.Zones.GetOne().Network
377+
if !NetworkExists(onlyNetStatus) { // create isolated network.
382378
if err := c.CreateIsolatedNetwork(csCluster); err != nil {
383379
return err
384380
}

0 commit comments

Comments
 (0)