Skip to content

Commit 06e21f6

Browse files
committed
initialize ipam
1 parent 1dd9d1f commit 06e21f6

File tree

6 files changed

+209
-5
lines changed

6 files changed

+209
-5
lines changed

apis/ipam/v1alpha1/ip_types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ type IPSpec struct {
6363
type IPStatus struct {
6464
// IPMappings contains the mapping of the local IP for each remote cluster.
6565
IPMappings map[string]networkingv1beta1.IP `json:"ipMappings,omitempty"`
66+
// IP is the remapped IP.
67+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="IP field is immutable"
68+
IP networkingv1beta1.IP `json:"ip"`
69+
// CIDR is the network CIDR where the IP is allocated.
70+
CIDR networkingv1beta1.CIDR `json:"cidr,omitempty"`
6671
}
6772

6873
// +kubebuilder:object:root=true

cmd/ipam/main.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"k8s.io/client-go/tools/record"
3232
"k8s.io/klog/v2"
3333
ctrl "sigs.k8s.io/controller-runtime"
34+
"sigs.k8s.io/controller-runtime/pkg/client"
3435
"sigs.k8s.io/controller-runtime/pkg/log"
3536

3637
ipamv1alpha1 "github.com/liqotech/liqo/apis/ipam/v1alpha1"
@@ -101,6 +102,12 @@ func run(cmd *cobra.Command, _ []string) error {
101102

102103
// Get the rest config.
103104
cfg := restcfg.SetRateLimiter(ctrl.GetConfigOrDie())
105+
options.Config = cfg
106+
cl, err := client.New(cfg, client.Options{})
107+
if err != nil {
108+
return err
109+
}
110+
options.Client = cl
104111

105112
if options.EnableLeaderElection {
106113
if leader, err := leaderelection.Blocking(ctx, cfg, record.NewBroadcaster(), &leaderelection.Opts{
@@ -123,7 +130,10 @@ func run(cmd *cobra.Command, _ []string) error {
123130
hs := health.NewServer()
124131
options.HealthServer = hs
125132

126-
liqoIPAM := ipam.New(&options)
133+
liqoIPAM, err := ipam.New(ctx, &options)
134+
if err != nil {
135+
return err
136+
}
127137

128138
lis, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", options.Port))
129139
if err != nil {

deployments/liqo/charts/liqo-crds/crds/ipam.liqo.io_ips.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,17 @@ spec:
439439
status:
440440
description: IPStatus defines remapped IPs.
441441
properties:
442+
cidr:
443+
description: CIDR is the network CIDR where the IP is allocated.
444+
format: cidr
445+
type: string
446+
ip:
447+
description: IP is the remapped IP.
448+
format: ipv4
449+
type: string
450+
x-kubernetes-validations:
451+
- message: IP field is immutable
452+
rule: self == oldSelf
442453
ipMappings:
443454
additionalProperties:
444455
description: IP defines a syntax validated IP.
@@ -447,6 +458,8 @@ spec:
447458
description: IPMappings contains the mapping of the local IP for each
448459
remote cluster.
449460
type: object
461+
required:
462+
- ip
450463
type: object
451464
required:
452465
- spec

pkg/ipam/doc.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2019-2024 The Liqo Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// Package ipam contains the login for the Liqo IPAM module.
16+
package ipam

pkg/ipam/initialize.go

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Copyright 2019-2024 The Liqo Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package ipam
16+
17+
import (
18+
"context"
19+
20+
klog "k8s.io/klog/v2"
21+
22+
ipamv1alpha1 "github.com/liqotech/liqo/apis/ipam/v1alpha1"
23+
"github.com/liqotech/liqo/pkg/consts"
24+
)
25+
26+
// +kubebuilder:rbac:groups=ipam.liqo.io,resources=ips,verbs=get;list;watch
27+
// +kubebuilder:rbac:groups=ipam.liqo.io,resources=networks,verbs=get;list;watch
28+
29+
type ipCidr struct {
30+
ip string
31+
cidr string
32+
}
33+
34+
func (lipam *LiqoIPAM) initialize(ctx context.Context) error {
35+
if err := lipam.initializeNetworks(ctx); err != nil {
36+
return err
37+
}
38+
39+
if err := lipam.initializeIPs(ctx); err != nil {
40+
return err
41+
}
42+
43+
klog.Info("IPAM initialized")
44+
return nil
45+
}
46+
47+
func (lipam *LiqoIPAM) initializeNetworks(ctx context.Context) error {
48+
// Initialize the networks.
49+
nets, err := lipam.getReservedNetworks(ctx)
50+
if err != nil {
51+
return err
52+
}
53+
54+
for _, net := range nets {
55+
if err := lipam.reserveNetwork(net); err != nil {
56+
klog.Errorf("Failed to reserve network %s: %v", net, err)
57+
return err
58+
}
59+
}
60+
61+
return nil
62+
}
63+
64+
func (lipam *LiqoIPAM) initializeIPs(ctx context.Context) error {
65+
// Initialize the IPs.
66+
ips, err := lipam.getReservedIPs(ctx)
67+
if err != nil {
68+
return err
69+
}
70+
71+
for _, ip := range ips {
72+
if err := lipam.reserveIP(ip.ip, ip.cidr); err != nil {
73+
klog.Errorf("Failed to reserve IP %s in network %s: %v", ip.ip, ip.cidr, err)
74+
return err
75+
}
76+
}
77+
78+
return nil
79+
}
80+
81+
func (lipam *LiqoIPAM) getReservedNetworks(ctx context.Context) ([]string, error) {
82+
var nets []string
83+
var networks ipamv1alpha1.NetworkList
84+
if err := lipam.Options.Client.List(ctx, &networks); err != nil {
85+
return nil, err
86+
}
87+
88+
for i := range networks.Items {
89+
net := &networks.Items[i]
90+
91+
var cidr string
92+
switch {
93+
case net.Labels != nil && net.Labels[consts.NetworkNotRemappedLabelKey] == consts.NetworkNotRemappedLabelValue:
94+
cidr = net.Spec.CIDR.String()
95+
default:
96+
cidr = net.Status.CIDR.String()
97+
}
98+
if cidr == "" {
99+
klog.Warningf("Network %s has no CIDR", net.Name)
100+
continue
101+
}
102+
103+
nets = append(nets, cidr)
104+
}
105+
106+
return nets, nil
107+
}
108+
109+
func (lipam *LiqoIPAM) getReservedIPs(ctx context.Context) ([]ipCidr, error) {
110+
var ips []ipCidr
111+
var ipList ipamv1alpha1.IPList
112+
if err := lipam.Options.Client.List(ctx, &ipList); err != nil {
113+
return nil, err
114+
}
115+
116+
for i := range ipList.Items {
117+
ip := &ipList.Items[i]
118+
119+
address := ip.Status.IP.String()
120+
if address == "" {
121+
klog.Warningf("IP %s has no address", ip.Name)
122+
continue
123+
}
124+
125+
cidr := ip.Status.CIDR.String()
126+
if cidr == "" {
127+
klog.Warningf("IP %s has no CIDR", ip.Name)
128+
continue
129+
}
130+
131+
ips = append(ips, ipCidr{ip: address, cidr: cidr})
132+
}
133+
134+
return ips, nil
135+
}
136+
137+
func (lipam *LiqoIPAM) reserveNetwork(cidr string) error {
138+
// TODO: Reserve the network.
139+
klog.Infof("Reserved network %s", cidr)
140+
return nil
141+
}
142+
143+
func (lipam *LiqoIPAM) reserveIP(ip, cidr string) error {
144+
// TODO: Reserve the IP.
145+
klog.Infof("Reserved IP %s in network %s", ip, cidr)
146+
return nil
147+
}

pkg/ipam/ipam.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,27 @@
1515
package ipam
1616

1717
import (
18+
"context"
1819
"time"
1920

2021
"google.golang.org/grpc/health"
2122
"google.golang.org/grpc/health/grpc_health_v1"
23+
"k8s.io/client-go/rest"
24+
"sigs.k8s.io/controller-runtime/pkg/client"
2225
)
2326

2427
// LiqoIPAM is the struct implementing the IPAM interface.
2528
type LiqoIPAM struct {
2629
UnimplementedIPAMServer
30+
31+
Options *Options
2732
}
2833

2934
// Options contains the options to configure the IPAM.
3035
type Options struct {
31-
Port int
36+
Port int
37+
Config *rest.Config
38+
Client client.Client
3239

3340
EnableLeaderElection bool
3441
LeaderElectionNamespace string
@@ -42,11 +49,17 @@ type Options struct {
4249
}
4350

4451
// New creates a new instance of the LiqoIPAM.
45-
func New(opts *Options) *LiqoIPAM {
52+
func New(ctx context.Context, opts *Options) (*LiqoIPAM, error) {
4653
opts.HealthServer.SetServingStatus(IPAM_ServiceDesc.ServiceName, grpc_health_v1.HealthCheckResponse_NOT_SERVING)
4754

48-
// TODO: add here the initialization logic
55+
lipam := &LiqoIPAM{
56+
Options: opts,
57+
}
58+
59+
if err := lipam.initialize(ctx); err != nil {
60+
return nil, err
61+
}
4962

5063
opts.HealthServer.SetServingStatus(IPAM_ServiceDesc.ServiceName, grpc_health_v1.HealthCheckResponse_SERVING)
51-
return &LiqoIPAM{}
64+
return lipam, nil
5265
}

0 commit comments

Comments
 (0)