Skip to content

Commit e46f038

Browse files
author
Joshua Reed
committed
Isolate the isolated network use case.
1 parent fe5af44 commit e46f038

File tree

5 files changed

+92
-57
lines changed

5 files changed

+92
-57
lines changed

controllers/cloudstackcluster_controller.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,17 +122,21 @@ func (r *CloudStackClusterReconciler) reconcile(
122122
csCluster *infrav1.CloudStackCluster,
123123
) (ctrl.Result, error) {
124124

125-
log.V(1).Info("reconcile CloudStackCluster")
125+
log.V(1).Info("Reconciling CloudStackCluster.", "clusterSpec", csCluster.Spec)
126126

127127
// Prevent premature deletion of the csCluster construct from CAPI.
128128
controllerutil.AddFinalizer(csCluster, infrav1.ClusterFinalizer)
129129

130-
// Create and or fetch cluster components -- sets cluster to ready if no errors.
130+
// Create and or fetch cluster components.
131131
err := r.CS.GetOrCreateCluster(csCluster)
132132
if err == nil {
133-
log.Info("Fetched cluster info successfully.", "clusterSpec", csCluster.Spec,
134-
"clusterStatus", csCluster.Status)
133+
log.Info("Fetched cluster info successfully.")
134+
log.V(1).Info("Post fetch cluster status.", "clusterStatus", csCluster.Status)
135+
136+
// Set cluster to ready to indicate readiness to CAPI.
137+
csCluster.Status.Ready = true
135138
}
139+
136140
return ctrl.Result{}, err
137141
}
138142

