Repository: Mellanox/network-operator
Pull request #1379: feat: Integrate maintenance OP upgrade with network OP
Author: login: heyvister1
Created: 2025-03-18T13:21:05Z | Merged: 2025-04-24T09:04:26Z

Integrate network operator upgrade controller with `k8s-operator-libs` changes for supporting new maintenance OP `requestor` upgrade mode

This PR depends on [NVIDIA/k8s-operator-libs#86](https://github.com/NVIDIA/k8s-operator-libs/pull/86)


Diff:
diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml
index 7bb9da81a..0436b1353 100644
--- a/config/rbac/role.yaml
+++ b/config/rbac/role.yaml
@@ -205,6 +205,12 @@ rules:
   - patch
   - update
   - watch
+- apiGroups:
+  - maintenance.nvidia.com
+  resources:
+  - nodemaintenances/status
+  verbs:
+  - get
 - apiGroups:
   - mellanox.com
   resources:
diff --git a/controllers/nicclusterpolicy_controller.go b/controllers/nicclusterpolicy_controller.go
index 355d6963d..9ad5a6c39 100644
--- a/controllers/nicclusterpolicy_controller.go
+++ b/controllers/nicclusterpolicy_controller.go
@@ -103,6 +103,7 @@ type NicClusterPolicyReconciler struct {
 // +kubebuilder:rbac:groups=configuration.net.nvidia.com,resources=nicfirmwaresources,verbs=get;list;watch;create;update;patch;delete
 // +kubebuilder:rbac:groups=configuration.net.nvidia.com,resources=nicfirmwaresources/finalizers,verbs=update
 // +kubebuilder:rbac:groups=maintenance.nvidia.com,resources=nodemaintenances,verbs=get;list;watch;create;update;patch;delete
+// +kubebuilder:rbac:groups=maintenance.nvidia.com,resources=nodemaintenances/status,verbs=get
 
 // Reconcile is part of the main kubernetes reconciliation loop which aims to
 // move the current state of the cluster closer to the desired state.
diff --git a/controllers/upgrade_controller.go b/controllers/upgrade_controller.go
index ca9de9131..458988865 100644
--- a/controllers/upgrade_controller.go
+++ b/controllers/upgrade_controller.go
@@ -38,6 +38,8 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/predicate"
 	"sigs.k8s.io/controller-runtime/pkg/reconcile"
 
+	maintenancev1alpha1 "github.com/Mellanox/maintenance-operator/api/v1alpha1"
+
 	mellanoxv1alpha1 "github.com/Mellanox/network-operator/api/v1alpha1"
 	"github.com/Mellanox/network-operator/pkg/config"
 	"github.com/Mellanox/network-operator/pkg/consts"
@@ -192,7 +194,8 @@ func (r *UpgradeReconciler) removeNodeUpgradeStateAnnotations(ctx context.Contex
 // SetupWithManager sets up the controller with the Manager.
 //
 //nolint:dupl
-func (r *UpgradeReconciler) SetupWithManager(mgr ctrl.Manager) error {
+func (r *UpgradeReconciler) SetupWithManager(mgr ctrl.Manager,
+	requestorPredicate upgrade.ConditionChangedPredicate) error {
 	// we always add object with a same(static) key to the queue to reduce
 	// reconciliation count
 	qHandler := func(q workqueue.TypedRateLimitingInterface[reconcile.Request]) {
@@ -228,14 +231,14 @@ func (r *UpgradeReconciler) SetupWithManager(mgr ctrl.Manager) error {
 		labels := object.GetLabels()
 		_, ok := labels[consts.OfedDriverLabel]
 		return ok
-	}))
+	}), requestorPredicate)
 
 	// react only on label and annotation changes
 	nodePredicates := builder.WithPredicates(
 		predicate.Or(predicate.AnnotationChangedPredicate{},
 			predicate.LabelChangedPredicate{}))
 
-	return ctrl.NewControllerManagedBy(mgr).
+	mngr := ctrl.NewControllerManagedBy(mgr).
 		For(&mellanoxv1alpha1.NicClusterPolicy{}).
 		Named("Upgrade").
 		// set MaxConcurrentReconciles to 1, by default it is already 1, but
@@ -244,6 +247,14 @@ func (r *UpgradeReconciler) SetupWithManager(mgr ctrl.Manager) error {
 		WithOptions(controller.Options{MaxConcurrentReconciles: 1}).
 		Watches(&mellanoxv1alpha1.NicClusterPolicy{}, createUpdateDeleteEnqueue).
 		Watches(&corev1.Node{}, createUpdateEnqueue, nodePredicates).
-		Watches(&appsv1.DaemonSet{}, createUpdateDeleteEnqueue, daemonSetPredicates).
-		Complete(r)
+		Watches(&appsv1.DaemonSet{}, createUpdateDeleteEnqueue, daemonSetPredicates)
+
+	// Conditionally add Watches for NodeMaintenance if UseMaintenanceOperator is true
+	requestorOpts := upgrade.GetRequestorOptsFromEnvs()
+	if requestorOpts.UseMaintenanceOperator {
+		mngr = mngr.Watches(&maintenancev1alpha1.NodeMaintenance{}, createUpdateDeleteEnqueue,
+			builder.WithPredicates(requestorPredicate))
+	}
+
+	return mngr.Complete(r)
 }
diff --git a/deployment/network-operator/templates/operator.yaml b/deployment/network-operator/templates/operator.yaml
index 23997b64e..e78dd88a2 100644
--- a/deployment/network-operator/templates/operator.yaml
+++ b/deployment/network-operator/templates/operator.yaml
@@ -90,6 +90,14 @@ spec:
               value: "{{ .repository }}/{{ .image }}:{{ .version }}"
               {{- end }}
             {{- end }}
+            {{- if .Values.maintenanceOperator.enabled }}
+            - name: MAINTENANCE_OPERATOR_ENABLED
+              value: "{{ .Values.operator.maintenanceOperator.useRequestor }}"
+            - name: MAINTENANCE_OPERATOR_REQUESTOR_ID
+              value: {{ .Values.operator.maintenanceOperator.requestorID }}
+            - name: MAINTENANCE_OPERATOR_REQUESTOR_NAMESPACE
+              value: {{ .Values.operator.maintenanceOperator.nodeMaintenanceNamespace }}
+            {{- end }}
           securityContext:
             allowPrivilegeEscalation: false
           livenessProbe:
diff --git a/deployment/network-operator/templates/role.yaml b/deployment/network-operator/templates/role.yaml
index 292230a08..066e86c68 100644
--- a/deployment/network-operator/templates/role.yaml
+++ b/deployment/network-operator/templates/role.yaml
@@ -332,19 +332,7 @@ rules:
     - patch
     - update
 - apiGroups:
-    - maintenance.nvidia.com
-  resources:
-    - nodemaintenances
-  verbs:
-    - create
-    - delete
-    - get
-    - list
-    - patch
-    - update
-    - watch
-- apiGroups:
-    - mellanox.com
+  - mellanox.com
   resources:
     - nicclusterpolicies
     - nicclusterpolicies/status
@@ -458,4 +446,22 @@ rules:
     - deletecollection
     - get
     - list
-    - patch
\ No newline at end of file
+    - patch
+- apiGroups:
+  - maintenance.nvidia.com
+  resources:
+  - nodemaintenances
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - maintenance.nvidia.com
+  resources:
+  - nodemaintenances/status
+  verbs:
+  - get
diff --git a/deployment/network-operator/values.yaml b/deployment/network-operator/values.yaml
index 2620e5658..a9b43340a 100644
--- a/deployment/network-operator/values.yaml
+++ b/deployment/network-operator/values.yaml
@@ -270,6 +270,11 @@ operator:
   # parameter. Note that the CNI bin directory should be aligned with the CNI bin
   # directory in the container runtime.
   cniBinDirectory: /opt/cni/bin
+  # -- Enable the use of maintenance operator upgrade logic.
+  maintenanceOperator:
+    useRequestor: false
+    requestorID: "nvidia.network.operator"
+    nodeMaintenanceNamespace: default
   # -- Enable the use of Driver ToolKit to compile DOCA Drivers (OpenShift only).
   useDTK: true
   admissionController:
diff --git a/go.mod b/go.mod
index 8e97436f9..27b9f5f40 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,8 @@ go 1.23.2
 
 require (
 	github.com/Masterminds/semver/v3 v3.3.1
-	github.com/NVIDIA/k8s-operator-libs v0.0.0-20241120073822-1ad8938d7274
+	github.com/Mellanox/maintenance-operator/api v0.1.1
+	github.com/NVIDIA/k8s-operator-libs v0.0.0-20250423130453-abf588756c1c
 	github.com/caarlos0/env/v6 v6.10.1
 	github.com/containers/image/v5 v5.34.3
 	github.com/go-logr/logr v1.4.2
@@ -18,11 +19,11 @@ require (
 	github.com/stretchr/testify v1.10.0
 	github.com/xeipuuv/gojsonschema v1.2.0
 	gopkg.in/yaml.v3 v3.0.1
-	k8s.io/api v0.31.7
-	k8s.io/apimachinery v0.31.7
-	k8s.io/client-go v0.31.7
-	k8s.io/utils v0.0.0-20240921022957-49e7df575cb6
-	sigs.k8s.io/controller-runtime v0.19.7
+	k8s.io/api v0.32.3
+	k8s.io/apimachinery v0.32.3
+	k8s.io/client-go v0.32.3
+	k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
+	sigs.k8s.io/controller-runtime v0.20.4
 	sigs.k8s.io/yaml v1.4.0
 )
 
@@ -41,7 +42,7 @@ require (
 	github.com/docker/docker-credential-helpers v0.8.2 // indirect
 	github.com/emicklei/go-restful/v3 v3.12.1 // indirect
 	github.com/evanphx/json-patch v5.9.0+incompatible // indirect
-	github.com/evanphx/json-patch/v5 v5.9.0 // indirect
+	github.com/evanphx/json-patch/v5 v5.9.11 // indirect
 	github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
 	github.com/fsnotify/fsnotify v1.7.0 // indirect
 	github.com/fxamacker/cbor/v2 v2.7.0 // indirect
@@ -52,7 +53,6 @@ require (
 	github.com/go-openapi/swag v0.23.0 // indirect
 	github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
-	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
 	github.com/golang/protobuf v1.5.4 // indirect
 	github.com/google/btree v1.1.3 // indirect
 	github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
@@ -63,7 +63,6 @@ require (
 	github.com/google/uuid v1.6.0 // indirect
 	github.com/gorilla/websocket v1.5.3 // indirect
 	github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
-	github.com/imdario/mergo v0.3.16 // indirect
 	github.com/inconshreveable/mousetrap v1.1.0 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
@@ -100,7 +99,6 @@ require (
 	go.uber.org/automaxprocs v1.6.0 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
 	go.uber.org/zap v1.27.0 // indirect
-	golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 // indirect
 	golang.org/x/net v0.38.0 // indirect
 	golang.org/x/oauth2 v0.25.0 // indirect
 	golang.org/x/sync v0.12.0 // indirect
@@ -113,15 +111,14 @@ require (
 	google.golang.org/protobuf v1.36.5 // indirect
 	gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
-	gopkg.in/yaml.v2 v2.4.0 // indirect
-	k8s.io/apiextensions-apiserver v0.31.1 // indirect
-	k8s.io/cli-runtime v0.31.2 // indirect
-	k8s.io/component-base v0.31.2 // indirect
+	k8s.io/apiextensions-apiserver v0.32.3 // indirect
+	k8s.io/cli-runtime v0.32.3 // indirect
+	k8s.io/component-base v0.32.3 // indirect
 	k8s.io/klog/v2 v2.130.1 // indirect
-	k8s.io/kube-openapi v0.0.0-20241009091222-67ed5848f094 // indirect
-	k8s.io/kubectl v0.31.2 // indirect
+	k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
+	k8s.io/kubectl v0.32.3 // indirect
 	sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
 	sigs.k8s.io/kustomize/api v0.18.0 // indirect
 	sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect
-	sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
+	sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
 )
diff --git a/go.sum b/go.sum
index 73d5db315..773a15462 100644
--- a/go.sum
+++ b/go.sum
@@ -4,8 +4,10 @@ github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ
 github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
 github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4=
 github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
-github.com/NVIDIA/k8s-operator-libs v0.0.0-20241120073822-1ad8938d7274 h1:ClLcJZjIgIWOYtLXnELKng4F5uDTUZwpgg0a1Dl0Fo8=
-github.com/NVIDIA/k8s-operator-libs v0.0.0-20241120073822-1ad8938d7274/go.mod h1:g8DW2t4Vit91uLdqCxsjKbKYrwCdb/oB9q/YOXdUjmQ=
+github.com/Mellanox/maintenance-operator/api v0.1.1 h1:DSPE7SS9DmieddjZtiL7eA5yCnYm9UkwRo1ViJtixoc=
+github.com/Mellanox/maintenance-operator/api v0.1.1/go.mod h1:5OIBO4beWexC3JvLIH1GGNzr49QW7UoZe2LgT/IXYIc=
+github.com/NVIDIA/k8s-operator-libs v0.0.0-20250423130453-abf588756c1c h1:QAx1rvFT70PPyYU/bx1KlKoQBZpod1D7hKLAluU4lIE=
+github.com/NVIDIA/k8s-operator-libs v0.0.0-20250423130453-abf588756c1c/go.mod h1:B5g1bFq39qbuVK62pz0m93Qy3CCjeutfNICSl7SFoYo=
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -41,8 +43,8 @@ github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtz
 github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
 github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls=
 github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
-github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
-github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
+github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU=
+github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=
 github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4=
 github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc=
 github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
@@ -65,8 +67,6 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
 github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
-github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
-github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
 github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
 github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
@@ -93,8 +93,6 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN
 github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
 github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
-github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
-github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
 github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
 github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -209,8 +207,6 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo=
-golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -262,44 +258,41 @@ gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSP
 gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
 gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
-gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
-gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
 gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
 gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
-k8s.io/api v0.31.7 h1:wSo59nXpVXmaB6hgNVJCrdnKtyYoutIgpNNBbROBd2U=
-k8s.io/api v0.31.7/go.mod h1:vLUha4nXRUGtQdayzsmjur0lQApK/sJSxyR/fwuujcU=
-k8s.io/apiextensions-apiserver v0.31.1 h1:L+hwULvXx+nvTYX/MKM3kKMZyei+UiSXQWciX/N6E40=
-k8s.io/apiextensions-apiserver v0.31.1/go.mod h1:tWMPR3sgW+jsl2xm9v7lAyRF1rYEK71i9G5dRtkknoQ=
-k8s.io/apimachinery v0.31.7 h1:fpV8yLerIZFAkj0of66+i1ArPv/Btf9KO6Aulng7RRw=
-k8s.io/apimachinery v0.31.7/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
-k8s.io/cli-runtime v0.31.2 h1:7FQt4C4Xnqx8V1GJqymInK0FFsoC+fAZtbLqgXYVOLQ=
-k8s.io/cli-runtime v0.31.2/go.mod h1:XROyicf+G7rQ6FQJMbeDV9jqxzkWXTYD6Uxd15noe0Q=
-k8s.io/client-go v0.31.7 h1:2+LFJc6Xw6rhmpDbN1NSmhoFLWBh62cPG/P+IfaTSGY=
-k8s.io/client-go v0.31.7/go.mod h1:hrrMorBQ17LqzoKIxKg5cSWvmWl94EwA/MUF0Mkf+Zw=
-k8s.io/component-base v0.31.2 h1:Z1J1LIaC0AV+nzcPRFqfK09af6bZ4D1nAOpWsy9owlA=
-k8s.io/component-base v0.31.2/go.mod h1:9PeyyFN/drHjtJZMCTkSpQJS3U9OXORnHQqMLDz0sUQ=
+k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls=
+k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k=
+k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY=
+k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss=
+k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U=
+k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
+k8s.io/cli-runtime v0.32.3 h1:khLF2ivU2T6Q77H97atx3REY9tXiA3OLOjWJxUrdvss=
+k8s.io/cli-runtime v0.32.3/go.mod h1:vZT6dZq7mZAca53rwUfdFSZjdtLyfF61mkf/8q+Xjak=
+k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU=
+k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY=
+k8s.io/component-base v0.32.3 h1:98WJvvMs3QZ2LYHBzvltFSeJjEx7t5+8s71P7M74u8k=
+k8s.io/component-base v0.32.3/go.mod h1:LWi9cR+yPAv7cu2X9rZanTiFKB2kHA+JjmhkKjCZRpI=
 k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
 k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
-k8s.io/kube-openapi v0.0.0-20241009091222-67ed5848f094 h1:MErs8YA0abvOqJ8gIupA1Tz6PKXYUw34XsGlA7uSL1k=
-k8s.io/kube-openapi v0.0.0-20241009091222-67ed5848f094/go.mod h1:7ioBJr1A6igWjsR2fxq2EZ0mlMwYLejazSIc2bzMp2U=
-k8s.io/kubectl v0.31.2 h1:gTxbvRkMBwvTSAlobiTVqsH6S8Aa1aGyBcu5xYLsn8M=
-k8s.io/kubectl v0.31.2/go.mod h1:EyASYVU6PY+032RrTh5ahtSOMgoDRIux9V1JLKtG5xM=
-k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 h1:MDF6h2H/h4tbzmtIKTuctcwZmY0tY9mD9fNT47QO6HI=
-k8s.io/utils v0.0.0-20240921022957-49e7df575cb6/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
-sigs.k8s.io/controller-runtime v0.19.7 h1:DLABZfMr20A+AwCZOHhcbcu+TqBXnJZaVBri9K3EO48=
-sigs.k8s.io/controller-runtime v0.19.7/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4=
+k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
+k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
+k8s.io/kubectl v0.32.3 h1:VMi584rbboso+yjfv0d8uBHwwxbC438LKq+dXd5tOAI=
+k8s.io/kubectl v0.32.3/go.mod h1:6Euv2aso5GKzo/UVMacV6C7miuyevpfI91SvBvV9Zdg=
+k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
+k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU=
+sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY=
 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
 sigs.k8s.io/kustomize/api v0.18.0 h1:hTzp67k+3NEVInwz5BHyzc9rGxIauoXferXyjv5lWPo=
 sigs.k8s.io/kustomize/api v0.18.0/go.mod h1:f8isXnX+8b+SGLHQ6yO4JG1rdkZlvhaCf/uZbLVMb0U=
 sigs.k8s.io/kustomize/kyaml v0.18.1 h1:WvBo56Wzw3fjS+7vBjN6TeivvpbW9GmRaWZ9CIVmt4E=
 sigs.k8s.io/kustomize/kyaml v0.18.1/go.mod h1:C3L2BFVU1jgcddNBE1TxuVLgS46TjObMwW5FT9FcjYo=
-sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
-sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
+sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA=
+sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
 sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
 sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
diff --git a/hack/templates/values/values.template b/hack/templates/values/values.template
index 7166baefa..8ff04dbb0 100644
--- a/hack/templates/values/values.template
+++ b/hack/templates/values/values.template
@@ -270,6 +270,11 @@ operator:
   # parameter. Note that the CNI bin directory should be aligned with the CNI bin
   # directory in the container runtime.
   cniBinDirectory: /opt/cni/bin
+  # -- Enable the use of maintenance operator upgrade logic.
+  maintenanceOperator:
+    useRequestor: false
+    requestorID: "nvidia.network.operator"
+    nodeMaintenanceNamespace: default
   # -- Enable the use of Driver ToolKit to compile DOCA Drivers (OpenShift only).
   useDTK: true
   admissionController:
diff --git a/main.go b/main.go
index 4f7f30da4..663d217ad 100644
--- a/main.go
+++ b/main.go
@@ -40,6 +40,8 @@ import (
 	// to ensure that exec-entrypoint and run can make use of them.
 	_ "k8s.io/client-go/plugin/pkg/client/auth"
 
+	maintenancev1alpha1 "github.com/Mellanox/maintenance-operator/api/v1alpha1"
+
 	mellanoxcomv1alpha1 "github.com/Mellanox/network-operator/api/v1alpha1"
 	"github.com/Mellanox/network-operator/api/v1alpha1/validator"
 	"github.com/Mellanox/network-operator/controllers"
@@ -63,6 +65,7 @@ func init() {
 	utilruntime.Must(netattdefv1.AddToScheme(scheme))
 	utilruntime.Must(osconfigv1.AddToScheme(scheme))
 	utilruntime.Must(imagev1.AddToScheme(scheme))
+	utilruntime.Must(maintenancev1alpha1.AddToScheme(scheme))
 	// +kubebuilder:scaffold:scheme
 }
 
@@ -225,21 +228,27 @@ func setupUpgradeController(mgr ctrl.Manager, migrationChan chan struct{}) error
 	upgrade.SetDriverName("ofed")
 
 	upgradeLogger := ctrl.Log.WithName("controllers").WithName("Upgrade")
-
+	MaintenanceOPEvictionRDMA := upgrade.MaintenanceOPEvictionRDMA
+	requestorOpts := upgrade.GetRequestorOptsFromEnvs()
+	requestorOpts.MaintenanceOPPodEvictionFilter = []maintenancev1alpha1.PodEvictionFiterEntry{
+		{ByResourceNameRegex: &MaintenanceOPEvictionRDMA}}
 	clusterUpdateStateManager, err := upgrade.NewClusterUpgradeStateManager(
-		upgradeLogger.WithName("clusterUpgradeManager"), config.GetConfigOrDie(), nil)
-
+		upgradeLogger.WithName("clusterUpgradeManager"),
+		config.GetConfigOrDie(),
+		nil,
+		upgrade.StateOptions{Requestor: requestorOpts})
 	if err != nil {
 		setupLog.Error(err, "unable to create new ClusterUpdateStateManager", "controller", "Upgrade")
 		return err
 	}
-
+	requestorPredicate := upgrade.NewConditionChangedPredicate(setupLog,
+		requestorOpts.MaintenanceOPRequestorID)
 	if err = (&controllers.UpgradeReconciler{
 		Client:       mgr.GetClient(),
 		Scheme:       mgr.GetScheme(),
 		StateManager: clusterUpdateStateManager,
 		MigrationCh:  migrationChan,
-	}).SetupWithManager(mgr); err != nil {
+	}).SetupWithManager(mgr, requestorPredicate); err != nil {
 		setupLog.Error(err, "unable to create controller", "controller", "Upgrade")
 		return err
 	}
diff --git a/pkg/nodeinfo/mocks/Provider.go b/pkg/nodeinfo/mocks/Provider.go
index ffaa1fab9..e3ce5683c 100644
--- a/pkg/nodeinfo/mocks/Provider.go
+++ b/pkg/nodeinfo/mocks/Provider.go
@@ -3,8 +3,9 @@
 package mocks
 
 import (
-	nodeinfo "github.com/Mellanox/network-operator/pkg/nodeinfo"
 	mock "github.com/stretchr/testify/mock"
+
+	nodeinfo "github.com/Mellanox/network-operator/pkg/nodeinfo"
 )
 
 // Provider is an autogenerated mock type for the Provider type
diff --git a/pkg/staticconfig/mocks/Provider.go b/pkg/staticconfig/mocks/Provider.go
index e1db2fd3f..b878492d8 100644
--- a/pkg/staticconfig/mocks/Provider.go
+++ b/pkg/staticconfig/mocks/Provider.go
@@ -3,8 +3,9 @@
 package mocks
 
 import (
-	staticconfig "github.com/Mellanox/network-operator/pkg/staticconfig"
 	mock "github.com/stretchr/testify/mock"
+
+	staticconfig "github.com/Mellanox/network-operator/pkg/staticconfig"
 )
 
 // Provider is an autogenerated mock type for the Provider type


Reviews:
user: login: heyvister1
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-18T13:26:27Z
user: login: rollandf
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-06T14:05:05Z
user: login: heyvister1
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-07T09:20:19Z
user: login: rollandf
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-07T09:28:29Z
user: login: heyvister1
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-07T09:30:05Z
user: login: rollandf
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-07T09:39:06Z
user: login: heyvister1
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-07T10:16:54Z
user: login: almaslennikov
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-08T11:29:35Z
user: login: heyvister1
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-08T11:47:43Z
user: login: heyvister1
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-08T11:52:14Z
user: login: rollandf
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-09T06:02:00Z
user: login: heyvister1
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-09T06:09:36Z
user: login: heyvister1
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-09T06:10:14Z
user: login: rollandf
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-09T06:14:52Z
user: login: almaslennikov
body: LGTM once my comment is addressed and the corresponding k8s-operator-libs PR is merged
state: DISMISSED
author_association: COLLABORATOR
submitted_at: 2025-04-10T07:24:57Z
user: login: heyvister1
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-10T12:00:37Z
user: login: rollandf
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-23T15:06:39Z

Review comments:
diff_hunk: @@ -18,13 +19,15 @@ require (
 	github.com/stretchr/testify v1.10.0
 	github.com/xeipuuv/gojsonschema v1.2.0
 	gopkg.in/yaml.v3 v3.0.1
-	k8s.io/api v0.31.6
-	k8s.io/apimachinery v0.31.6
-	k8s.io/client-go v0.31.6
-	k8s.io/utils v0.0.0-20240921022957-49e7df575cb6
-	sigs.k8s.io/controller-runtime v0.19.7
+	k8s.io/api v0.32.2
+	k8s.io/apimachinery v0.32.2
+	k8s.io/client-go v0.32.2
+	k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
+	sigs.k8s.io/controller-runtime v0.20.3
 	sigs.k8s.io/yaml v1.4.0
 )
+// TODO: replace github.com/heyvister1/k8s-operator-libs one PR is merged 
+replace github.com/NVIDIA/k8s-operator-libs => github.com/heyvister1/k8s-operator-libs v0.0.0-20250318131039-c2e0ef3cf091
path: go.mod
user: login: heyvister1
body: Should be removed after `k8s-operator-libs` PR is merged
created_at: 2025-03-18T13:26:27Z
author_association: COLLABORATOR
diff_hunk: @@ -267,6 +267,11 @@ operator:
   # parameter. Note that the CNI bin directory should be aligned with the CNI bin
   # directory in the container runtime.
   cniBinDirectory: /opt/cni/bin
+  # -- Enable the use of maintenance operator upgrade logic.
+  maintenanceOperator:
+    enabledRequestor: false
+    requestorID: "nvidia.network.operator"
+    nodeMainteNamespace: default
path: deployment/network-operator/values.yaml
user: login: almaslennikov
body: Looks like a typo in the field name
created_at: 2025-03-18T13:42:33Z
author_association: COLLABORATOR
diff_hunk: @@ -435,3 +435,29 @@ rules:
   - patch
   - update
   - watch
+- apiGroups:
path: deployment/network-operator/templates/role.yaml
user: login: rollandf
body: Please add `//+kubebuilder` annotation to generate rbac.
We should see `config/rbac/role.yaml` updated with same.
created_at: 2025-04-06T14:02:38Z
author_association: MEMBER
diff_hunk: @@ -270,6 +270,11 @@ operator:
   # parameter. Note that the CNI bin directory should be aligned with the CNI bin
   # directory in the container runtime.
   cniBinDirectory: /opt/cni/bin
+  # -- Enable the use of maintenance operator upgrade logic.
+  maintenanceOperator:
+    enabledRequestor: false
+    requestorID: "nvidia.network.operator"
+    nodeMainteNamespace: default
path: hack/templates/values/values.template
user: login: rollandf
body: Maybe "nodeMaitenanceNamespace" is more readable
created_at: 2025-04-06T14:04:12Z
author_association: MEMBER
diff_hunk: @@ -435,3 +435,29 @@ rules:
   - patch
   - update
   - watch
+- apiGroups:
path: deployment/network-operator/templates/role.yaml
user: login: heyvister1
body: Looks like there is no need to add new `kubebuilder` annotation, since they have already been added by Alex
https://github.com/Mellanox/network-operator/blob/master/controllers/nicclusterpolicy_controller.go#L105

created_at: 2025-04-07T09:20:19Z
author_association: COLLABORATOR
diff_hunk: @@ -435,3 +435,29 @@ rules:
   - patch
   - update
   - watch
+- apiGroups:
path: deployment/network-operator/templates/role.yaml
user: login: rollandf
body: The annotations are missing `nodemaintenances/finalizers`.
Also please note that you have already some of these in line 333
created_at: 2025-04-07T09:28:29Z
author_association: MEMBER
diff_hunk: @@ -435,3 +435,29 @@ rules:
   - patch
   - update
   - watch
+- apiGroups:
path: deployment/network-operator/templates/role.yaml
user: login: heyvister1
body: I will remove `nodemaintenances/finalizers` since they are not used. I will also remove duplicated duplicated `nodemaintenances`
created_at: 2025-04-07T09:30:05Z
author_association: COLLABORATOR
diff_hunk: @@ -103,6 +103,7 @@ type NicClusterPolicyReconciler struct {
 // +kubebuilder:rbac:groups=configuration.net.nvidia.com,resources=nicfirmwaresources,verbs=get;list;watch;create;update;patch;delete
 // +kubebuilder:rbac:groups=configuration.net.nvidia.com,resources=nicfirmwaresources/finalizers,verbs=update
 // +kubebuilder:rbac:groups=maintenance.nvidia.com,resources=nodemaintenances,verbs=get;list;watch;create;update;patch;delete
+// +kubebuilder:rbac:groups=aintenance.nvidia.com,resources=nodemaintenances/status,verbs=get
path: controllers/nicclusterpolicy_controller.go
user: login: rollandf
body: typo in name. missing `m`
created_at: 2025-04-07T09:39:05Z
author_association: MEMBER
diff_hunk: @@ -103,6 +103,7 @@ type NicClusterPolicyReconciler struct {
 // +kubebuilder:rbac:groups=configuration.net.nvidia.com,resources=nicfirmwaresources,verbs=get;list;watch;create;update;patch;delete
 // +kubebuilder:rbac:groups=configuration.net.nvidia.com,resources=nicfirmwaresources/finalizers,verbs=update
 // +kubebuilder:rbac:groups=maintenance.nvidia.com,resources=nodemaintenances,verbs=get;list;watch;create;update;patch;delete
+// +kubebuilder:rbac:groups=aintenance.nvidia.com,resources=nodemaintenances/status,verbs=get
path: controllers/nicclusterpolicy_controller.go
user: login: heyvister1
body: Done
created_at: 2025-04-07T10:16:54Z
author_association: COLLABORATOR
diff_hunk: @@ -205,6 +205,12 @@ rules:
   - patch
   - update
   - watch
+- apiGroups:
+  - maintenance.nvidia.com
+  resources:
+  - nodemaintenances/status
+  verbs:
+  - get
path: config/rbac/role.yaml
user: login: almaslennikov
body: Don't we need create permissions?
created_at: 2025-04-08T06:58:33Z
author_association: COLLABORATOR
diff_hunk: @@ -270,6 +270,11 @@ operator:
   # parameter. Note that the CNI bin directory should be aligned with the CNI bin
   # directory in the container runtime.
   cniBinDirectory: /opt/cni/bin
+  # -- Enable the use of maintenance operator upgrade logic.
+  maintenanceOperator:
+    enabledRequestor: false
path: deployment/network-operator/values.yaml
user: login: almaslennikov
body: In helm values we usually use present simple tense with verbs, i.e. `useRequestor`
created_at: 2025-04-08T07:00:51Z
author_association: COLLABORATOR
diff_hunk: @@ -270,6 +270,11 @@ operator:
   # parameter. Note that the CNI bin directory should be aligned with the CNI bin
   # directory in the container runtime.
   cniBinDirectory: /opt/cni/bin
+  # -- Enable the use of maintenance operator upgrade logic.
+  maintenanceOperator:
+    enabledRequestor: false
+    requestorID: "nvidia.network.operator"
+    nodeMaitenanceNamespace: default
path: deployment/network-operator/values.yaml
user: login: almaslennikov
body: typo, should be `nodeMaintenanceNamespace`
created_at: 2025-04-08T07:01:11Z
author_association: COLLABORATOR
diff_hunk: @@ -90,6 +90,14 @@ spec:
               value: "{{ .repository }}/{{ .image }}:{{ .version }}"
               {{- end }}
             {{- end }}
+            {{- if .Values.maintenanceOperator.enabled }}
+            - name: MAINTENANCE_OPERATOR_ENABLED
+              value: "{{ .Values.operator.maintenanceOperator.enabledRequestor }}"
+            - name: MAINTENANCE_OPERATOR_REQUESTOR_ID
+              value: {{ .Values.operator.maintenanceOperator.requestorID }}
+            - name: MAINTENANCE_OPERATOR_REQUESTOR_NAMESPACE
+              value: {{ .Values.operator.maintenanceOperator.nodeMainteNamespace }}
path: deployment/network-operator/templates/operator.yaml
user: login: almaslennikov
body: The parameter used doesn't match the parameter from the helm chart
created_at: 2025-04-08T07:02:13Z
author_association: COLLABORATOR
diff_hunk: @@ -225,21 +229,27 @@ func setupUpgradeController(mgr ctrl.Manager, migrationChan chan struct{}) error
 	upgrade.SetDriverName("ofed")
 
 	upgradeLogger := ctrl.Log.WithName("controllers").WithName("Upgrade")
-
+	MaintenanceOPEvictionRDMA := requestor.MaintenanceOPEvictionRDMA
path: main.go
user: login: almaslennikov
body: We don't change this variable, let's use the constant from the library instead
created_at: 2025-04-08T07:03:00Z
author_association: COLLABORATOR
diff_hunk: @@ -205,6 +205,12 @@ rules:
   - patch
   - update
   - watch
+- apiGroups:
+  - maintenance.nvidia.com
+  resources:
+  - nodemaintenances/status
+  verbs:
+  - get
path: config/rbac/role.yaml
user: login: heyvister1
body: Requestor doesn't change nodeMaintenance status. Status sub resource should be added be Maintenance OP
created_at: 2025-04-08T11:47:43Z
author_association: COLLABORATOR
diff_hunk: @@ -225,21 +229,27 @@ func setupUpgradeController(mgr ctrl.Manager, migrationChan chan struct{}) error
 	upgrade.SetDriverName("ofed")
 
 	upgradeLogger := ctrl.Log.WithName("controllers").WithName("Upgrade")
-
+	MaintenanceOPEvictionRDMA := requestor.MaintenanceOPEvictionRDMA
path: main.go
user: login: heyvister1
body: API is expecting a string reference
created_at: 2025-04-08T11:52:14Z
author_association: COLLABORATOR
diff_hunk: @@ -435,3 +423,23 @@ rules:
   - patch
   - update
   - watch
+{{- if .Values.maintenanceOperator.enabled }}
path: deployment/network-operator/templates/role.yaml
user: login: rollandf
body: This is the first time we have a condition in the role.yaml.
Is it necessary?
created_at: 2025-04-09T05:52:22Z
author_association: MEMBER
diff_hunk: @@ -245,5 +249,7 @@ func (r *UpgradeReconciler) SetupWithManager(mgr ctrl.Manager) error {
 		Watches(&mellanoxv1alpha1.NicClusterPolicy{}, createUpdateDeleteEnqueue).
 		Watches(&corev1.Node{}, createUpdateEnqueue, nodePredicates).
 		Watches(&appsv1.DaemonSet{}, createUpdateDeleteEnqueue, daemonSetPredicates).
+		Watches(&maintenancev1alpha1.NodeMaintenance{}, createUpdateDeleteEnqueue,
path: controllers/upgrade_controller.go
user: login: rollandf
body: Here it fails when CRD is not installed.
Need to decide on the handling on what happens when Maintenance Operator is not yet installed. 
1 The user want to use new method (will it retry to start until CRD is available?)
2 The user want to use old method (not add the watch?)

created_at: 2025-04-09T06:01:50Z
author_association: MEMBER
diff_hunk: @@ -245,5 +249,7 @@ func (r *UpgradeReconciler) SetupWithManager(mgr ctrl.Manager) error {
 		Watches(&mellanoxv1alpha1.NicClusterPolicy{}, createUpdateDeleteEnqueue).
 		Watches(&corev1.Node{}, createUpdateEnqueue, nodePredicates).
 		Watches(&appsv1.DaemonSet{}, createUpdateDeleteEnqueue, daemonSetPredicates).
+		Watches(&maintenancev1alpha1.NodeMaintenance{}, createUpdateDeleteEnqueue,
path: controllers/upgrade_controller.go
user: login: heyvister1
body: I already have a fix for it. I created a condition for adding new NodeMaintenance Watch
created_at: 2025-04-09T06:09:36Z
author_association: COLLABORATOR
diff_hunk: @@ -435,3 +423,23 @@ rules:
   - patch
   - update
   - watch
+{{- if .Values.maintenanceOperator.enabled }}
path: deployment/network-operator/templates/role.yaml
user: login: heyvister1
body: In case maintenance.nvidia.com are not applied in cluster
created_at: 2025-04-09T06:10:14Z
author_association: COLLABORATOR
diff_hunk: @@ -435,3 +423,23 @@ rules:
   - patch
   - update
   - watch
+{{- if .Values.maintenanceOperator.enabled }}
path: deployment/network-operator/templates/role.yaml
user: login: rollandf
body: It is not an issue for `role.yaml`, let's remove it.
created_at: 2025-04-09T06:14:52Z
author_association: MEMBER
diff_hunk: @@ -90,6 +90,14 @@ spec:
               value: "{{ .repository }}/{{ .image }}:{{ .version }}"
               {{- end }}
             {{- end }}
+            {{- if .Values.maintenanceOperator.enabled }}
+            - name: MAINTENANCE_OPERATOR_ENABLED
+              value: "{{ .Values.operator.maintenanceOperator.enabledRequestor }}"
+            - name: MAINTENANCE_OPERATOR_REQUESTOR_ID
+              value: {{ .Values.operator.maintenanceOperator.requestorID }}
+            - name: MAINTENANCE_OPERATOR_REQUESTOR_NAMESPACE
+              value: {{ .Values.operator.maintenanceOperator.nodeMainteNamespace }}
path: deployment/network-operator/templates/operator.yaml
user: login: almaslennikov
body: This one is still pending. You should use the `.Values.operator.maintenanceOperator.nodeMaintenanceNamespace`
created_at: 2025-04-10T07:23:16Z
author_association: COLLABORATOR
diff_hunk: @@ -90,6 +90,14 @@ spec:
               value: "{{ .repository }}/{{ .image }}:{{ .version }}"
               {{- end }}
             {{- end }}
+            {{- if .Values.maintenanceOperator.enabled }}
+            - name: MAINTENANCE_OPERATOR_ENABLED
+              value: "{{ .Values.operator.maintenanceOperator.enabledRequestor }}"
+            - name: MAINTENANCE_OPERATOR_REQUESTOR_ID
+              value: {{ .Values.operator.maintenanceOperator.requestorID }}
+            - name: MAINTENANCE_OPERATOR_REQUESTOR_NAMESPACE
+              value: {{ .Values.operator.maintenanceOperator.nodeMainteNamespace }}
path: deployment/network-operator/templates/operator.yaml
user: login: heyvister1
body: Done
created_at: 2025-04-10T12:00:37Z
author_association: COLLABORATOR

PR comments:
user: login: coveralls
created_at: 2025-03-18T14:16:52Z
body: ## Pull Request Test Coverage Report for [Build 14620012502](https://coveralls.io/builds/73349922)


### Details

* **0** of **24**   **(0.0%)**  changed or added relevant lines in **2** files are covered.
* **6** unchanged lines in **2** files lost coverage.
* Overall coverage decreased (**-0.2%**) to **59.665%**

---

|  Changes Missing Coverage | Covered Lines | Changed/Added Lines | % |
| :-----|--------------|--------|---: |
| [controllers/upgrade_controller.go](https://coveralls.io/builds/73349922/source?filename=controllers%2Fupgrade_controller.go#L198) | 0 | 12 | 0.0%
| [main.go](https://coveralls.io/builds/73349922/source?filename=main.go#L68) | 0 | 12 | 0.0%
<!-- | **Total:** | **0** | **24** | **0.0%** | -->

|  Files with Coverage Reduction | New Missed Lines | % |
| :-----|--------------|--: |
| [controllers/nicclusterpolicy_controller.go](https://coveralls.io/builds/73349922/source?filename=controllers%2Fnicclusterpolicy_controller.go#L190) | 1 | 74.9% |
| [controllers/ipoibnetwork_controller.go](https://coveralls.io/builds/73349922/source?filename=controllers%2Fipoibnetwork_controller.go#L88) | 5 | 77.38% |
<!-- | **Total:** | **6** |  | -->

|  Totals | [![Coverage Status](https://coveralls.io/builds/73349922/badge)](https://coveralls.io/builds/73349922) |
| :-- | --: |
| Change from base [Build 14617588811](https://coveralls.io/builds/73347793): |  -0.2% |
| Covered Lines: | 3494 |
| Relevant Lines: | 5856 |

---
##### 💛  - [Coveralls](https://coveralls.io)

author_association: COLLABORATOR
user: login: heyvister1
created_at: 2025-04-06T12:50:09Z
body: /retest-all
author_association: COLLABORATOR
user: login: almaslennikov
created_at: 2025-04-08T06:58:02Z
body: /retest-nic_operator_helm
author_association: COLLABORATOR
user: login: heyvister1
created_at: 2025-04-08T10:04:37Z
body: /retest-nic_operator_helm


author_association: COLLABORATOR
user: login: rollandf
created_at: 2025-04-09T05:49:50Z
body: Seems to be an issue in case the Maintenance Operator is not installed:

```
2025-04-08T14:23:09Z	ERROR	controller-runtime.source.EventHandler	if kind is a CRD, it should be installed before calling Start	{"kind": "NodeMaintenance.maintenance.nvidia.com", "error": "no matches for kind \"NodeMaintenance\" in version \"maintenance.nvidia.com/v1alpha1\""}
sigs.k8s.io/controller-runtime/pkg/internal/source.(*Kind[...]).Start.func1.1
	/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.20.4/pkg/internal/source/kind.go:71
k8s.io/apimachinery/pkg/util/wait.loopConditionUntilContext.func2
	/go/pkg/mod/k8s.io/apimachinery@v0.32.2/pkg/util/wait/loop.go:87
k8s.io/apimachinery/pkg/util/wait.loopConditionUntilContext
	/go/pkg/mod/k8s.io/apimachinery@v0.32.2/pkg/util/wait/loop.go:88
k8s.io/apimachinery/pkg/util/wait.PollUntilContextCancel
	/go/pkg/mod/k8s.io/apimachinery@v0.32.2/pkg/util/wait/poll.go:33
sigs.k8s.io/controller-runtime/pkg/internal/source.(*Kind[...]).Start.func1
	/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.20.4/pkg/internal/source/kind.go:64
2025-04-08T14:23:19Z	ERROR	controller-runtime.source.EventHandler	if kind is a CRD, it should be installed before calling Start	{"kind": "NodeMaintenance.maintenance.nvidia.com", "error": "no matches for kind \"NodeMaintenance\" in version 
```
author_association: MEMBER
user: login: heyvister1
created_at: 2025-04-09T07:57:59Z
body: /retest-nic_operator_kind
author_association: COLLABORATOR