Skip to content

Commit

Permalink
Merge pull request #43 from GDATASoftwareAG/configure-failover-groups
Browse files Browse the repository at this point in the history
configure failover groups
  • Loading branch information
farodin91 authored Nov 21, 2023
2 parents 469179c + ebf3e38 commit df34d2b
Show file tree
Hide file tree
Showing 12 changed files with 201 additions and 5 deletions.
9 changes: 8 additions & 1 deletion api/v1alpha1/ionoscloudcluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,15 @@ type IONOSLanSpec struct {
LanID *int32 `json:"lanID,omitempty"` //validate?
Name string `json:"name"` //validate?
Public bool `json:"public"`
// +listType=map
// +listMapKey=id
FailoverGroups []IONOSFailoverGroup `json:"failoverGroups,omitempty"`
//NameTemplate string `json:"nameTemplate"`
//FailoverIPs []string `json:"failoverIPs,omitempty"`
}

type IONOSFailoverGroup struct {
ID string `json:"id"`
// NicUuid string `json:"nicUuid,omitempty"`
}

type IONOSLoadBalancerSpec struct {
Expand Down
20 changes: 20 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ spec:
lans:
items:
properties:
failoverGroups:
items:
properties:
id:
type: string
required:
- id
type: object
type: array
x-kubernetes-list-map-keys:
- id
x-kubernetes-list-type: map
lanID:
format: int32
type: integer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ spec:
lans:
items:
properties:
failoverGroups:
items:
properties:
id:
type: string
required:
- id
type: object
type: array
x-kubernetes-list-map-keys:
- id
x-kubernetes-list-type: map
lanID:
format: int32
type: integer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ spec:
public: true
- name: internet
public: true
failoverGroups:
- id: 3682d039-e520-4837-810c-c43358949463
loadBalancer:
listenerLanRef:
name: public
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ spec:
ram: 4096
cpuFamily: "INTEL_SKYLAKE"
bootVolume:
image: "a9152e16-2482-11ee-9eb0-82cf6aa9b8c3"
image: "3c2a7c7a-8488-11ee-811f-826459b45e91"
type: "HDD"
size: "25"
nics:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ spec:
ram: 2048
cpuFamily: "INTEL_SKYLAKE"
bootVolume:
image: "a9152e16-2482-11ee-9eb0-82cf6aa9b8c3"
image: "3c2a7c7a-8488-11ee-811f-826459b45e91"
type: "HDD"
size: "25"
nics:
Expand Down
2 changes: 1 addition & 1 deletion config/samples/kubeadmcontrolplane.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ spec:
kind: IONOSCloudMachineTemplate
name: ionoscloudcluster-control-plane
replicas: 3
version: "1.25.11"
version: "1.27.6"
2 changes: 1 addition & 1 deletion config/samples/machinedeployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ spec:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: IONOSCloudMachineTemplate
name: ionoscloudcluster-worker
version: "1.25.11"
version: "1.27.6"
65 changes: 65 additions & 0 deletions internal/controller/ionoscloudmachine_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,11 +414,65 @@ func (r *IONOSCloudMachineReconciler) reconcileServer(ctx *context.MachineContex
return &reconcile.Result{RequeueAfter: defaultRetryIntervalOnBusy}, errors.New("server does not have an ip yet")
}

err = r.reconcileFailoverGroups(ctx, server)
if err != nil {
return &reconcile.Result{RequeueAfter: defaultRetryIntervalOnBusy}, err
}

conditions.MarkTrue(ctx.IONOSCloudMachine, v1alpha1.ServerCreatedCondition)

return nil, nil
}

func (r *IONOSCloudMachineReconciler) reconcileFailoverGroups(ctx *context.MachineContext, server ionoscloud.Server) error {
for i := range ctx.IONOSCloudCluster.Spec.Lans {
lanSpec := &ctx.IONOSCloudCluster.Spec.Lans[i]
serverNic := serverNicByLan(server, lanSpec)
if serverNic == nil {
continue
}
for k := range lanSpec.FailoverGroups {
group := &lanSpec.FailoverGroups[k]
ctx.Logger.Info("Reconciling failover group " + group.ID)

block, _, err := ctx.IONOSClient.GetIPBlock(ctx, group.ID)
if err != nil {
return err
}
for _, ip := range *block.Properties.Ips {
err = ctx.IONOSClient.EnsureAdditionalIPOnNic(ctx, ctx.IONOSCloudCluster.Spec.DataCenterID, ctx.IONOSCloudMachine.Spec.ProviderID, *serverNic.Id, ip)
if err != nil {
return err
}
lanId := fmt.Sprint(*lanSpec.LanID)
lan, _, err := ctx.IONOSClient.GetLan(ctx, ctx.IONOSCloudCluster.Spec.DataCenterID, lanId)
if err != nil {
return err
}
registered := false
if lan.Properties.IpFailover != nil {
for _, f := range *lan.Properties.IpFailover {
if *f.Ip == ip {
registered = true
continue
}
}
if registered {
continue
}
}

//todo only once per cluster and change if machine gets delete
err = ctx.IONOSClient.EnsureFailoverIPOnLan(ctx, ctx.IONOSCloudCluster.Spec.DataCenterID, lanId, ip, *serverNic.Id)
if err != nil {
return err
}
}
}
}
return nil
}

