7 "ovn4nfv-k8s-plugin/internal/pkg/ovn"
9 corev1 "k8s.io/api/core/v1"
10 "k8s.io/apimachinery/pkg/api/errors"
11 "k8s.io/apimachinery/pkg/runtime"
12 "k8s.io/apimachinery/pkg/types"
13 "sigs.k8s.io/controller-runtime/pkg/client"
14 "sigs.k8s.io/controller-runtime/pkg/controller"
15 "sigs.k8s.io/controller-runtime/pkg/event"
16 "sigs.k8s.io/controller-runtime/pkg/handler"
17 "sigs.k8s.io/controller-runtime/pkg/manager"
18 "sigs.k8s.io/controller-runtime/pkg/predicate"
19 "sigs.k8s.io/controller-runtime/pkg/reconcile"
20 logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
21 "sigs.k8s.io/controller-runtime/pkg/source"
24 var log = logf.Log.WithName("controller_pod")
27 nfnNetworkAnnotation = "k8s.plugin.opnfv.org/nfn-network"
30 type nfnNetwork struct {
31 Type string "json:\"type\""
32 Interface []map[string]interface{} "json:\"interface\""
35 var enableOvnDefaultIntf bool = true
37 // Add creates a new Pod Controller and adds it to the Manager. The Manager will set fields on the Controller
38 // and Start it when the Manager is Started.
39 func Add(mgr manager.Manager) error {
40 return add(mgr, newReconciler(mgr))
43 // newReconciler returns a new reconcile.Reconciler
44 func newReconciler(mgr manager.Manager) reconcile.Reconciler {
45 return &ReconcilePod{client: mgr.GetClient(), scheme: mgr.GetScheme()}
48 // add adds a new Controller to mgr with r as the reconcile.Reconciler
49 func add(mgr manager.Manager, r reconcile.Reconciler) error {
51 // Create a new Controller that will call the provided Reconciler function in response
53 c, err := controller.New("pod-controller", mgr, controller.Options{Reconciler: r})
57 // Define Predicates On Create and Update function
59 UpdateFunc: func(e event.UpdateEvent) bool {
60 annotaion := e.MetaNew.GetAnnotations()
61 // The object doesn't contain annotation ,nfnNetworkAnnotation so the event will be
63 if _, ok := annotaion[nfnNetworkAnnotation]; !ok {
66 // If pod is already processed by OVN don't add event
67 if _, ok := annotaion[ovn.Ovn4nfvAnnotationTag]; ok {
72 CreateFunc: func(e event.CreateEvent) bool {
73 // The object doesn't contain annotation ,nfnNetworkAnnotation so the event will be
75 /*annotaion := e.Meta.GetAnnotations()
76 if _, ok := annotaion[nfnNetworkAnnotation]; !ok {
81 DeleteFunc: func(e event.DeleteEvent) bool {
82 // The object doesn't contain annotation ,nfnNetworkAnnotation so the event will be
84 /*annotaion := e.Meta.GetAnnotations()
85 if _, ok := annotaion[nfnNetworkAnnotation]; !ok {
92 // Watch for Pod create / update / delete events and call Reconcile
93 err = c.Watch(&source.Kind{Type: &corev1.Pod{}}, &handler.EnqueueRequestForObject{}, p)
100 // blank assignment to verify that ReconcuilePod implements reconcile.Reconciler
101 var _ reconcile.Reconciler = &ReconcilePod{}
103 // ReconcilePod reconciles a ProviderNetwork object
104 type ReconcilePod struct {
105 // This client, initialized using mgr.Client() above, is a split client
106 // that reads objects from the cache and writes to the apiserver
108 scheme *runtime.Scheme
111 // Reconcile function
112 // The Controller will requeue the Request to be processed again if the returned error is non-nil or
113 // Result.Requeue is true, otherwise upon completion it will remove the work from the queue.
114 func (r *ReconcilePod) Reconcile(request reconcile.Request) (reconcile.Result, error) {
115 reqLogger := log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name)
116 reqLogger.Info("Enter Reconciling Pod")
118 // Fetch the Pod instance
119 instance := &corev1.Pod{}
120 err := r.client.Get(context.TODO(), request.NamespacedName, instance)
123 if errors.IsNotFound(err) {
124 // Request object not found, could have been deleted after reconcile request.
125 // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
126 // Return and don't requeue
127 reqLogger.Info("Delete Pod", "request", request)
128 r.deleteLogicalPorts(request.Name, request.Namespace)
129 reqLogger.Info("Exit Reconciling Pod")
130 return reconcile.Result{}, nil
132 // Error reading the object - requeue the request.
133 return reconcile.Result{}, err
135 if instance.Name == "" || instance.Namespace == "" {
136 return reconcile.Result{}, nil
138 if instance.Spec.HostNetwork {
139 return reconcile.Result{}, nil
142 if instance.Spec.NodeName == "" {
143 return reconcile.Result{
148 err = r.addLogicalPorts(instance)
149 if err != nil && err.Error() == "Failed to add ports" {
150 // Requeue the object
151 return reconcile.Result{}, err
153 reqLogger.Info("Exit Reconciling Pod")
154 return reconcile.Result{}, nil
157 // annotatePod annotates pod with the given annotations
158 func (r *ReconcilePod) setPodAnnotation(pod *corev1.Pod, key, value string) error {
160 patchData := fmt.Sprintf(`{"metadata":{"annotations":{"%s":"%s"}}}`, key, value)
161 err := r.client.Patch(context.TODO(), pod, client.ConstantPatch(types.MergePatchType, []byte(patchData)))
163 log.Error(err, "Updating pod failed", "pod", pod, "key", key, "value", value)
169 func (r *ReconcilePod) addLogicalPorts(pod *corev1.Pod) error {
171 nfn, err := r.readPodAnnotation(pod)
173 // No annotation for multiple interfaces
174 nfn = &nfnNetwork{Interface: nil}
175 if enableOvnDefaultIntf == true {
183 case nfn.Type == "ovn4nfv":
184 ovnCtl, err := ovn.GetOvnController()
188 if _, ok := pod.Annotations[ovn.Ovn4nfvAnnotationTag]; ok {
189 return fmt.Errorf("Pod annotation found")
191 key, value := ovnCtl.AddLogicalPorts(pod, nfn.Interface)
193 return r.setPodAnnotation(pod, key, value)
195 return fmt.Errorf("Failed to add ports")
197 return fmt.Errorf("Unsupported Networking type %s", nfn.Type)
198 // Add other types here
202 func (r *ReconcilePod) deleteLogicalPorts(name, namesapce string) error {
204 // Run delete for all controllers; pod annonations inaccessible
205 ovnCtl, err := ovn.GetOvnController()
209 log.Info("Calling DeleteLogicalPorts")
210 ovnCtl.DeleteLogicalPorts(name, namesapce)
212 // Add other types here
215 func (r *ReconcilePod) readPodAnnotation(pod *corev1.Pod) (*nfnNetwork, error) {
216 annotaion, ok := pod.Annotations[nfnNetworkAnnotation]
218 return nil, fmt.Errorf("Invalid annotations")
221 err := json.Unmarshal([]byte(annotaion), &nfn)
223 log.Error(err, "Invalid nfn annotaion", "annotaiton", annotaion)