aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--deploy/crds/k8s_v1alpha1_providernetwork_cr.yaml19
-rw-r--r--deploy/crds/k8s_v1alpha1_providernetwork_crd.yaml14
-rw-r--r--pkg/controller/add_providernetwork.go10
-rw-r--r--pkg/controller/providernetwork/providernetwork_controller.go196
4 files changed, 236 insertions, 3 deletions
diff --git a/deploy/crds/k8s_v1alpha1_providernetwork_cr.yaml b/deploy/crds/k8s_v1alpha1_providernetwork_cr.yaml
new file mode 100644
index 0000000..ef03725
--- /dev/null
+++ b/deploy/crds/k8s_v1alpha1_providernetwork_cr.yaml
@@ -0,0 +1,19 @@
+apiVersion: k8s.plugin.opnfv.org/v1alpha1
+kind: ProviderNetwork
+metadata:
+ name: pnetwork
+spec:
+ cniType: ovn4nfv
+ ipv4Subnets:
+ - subnet: 172.16.33.0/24
+ name: subnet1
+ gateway: 172.16.33.1/24
+ excludeIps: 172.16.33.2 172.16.33.5..172.16.33.10
+ providerNetType: VLAN
+ vlan:
+ vlanId: "100"
+ providerInterfaceName: eth1
+ logicalInterfaceName: eth1.100
+ vlanNodeSelector: specific
+ nodeLabelList:
+ - kubernetes.io/hostname=testnode1
diff --git a/deploy/crds/k8s_v1alpha1_providernetwork_crd.yaml b/deploy/crds/k8s_v1alpha1_providernetwork_crd.yaml
index eabf3f2..cea5b72 100644
--- a/deploy/crds/k8s_v1alpha1_providernetwork_crd.yaml
+++ b/deploy/crds/k8s_v1alpha1_providernetwork_crd.yaml
@@ -101,15 +101,23 @@ spec:
properties:
logicalInterfaceName:
type: string
- node:
- type: string
+ nodeLabelList:
+ description: '"all"/"any"(in which case a node will be randomly
+ selected)/"specific"(see below)'
+ items:
+ type: string
+ type: array
providerInterfaceName:
+ description: if VlanNodeSelector is value "specific" then this array
+ provides a list of nodes labels
type: string
vlanId:
type: string
+ vlanNodeSelector:
+ type: string
required:
- vlanId
- - node
+ - vlanNodeSelector
- providerInterfaceName
type: object
required:
diff --git a/pkg/controller/add_providernetwork.go b/pkg/controller/add_providernetwork.go
new file mode 100644
index 0000000..58c3940
--- /dev/null
+++ b/pkg/controller/add_providernetwork.go
@@ -0,0 +1,10 @@
+package controller
+
+import (
+ "ovn4nfv-k8s-plugin/pkg/controller/providernetwork"
+)
+
+func init() {
+ // AddToManagerFuncs is a list of functions to create controllers and add them to a manager.
+ AddToManagerFuncs = append(AddToManagerFuncs, providernetwork.Add)
+}
diff --git a/pkg/controller/providernetwork/providernetwork_controller.go b/pkg/controller/providernetwork/providernetwork_controller.go
new file mode 100644
index 0000000..1281ac3
--- /dev/null
+++ b/pkg/controller/providernetwork/providernetwork_controller.go
@@ -0,0 +1,196 @@
+package providernetwork
+
+import (
+ "context"
+ "fmt"
+ "github.com/go-logr/logr"
+ "k8s.io/apimachinery/pkg/api/errors"
+ "k8s.io/apimachinery/pkg/runtime"
+ notif "ovn4nfv-k8s-plugin/internal/pkg/nfnNotify"
+ "ovn4nfv-k8s-plugin/internal/pkg/ovn"
+ k8sv1alpha1 "ovn4nfv-k8s-plugin/pkg/apis/k8s/v1alpha1"
+ "ovn4nfv-k8s-plugin/pkg/utils"
+ "reflect"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/controller"
+ "sigs.k8s.io/controller-runtime/pkg/handler"
+ "sigs.k8s.io/controller-runtime/pkg/manager"
+ "sigs.k8s.io/controller-runtime/pkg/reconcile"
+ logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
+ "sigs.k8s.io/controller-runtime/pkg/source"
+)
+
+var log = logf.Log.WithName("controller_providernetwork")
+
+// Add creates a new ProviderNetwork Controller and adds it to the Manager. The Manager will set fields on the Controller
+// and Start it when the Manager is Started.
+func Add(mgr manager.Manager) error {
+ return add(mgr, newReconciler(mgr))
+}
+
+// newReconciler returns a new reconcile.Reconciler
+func newReconciler(mgr manager.Manager) reconcile.Reconciler {
+ return &ReconcileProviderNetwork{client: mgr.GetClient(), scheme: mgr.GetScheme()}
+}
+
+// add adds a new Controller to mgr with r as the reconcile.Reconciler
+func add(mgr manager.Manager, r reconcile.Reconciler) error {
+ // Create a new controller
+ c, err := controller.New("providernetwork-controller", mgr, controller.Options{Reconciler: r})
+ if err != nil {
+ return err
+ }
+
+ // Watch for changes to primary resource ProviderNetwork
+ err = c.Watch(&source.Kind{Type: &k8sv1alpha1.ProviderNetwork{}}, &handler.EnqueueRequestForObject{})
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// blank assignment to verify that ReconcileProviderNetwork implements reconcile.Reconciler
+var _ reconcile.Reconciler = &ReconcileProviderNetwork{}
+
+// ReconcileProviderNetwork reconciles a ProviderNetwork object
+type ReconcileProviderNetwork struct {
+ // This client, initialized using mgr.Client() above, is a split client
+ // that reads objects from the cache and writes to the apiserver
+ client client.Client
+ scheme *runtime.Scheme
+}
+type reconcileFun func(instance *k8sv1alpha1.ProviderNetwork, reqLogger logr.Logger) error
+
+// Reconcile reads that state of the cluster for a ProviderNetwork object and makes changes based on the state read
+// and what is in the ProviderNetwork.Spec
+// The Controller will requeue the Request to be processed again if the returned error is non-nil or
+// Result.Requeue is true, otherwise upon completion it will remove the work from the queue.
+func (r *ReconcileProviderNetwork) Reconcile(request reconcile.Request) (reconcile.Result, error) {
+ reqLogger := log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name)
+ reqLogger.Info("Reconciling ProviderNetwork")
+
+ // Fetch the ProviderNetwork instance
+ instance := &k8sv1alpha1.ProviderNetwork{}
+ err := r.client.Get(context.TODO(), request.NamespacedName, instance)
+ if err != nil {
+ if errors.IsNotFound(err) {
+ // Request object not found, could have been deleted after reconcile request.
+ // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
+ // Return and don't requeue
+ return reconcile.Result{}, nil
+ }
+ // Error reading the object - requeue the request.
+ return reconcile.Result{}, err
+ }
+ for _, fun := range []reconcileFun{
+ r.reconcileFinalizers,
+ r.createNetwork,
+ } {
+ if err = fun(instance, reqLogger); err != nil {
+ return reconcile.Result{}, err
+ }
+ }
+ return reconcile.Result{}, nil
+}
+
+const (
+ nfnProviderNetworkFinalizer = "nfnCleanUpProviderNetwork"
+)
+
+func (r *ReconcileProviderNetwork) createNetwork(cr *k8sv1alpha1.ProviderNetwork, reqLogger logr.Logger) error {
+
+ if !cr.DeletionTimestamp.IsZero() {
+ // Marked for deletion
+ return nil
+ }
+ switch {
+ case cr.Spec.CniType == "ovn4nfv":
+ ovnCtl, err := ovn.GetOvnController()
+ if err != nil {
+ return err
+ }
+ err = ovnCtl.CreateProviderNetwork(cr)
+ if err != nil && !reflect.DeepEqual(err, fmt.Errorf("LS exists")) {
+ // Log the error
+ reqLogger.Error(err, "Error Creating Network")
+ cr.Status.State = k8sv1alpha1.CreateInternalError
+ } else {
+ err := notif.SendNotif(cr, "create", "")
+ if err != nil {
+ cr.Status.State = k8sv1alpha1.CreateInternalError
+ reqLogger.Error(err, "Error Sending Message")
+ } else {
+ cr.Status.State = k8sv1alpha1.Created
+ }
+ err = r.client.Status().Update(context.TODO(), cr)
+ if err != nil {
+ return err
+ }
+ }
+ // If OVN internal error don't requeue
+ return nil
+ // Add other CNI types here
+ }
+ reqLogger.Info("CNI type not supported", "name", cr.Spec.CniType)
+ return fmt.Errorf("CNI type not supported")
+}
+
+func (r *ReconcileProviderNetwork) deleteNetwork(cr *k8sv1alpha1.ProviderNetwork, reqLogger logr.Logger) error {
+
+ switch {
+ case cr.Spec.CniType == "ovn4nfv":
+ ovnCtl, err := ovn.GetOvnController()
+ if err != nil {
+ return err
+ }
+
+ notif.SendNotif(cr, "delete", "")
+
+ err = ovnCtl.DeleteProviderNetwork(cr)
+ if err != nil {
+ // Log the error
+ reqLogger.Error(err, "Error Delete Network")
+ cr.Status.State = k8sv1alpha1.DeleteInternalError
+ err = r.client.Status().Update(context.TODO(), cr)
+ if err != nil {
+ return err
+ }
+ }
+ // If OVN internal error don't requeue
+ return nil
+ // Add other CNI types here
+ }
+ reqLogger.Info("CNI type not supported", "name", cr.Spec.CniType)
+ return fmt.Errorf("CNI type not supported")
+}
+
+func (r *ReconcileProviderNetwork) reconcileFinalizers(instance *k8sv1alpha1.ProviderNetwork, reqLogger logr.Logger) (err error) {
+
+ if !instance.DeletionTimestamp.IsZero() {
+ // Instance marked for deletion
+ if utils.Contains(instance.ObjectMeta.Finalizers, nfnProviderNetworkFinalizer) {
+ reqLogger.V(1).Info("Finalizer found - delete network")
+ if err = r.deleteNetwork(instance, reqLogger); err != nil {
+ reqLogger.Error(err, "Delete network")
+ }
+ // Remove the finalizer even if Delete Network fails. Fatal error retry will not resolve
+ instance.ObjectMeta.Finalizers = utils.Remove(instance.ObjectMeta.Finalizers, nfnProviderNetworkFinalizer)
+ if err = r.client.Update(context.TODO(), instance); err != nil {
+ reqLogger.Error(err, "Removing Finalize")
+ return err
+ }
+ }
+
+ } else {
+ // If finalizer doesn't exist add it
+ if !utils.Contains(instance.GetFinalizers(), nfnProviderNetworkFinalizer) {
+ instance.SetFinalizers(append(instance.GetFinalizers(), nfnProviderNetworkFinalizer))
+ if err = r.client.Update(context.TODO(), instance); err != nil {
+ reqLogger.Error(err, "Adding Finalize")
+ return err
+ }
+ reqLogger.V(1).Info("Finalizer added")
+ }
+ }
+ return nil
+}