func (r *IONOSCloudMachineReconciler) reconcileLoadBalancerForwardingRule(ctx *context.MachineContext) (*reconcile.Result, error) {
ctx.Logger.Info("Reconciling load balancer forwarding rule")

Expand Down Expand Up @@ -494,6 +548,17 @@ func (r *IONOSCloudMachineReconciler) SetupWithManager(mgr ctrl.Manager) error {
Complete(r)
}

func serverNicByLan(server ionoscloud.Server, lan *v1alpha1.IONOSLanSpec) *ionoscloud.Nic {
var serverNic *ionoscloud.Nic
for _, nic := range *server.Entities.Nics.Items {
if *nic.Properties.Lan == *lan.LanID {
serverNic = &nic
break
}
}
return serverNic
}

func findAndDeleteByIP(s []ionoscloud.NetworkLoadBalancerForwardingRuleTarget, item ionoscloud.NetworkLoadBalancerForwardingRuleTarget) []ionoscloud.NetworkLoadBalancerForwardingRuleTarget {
index := 0
for _, i := range s {
Expand Down
64 changes: 64 additions & 0 deletions internal/ionos/apiclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@ type DatacenterAPI interface {
DeleteDatacenter(ctx context.Context, datacenterId string) (*ionoscloud.APIResponse, error)
}

type IPBlockAPI interface {
GetIPBlock(ctx context.Context, id string) (ionoscloud.IpBlock, *ionoscloud.APIResponse, error)
}

type LanAPI interface {
CreateLan(ctx context.Context, datacenterId string, public bool) (ionoscloud.LanPost, *ionoscloud.APIResponse, error)
GetLan(ctx context.Context, datacenterId, lanId string) (ionoscloud.Lan, *ionoscloud.APIResponse, error)
EnsureFailoverIPOnLan(ctx context.Context, datacenterId, lanId, ip, nicUuid string) error
}

type DefaultAPI interface {
Expand All @@ -46,6 +51,7 @@ type ServerAPI interface {
CreateServer(ctx context.Context, datacenterId string, server ionoscloud.Server) (ionoscloud.Server, *ionoscloud.APIResponse, error)
GetServer(ctx context.Context, datacenterId, serverId string) (ionoscloud.Server, *ionoscloud.APIResponse, error)
DeleteServer(ctx context.Context, datacenterId, serverId string) (*ionoscloud.APIResponse, error)
EnsureAdditionalIPOnNic(ctx context.Context, datacenterId, serverId, nic, ip string) error
}

type Client interface {
Expand All @@ -55,6 +61,7 @@ type Client interface {
ServerAPI
DefaultAPI
VolumeAPI
IPBlockAPI
}

func NewAPIClient(username, password, token, host string) Client {
Expand All @@ -78,6 +85,63 @@ type APIClient struct {
client *ionoscloud.APIClient
}

func (c *APIClient) EnsureAdditionalIPOnNic(ctx context.Context, datacenterId, serverId, nicUuid, ip string) error {
serverId = strings.TrimPrefix(serverId, "ionos://")
nic, _, err := c.client.NetworkInterfacesApi.DatacentersServersNicsFindById(ctx, datacenterId, serverId, nicUuid).Execute()
if err != nil {
return err
}
ips := []string{}
if nic.Properties.Ips != nil {
for _, current := range *nic.Properties.Ips {
if current == ip {
return nil
}
}
ips = *nic.Properties.Ips
}
ips = append(ips, ip)
_, _, err = c.client.NetworkInterfacesApi.DatacentersServersNicsPatch(ctx, datacenterId, serverId, nicUuid).Nic(ionoscloud.NicProperties{
Ips: &ips,
}).Execute()
return err
}

func (c *APIClient) EnsureFailoverIPOnLan(ctx context.Context, datacenterId, lanId, ip, nicUuid string) error {
lan, _, err := c.client.LANsApi.DatacentersLansFindById(ctx, datacenterId, lanId).Execute()
if err != nil {
return err
}
failovers := []ionoscloud.IPFailover{}
ignore := false
if lan.Properties.IpFailover != nil {
for _, failover := range *lan.Properties.IpFailover {
if *failover.Ip == ip {
if *failover.NicUuid == nicUuid {
return nil
}
failover.NicUuid = &nicUuid
ignore = true
}
failovers = append(failovers, failover)
}
}
if !ignore {
failovers = append(failovers, ionoscloud.IPFailover{
Ip: &ip,
NicUuid: &nicUuid,
})
}
_, _, err = c.client.LANsApi.DatacentersLansPatch(ctx, datacenterId, lanId).Lan(ionoscloud.LanProperties{
IpFailover: &failovers,
}).Execute()
return err
}

func (c *APIClient) GetIPBlock(ctx context.Context, id string) (ionoscloud.IpBlock, *ionoscloud.APIResponse, error) {
return c.client.IPBlocksApi.IpblocksFindById(ctx, id).Execute()
}

func (c *APIClient) DeleteVolume(ctx context.Context, datacenterId, volumeId string) (*ionoscloud.APIResponse, error) {
return c.client.VolumesApi.DatacentersVolumesDelete(ctx, datacenterId, volumeId).Execute()
}
Expand Down
14 changes: 14 additions & 0 deletions testing/fakeClient.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,20 @@ type FakeClient struct {
CredentialsAreValid bool
}

func (f FakeClient) EnsureFailoverIPOnLan(ctx context.Context, datacenterId, lanId, ip, nicUuid string) error {
//TODO implement me
panic("implement me")
}

func (f FakeClient) EnsureAdditionalIPOnNic(ctx context.Context, datacenterId, serverId, nic, ip string) error {
//TODO implement me
panic("implement me")
}

func (f FakeClient) GetIPBlock(_ context.Context, _ string) (ionoscloud.IpBlock, *ionoscloud.APIResponse, error) {
return ionoscloud.IpBlock{}, nil, nil
}

func (f FakeClient) DeleteServer(_ context.Context, datacenterId, serverId string) (*ionoscloud.APIResponse, error) {
serverId = strings.TrimPrefix(serverId, "ionos://")
var items []ionoscloud.Server
Expand Down

0 comments on commit df34d2b

Please sign in to comment.