controllers/cloudstackmachine_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ func (r *CloudStackMachineReconciler) reconcile(
204204

205205
if len(csCluster.Spec.Zones) == 1 {
206206
for _, zone := range csCluster.Status.Zones { // Ugly way to get the only Zone.
207-
if util.IsControlPlaneMachine(capiMachine) && zone.Network.Type != cloud.NetworkTypeShared {
207+
if util.IsControlPlaneMachine(capiMachine) && zone.Network.Type == cloud.NetworkTypeIsolated {
208208
log.Info("Assigning VM to load balancer rule.")
209209
err := r.CS.AssignVMToLoadBalancerRule(csCluster, *csMachine.Spec.InstanceID)
210210
if err != nil {

pkg/cloud/client.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"strings"
2121

2222
"github.com/apache/cloudstack-go/v2/cloudstack"
23-
infrav1 "github.com/aws/cluster-api-provider-cloudstack/api/v1beta1"
2423
"github.com/pkg/errors"
2524
"gopkg.in/ini.v1"
2625
)
@@ -30,13 +29,9 @@ import (
3029
type Client interface {
3130
ClusterIface
3231
VMIface
33-
GetOrCreateNetworks(*infrav1.CloudStackCluster) error
34-
OpenFirewallRules(*infrav1.CloudStackCluster) error
35-
ResolvePublicIPDetails(*infrav1.CloudStackCluster) (*cloudstack.PublicIpAddress, error)
36-
ResolveLoadBalancerRuleDetails(*infrav1.CloudStackCluster) error
37-
GetOrCreateLoadBalancerRule(*infrav1.CloudStackCluster) error
38-
AffinityGroupIface
39-
TagIface
32+
NetworkIface
33+
AffinityGroupIFace
34+
TagIFace
4035
}
4136

4237
type client struct {

pkg/cloud/cluster.go

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -75,31 +75,27 @@ func (c *client) GetOrCreateCluster(csCluster *infrav1.CloudStackCluster) (retEr
7575
}
7676
}
7777

78-
// Get or create network and needed network constructs.
79-
if retErr = c.GetOrCreateNetworks(csCluster); retErr != nil {
78+
// Get current network statuses.
79+
// CAPC only modifies networks in the single isolated network case.
80+
if retErr = c.ResolveNetworkStatuses(csCluster); retErr != nil {
8081
return retErr
8182
}
8283

83-
if len(csCluster.Spec.Zones) > 1 { // Ignore isolated network use case if spec indicates multiple zones.
84-
for _, zone := range csCluster.Status.Zones { // Get the only zone from the status zone map.
85-
if zone.Network.Type == NetworkTypeIsolated {
86-
if retErr = c.OpenFirewallRules(csCluster); retErr != nil {
87-
return retErr
88-
}
89-
if csCluster.Status.PublicIPID == "" { // Don't try to get public IP again it's already been fetched.
90-
if retErr = c.AssociatePublicIpAddress(csCluster); retErr != nil {
91-
return retErr
92-
}
93-
}
94-
if retErr = c.GetOrCreateLoadBalancerRule(csCluster); retErr != nil {
95-
return retErr
96-
}
84+
if usesIsolatedNetwork(csCluster) {
85+
onlyNetStatus := csCluster.Status.Zones[csCluster.Spec.Zones[0].Network.Name].Network
86+
if !networkExists(onlyNetStatus) { // create isolated network.
87+
88+
}
89+
90+
if csCluster.Status.PublicIPID == "" { // Don't try to get public IP again it's already been fetched.
91+
if retErr = c.AssociatePublicIpAddress(csCluster); retErr != nil {
92+
return retErr
9793
}
9894
}
95+
if retErr = c.GetOrCreateLoadBalancerRule(csCluster); retErr != nil {
96+
return retErr
97+
}
9998
}
100-
101-
// Set cluster to ready to indicate readiness to CAPI.
102-
csCluster.Status.Ready = true
10399
return nil
104100
}
105101

pkg/cloud/network.go

Lines changed: 65 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ import (
2626
"github.com/pkg/errors"
2727
)
2828

29+
type NetworkIface interface {
30+
ResolveNetworkStatuses(*infrav1.CloudStackCluster) error
31+
CreateIsolatedNewtork(*infrav1.CloudStackCluster) error
32+
OpenFirewallRules(*infrav1.CloudStackCluster) error
33+
ResolvePublicIPDetails(*infrav1.CloudStackCluster) (*cloudstack.PublicIpAddress, error)
34+
ResolveLoadBalancerRuleDetails(*infrav1.CloudStackCluster) error
35+
GetOrCreateLoadBalancerRule(*infrav1.CloudStackCluster) error
36+
}
37+
2938
const (
3039
NetOffering = "DefaultIsolatedNetworkOfferingWithSourceNatService"
3140
K8sDefaultAPIPort = 6443
@@ -36,6 +45,29 @@ const (
3645
doNotAddCreatedByTag = false
3746
)
3847

48+
// usesIsolatedNetwork returns true if this cluster is specs an isolated network.
49+
// Assumes that the a fetch has been done on network statuses prior.
50+
func usesIsolatedNetwork(csCluster *infrav1.CloudStackCluster) bool {
51+
firstNetStatus := csCluster.Status.Zones[csCluster.Spec.Zones[0].Network.Name].Network
52+
// Check for Isolated network use case.
53+
if len(csCluster.Spec.Zones) == 1 { // Where the only specced network
54+
if firstNetStatus.Type == "" || // doesn't exist or
55+
firstNetStatus.Type == NetworkTypeIsolated { // exists and is an isolated network.
56+
return true
57+
}
58+
}
59+
return false
60+
}
61+
62+
// networkExists checks that the network already exists based on the presence of all fields.
63+
// Assumes that the a fetch has been done on network statuses prior.
64+
func networkExists(net infrav1.Network) bool {
65+
if net.Name != "" && net.Type != "" && net.Id != "" {
66+
return true
67+
}
68+
return false
69+
}
70+
3971
// ResolveNetworks fetches networks' Id, Name, and Type.
4072
func (c *client) ResolveNetwork(csCluster *infrav1.CloudStackCluster, net *infrav1.Network) (retErr error) {
4173
netName := net.Name
@@ -79,8 +111,39 @@ func (c *client) getOfferingId() (string, error) {
79111
return offeringId, nil
80112
}
81113

82-
// GetOrCreateNetworks fetches the details of or creates networks per specs.
83-
func (c *client) GetOrCreateNetworks(csCluster *infrav1.CloudStackCluster) (retErr error) {
114+
// CreateIsolatedNewtork creates an isolated network in the relevant Zone.
115+
// Assumes that there is only the one zone in the cluster.
116+
func (c *client) CreateIsolatedNewtork(csCluster *infrav1.CloudStackCluster) (retErr error) {
117+
zoneStatus := csCluster.Status.Zones[csCluster.Spec.Zones[0].Network.Name]
118+
netStatus := zoneStatus.Network
119+
120+
// Fetch offering Id.
121+
offeringId, err := c.getOfferingId()
122+
if err != nil {
123+
return err
124+
}
125+
126+
// Do creation.
127+
p := c.cs.Network.NewCreateNetworkParams(netStatus.Name, netStatus.Name, offeringId, zoneStatus.Id)
128+
setIfNotEmpty(csCluster.Spec.Account, p.SetAccount)
129+
setIfNotEmpty(csCluster.Status.DomainID, p.SetDomainid)
130+
resp, err := c.cs.Network.CreateNetwork(p)
131+
if err != nil {
132+
return err
133+
}
134+
c.addClusterTags(csCluster, zoneStatus.Network, addCreatedByTag)
135+
136+
// Update Zone/Network status accordingly.
137+
netStatus.Id = resp.Id
138+
netStatus.Type = resp.Type
139+
zoneStatus.Network = netStatus
140+
csCluster.Status.Zones[zoneStatus.Name] = zoneStatus
141+
142+
return nil
143+
}
144+
145+
// ResolveNetworkStatuses fetches details on all networks specced, but will not modify ACS settings.
146+
func (c *client) ResolveNetworkStatuses(csCluster *infrav1.CloudStackCluster) (retErr error) {
84147
// Copy network spec to status in preparation for network resolution or creation.
85148
for _, specZone := range csCluster.Spec.Zones {
86149
zone, ok := csCluster.Status.Zones[specZone.Name]
@@ -93,35 +156,12 @@ func (c *client) GetOrCreateNetworks(csCluster *infrav1.CloudStackCluster) (retE
93156

94157
// At this point network status should have been populated (copied) from the spec.
95158
for _, zoneStatus := range csCluster.Status.Zones {
96-
netStatus := zoneStatus.Network
97159
if retErr = c.ResolveNetwork(csCluster, &zoneStatus.Network); retErr == nil { // Found network
98160
c.addClusterTags(csCluster, zoneStatus.Network, doNotAddCreatedByTag)
99161
continue
100162
} else if !strings.Contains(retErr.Error(), "No match found") { // Some other error.
101163
return retErr
102164
} // Network not found, so create it.
103-
104-
// Fetch offering Id.
105-
offeringId, err := c.getOfferingId()
106-
if err != nil {
107-
return err
108-
}
109-
110-
// Do creation
111-
p := c.cs.Network.NewCreateNetworkParams(netStatus.Name, netStatus.Name, offeringId, zoneStatus.Id)
112-
setIfNotEmpty(csCluster.Spec.Account, p.SetAccount)
113-
setIfNotEmpty(csCluster.Status.DomainID, p.SetDomainid)
114-
resp, err := c.cs.Network.CreateNetwork(p)
115-
if err != nil {
116-
return err
117-
}
118-
c.addClusterTags(csCluster, zoneStatus.Network, addCreatedByTag)
119-
120-
// Update Zone/Network status accordingly.
121-
netStatus.Id = resp.Id
122-
netStatus.Type = resp.Type
123-
zoneStatus.Network = netStatus
124-
csCluster.Status.Zones[zoneStatus.Name] = zoneStatus
125165
}
126166

127167
return nil

0 commit comments

Comments
 (0)