6 k8sv1alpha1 "ovn4nfv-k8s-plugin/pkg/apis/k8s/v1alpha1"
8 // corev1 "k8s.io/api/core/v1"
9 "github.com/go-logr/logr"
10 "k8s.io/apimachinery/pkg/api/errors"
11 "k8s.io/apimachinery/pkg/runtime"
12 "ovn4nfv-k8s-plugin/internal/pkg/ovn"
13 "ovn4nfv-k8s-plugin/pkg/utils"
14 "sigs.k8s.io/controller-runtime/pkg/client"
15 "sigs.k8s.io/controller-runtime/pkg/controller"
16 "sigs.k8s.io/controller-runtime/pkg/handler"
17 "sigs.k8s.io/controller-runtime/pkg/manager"
18 "sigs.k8s.io/controller-runtime/pkg/reconcile"
19 logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
20 "sigs.k8s.io/controller-runtime/pkg/source"
23 var log = logf.Log.WithName("network_controller")
25 // Add creates a new Network Controller and adds it to the Manager. The Manager will set fields on the Controller
26 // and Start it when the Manager is Started.
27 func Add(mgr manager.Manager) error {
28 return add(mgr, newReconciler(mgr))
31 // newReconciler returns a new reconcile.Reconciler
32 func newReconciler(mgr manager.Manager) reconcile.Reconciler {
33 return &ReconcileNetwork{client: mgr.GetClient(), scheme: mgr.GetScheme()}
36 // add adds a new Controller to mgr with r as the reconcile.Reconciler
37 func add(mgr manager.Manager, r reconcile.Reconciler) error {
38 // Create a new controller
39 c, err := controller.New("network-controller", mgr, controller.Options{Reconciler: r})
43 // Watch for changes to primary resource Network
44 err = c.Watch(&source.Kind{Type: &k8sv1alpha1.Network{}}, &handler.EnqueueRequestForObject{})
52 // blank assignment to verify that ReconcileNetwork implements reconcile.Reconciler
53 var _ reconcile.Reconciler = &ReconcileNetwork{}
55 // ReconcileNetwork reconciles a Network object
56 type ReconcileNetwork struct {
57 // This client, initialized using mgr.Client() above, is a split client
58 // that reads objects from the cache and writes to the apiserver
60 scheme *runtime.Scheme
62 type reconcileFun func(instance *k8sv1alpha1.Network, reqLogger logr.Logger) error
64 // Reconcile reads that state of the cluster for a Network object and makes changes based on the state read
65 // and what is in the Network.Spec
66 // The Controller will requeue the Request to be processed again if the returned error is non-nil or
67 // Result.Requeue is true, otherwise upon completion it will remove the work from the queue.
68 func (r *ReconcileNetwork) Reconcile(request reconcile.Request) (reconcile.Result, error) {
69 reqLogger := log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name)
70 reqLogger.V(1).Info("Reconciling Network")
72 // Fetch the Network instance
73 instance := &k8sv1alpha1.Network{}
74 err := r.client.Get(context.TODO(), request.NamespacedName, instance)
76 if errors.IsNotFound(err) {
77 // Request object not found, could have been deleted after reconcile request.
78 // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
79 // Return and don't requeue
80 reqLogger.V(1).Info("Network Object not found")
81 return reconcile.Result{}, nil
83 // Error reading the object - requeue the request.
84 return reconcile.Result{}, err
86 for _, fun := range []reconcileFun{
87 r.reconcileFinalizers,
90 if err = fun(instance, reqLogger); err != nil {
91 return reconcile.Result{}, err
94 return reconcile.Result{}, nil
98 nfnNetworkFinalizer = "nfnCleanUpNetwork"
101 func (r *ReconcileNetwork) createNetwork(cr *k8sv1alpha1.Network, reqLogger logr.Logger) error {
103 if !cr.DeletionTimestamp.IsZero() {
104 // Marked for deletion
108 case cr.Spec.CniType == "ovn4nfv":
109 ovnCtl, err := ovn.GetOvnController()
113 err = ovnCtl.CreateNetwork(cr)
116 reqLogger.Error(err, "Error Creating Network")
117 cr.Status.State = k8sv1alpha1.CreateInternalError
119 cr.Status.State = k8sv1alpha1.Created
121 err = r.client.Status().Update(context.TODO(), cr)
125 // If OVN internal error don't requeue
127 // Add other CNI types here
129 reqLogger.Info("CNI type not supported", "name", cr.Spec.CniType)
130 return fmt.Errorf("CNI type not supported")
134 func (r *ReconcileNetwork) deleteNetwork(cr *k8sv1alpha1.Network, reqLogger logr.Logger) error {
137 case cr.Spec.CniType == "ovn4nfv":
138 ovnCtl, err := ovn.GetOvnController()
142 err = ovnCtl.DeleteNetwork(cr)
145 reqLogger.Error(err, "Error Delete Network")
146 cr.Status.State = k8sv1alpha1.DeleteInternalError
147 err = r.client.Status().Update(context.TODO(), cr)
152 // If OVN internal error don't requeue
154 // Add other CNI types here
156 reqLogger.Info("CNI type not supported", "name", cr.Spec.CniType)
157 return fmt.Errorf("CNI type not supported")
160 func (r *ReconcileNetwork) reconcileFinalizers(instance *k8sv1alpha1.Network, reqLogger logr.Logger) (err error) {
162 if !instance.DeletionTimestamp.IsZero() {
163 // Instance marked for deletion
164 if utils.Contains(instance.ObjectMeta.Finalizers, nfnNetworkFinalizer) {
165 reqLogger.V(1).Info("Finalizer found - delete network")
166 if err = r.deleteNetwork(instance, reqLogger); err != nil {
167 reqLogger.Error(err, "Delete network")
169 // Remove the finalizer even if Delete Network fails. Fatal error retry will not resolve
170 instance.ObjectMeta.Finalizers = utils.Remove(instance.ObjectMeta.Finalizers, nfnNetworkFinalizer)
171 if err = r.client.Update(context.TODO(), instance); err != nil {
172 reqLogger.Error(err, "Removing Finalize")
178 // If finalizer doesn't exist add it
179 if !utils.Contains(instance.GetFinalizers(), nfnNetworkFinalizer) {
180 instance.SetFinalizers(append(instance.GetFinalizers(), nfnNetworkFinalizer))
181 if err = r.client.Update(context.TODO(), instance); err != nil {
182 reqLogger.Error(err, "Adding Finalize")
185 reqLogger.V(1).Info("Finalizer added")