Skip to content

Commit f829c85

Browse files
authored
Merge pull request #135 from Prajyot-Parab/update
NodeUpdate controller for csi-driver
2 parents 0086074 + 0a416d9 commit f829c85

File tree

9 files changed

+420
-7
lines changed

9 files changed

+420
-7
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
Copyright 2022.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package controllers
18+
19+
import (
20+
"context"
21+
"fmt"
22+
"strings"
23+
24+
"github.com/pkg/errors"
25+
corev1 "k8s.io/api/core/v1"
26+
apierrors "k8s.io/apimachinery/pkg/api/errors"
27+
"k8s.io/apimachinery/pkg/runtime"
28+
"k8s.io/klog"
29+
ctrl "sigs.k8s.io/controller-runtime"
30+
"sigs.k8s.io/controller-runtime/pkg/client"
31+
"sigs.k8s.io/ibm-powervs-block-csi-driver/pkg/cloud"
32+
)
33+
34+
// NodeUpdateReconciler reconciles a NodeUpdate object
35+
type NodeUpdateReconciler struct {
36+
Client client.Client
37+
Scheme *runtime.Scheme
38+
}
39+
40+
// Reconcile is part of the main kubernetes reconciliation loop which aims to
41+
// move the current state of the cluster closer to the desired state.
42+
//
43+
// For more details, check Reconcile and its Result here:
44+
// - https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/reconcile
45+
func (r *NodeUpdateReconciler) Reconcile(_ context.Context, req ctrl.Request) (ctrl.Result, error) {
46+
47+
// Fetch the Node instance
48+
node := corev1.Node{}
49+
err := r.Client.Get(context.Background(), req.NamespacedName, &node)
50+
if err != nil {
51+
if apierrors.IsNotFound(err) {
52+
// req object not found, could have been deleted after reconcile req.
53+
// Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
54+
// Return and don't requeue
55+
klog.Infof("%s: Node not found - do nothing", req.NamespacedName)
56+
return ctrl.Result{}, nil
57+
}
58+
// Error reading the object - requeue the req.
59+
return ctrl.Result{}, fmt.Errorf("error getting node: %v", err)
60+
}
61+
62+
// ProviderID format: ibmpowervs://<region>/<zone>/<service_instance_id>/<powervs_machine_id>
63+
if node.Spec.ProviderID != "" {
64+
klog.Infof("PROVIDER-ID: %s", node.Spec.ProviderID)
65+
data := strings.Split(node.Spec.ProviderID, "/")
66+
if len(data) != cloud.ProviderIDValidLength {
67+
return ctrl.Result{}, fmt.Errorf("invalid ProviderID format - %v, expected format - ibmpowervs://<region>/<zone>/<service_instance_id>/<powervs_machine_id>", node.Spec.ProviderID)
68+
}
69+
70+
nodeUpdateScope, err := cloud.NewNodeUpdateScope(cloud.NodeUpdateScopeParams{
71+
ServiceInstanceId: data[4],
72+
InstanceId: data[5],
73+
})
74+
75+
if err != nil {
76+
return ctrl.Result{}, errors.Errorf("failed to create nodeUpdateScope: %+v", err)
77+
}
78+
79+
instance, err := nodeUpdateScope.Cloud.GetPVMInstanceDetails(nodeUpdateScope.InstanceId)
80+
if err != nil {
81+
klog.Infof("Unable to fetch Instance Details %v", err)
82+
return ctrl.Result{}, nil
83+
}
84+
85+
if instance != nil {
86+
klog.Infof("StoragePoolAffinity: %v", *instance.StoragePoolAffinity)
87+
if *instance.StoragePoolAffinity {
88+
switch *instance.Status {
89+
case cloud.PowerVSInstanceStateSHUTOFF, cloud.PowerVSInstanceStateACTIVE:
90+
switch instance.Health.Status {
91+
case cloud.PowerVSInstanceHealthOK:
92+
err := r.getOrUpdate(nodeUpdateScope)
93+
if err != nil {
94+
klog.Infof("unable to update instance StoragePoolAffinity %v", err)
95+
return ctrl.Result{}, errors.Wrapf(err, "failed to reconcile VSI for IBMPowerVSMachine %s/%s", node.Namespace, node.Name)
96+
}
97+
default:
98+
klog.Infof("PowerVS instance - %v health not OK yet", instance.PvmInstanceID)
99+
}
100+
default:
101+
klog.Infof("PowerVS instance - %v state not ACTIVE/SHUTOFF yet", instance.PvmInstanceID)
102+
}
103+
}
104+
}
105+
}
106+
107+
return ctrl.Result{}, nil
108+
}
109+
110+
func (r *NodeUpdateReconciler) getOrUpdate(scope *cloud.NodeUpdateScope) error {
111+
if err := scope.Cloud.UpdateStoragePoolAffinity(scope.InstanceId); err != nil {
112+
return err
113+
}
114+
return nil
115+
}
116+
117+
// SetupWithManager sets up the controller with the Manager.
118+
func (r *NodeUpdateReconciler) SetupWithManager(mgr ctrl.Manager) error {
119+
return ctrl.NewControllerManagedBy(mgr).
120+
For(&corev1.Node{}).
121+
Complete(r)
122+
}

adhoc-controllers/main.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
Copyright 2022.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package main
18+
19+
import (
20+
"flag"
21+
"os"
22+
23+
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
24+
// to ensure that exec-entrypoint and run can make use of them.
25+
_ "k8s.io/client-go/plugin/pkg/client/auth"
26+
27+
"k8s.io/apimachinery/pkg/runtime"
28+
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
29+
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
30+
ctrl "sigs.k8s.io/controller-runtime"
31+
"sigs.k8s.io/controller-runtime/pkg/healthz"
32+
"sigs.k8s.io/controller-runtime/pkg/log/zap"
33+
34+
"sigs.k8s.io/ibm-powervs-block-csi-driver/adhoc-controllers/controllers"
35+
//+kubebuilder:scaffold:imports
36+
)
37+
38+
var (
39+
scheme = runtime.NewScheme()
40+
setupLog = ctrl.Log.WithName("setup")
41+
)
42+
43+
func init() {
44+
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
45+
46+
//+kubebuilder:scaffold:scheme
47+
}
48+
49+
func main() {
50+
var metricsAddr string
51+
var enableLeaderElection bool
52+
var probeAddr string
53+
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8081", "The address the metric endpoint binds to.")
54+
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8082", "The address the probe endpoint binds to.")
55+
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
56+
"Enable leader election for controller manager. "+
57+
"Enabling this will ensure there is only one active controller manager.")
58+
opts := zap.Options{
59+
Development: true,
60+
}
61+
opts.BindFlags(flag.CommandLine)
62+
flag.Parse()
63+
64+
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
65+
66+
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
67+
Scheme: scheme,
68+
MetricsBindAddress: metricsAddr,
69+
Port: 9443,
70+
HealthProbeBindAddress: probeAddr,
71+
LeaderElection: enableLeaderElection,
72+
LeaderElectionID: "15c66b50.my.domain",
73+
})
74+
if err != nil {
75+
setupLog.Error(err, "unable to start manager")
76+
os.Exit(1)
77+
}
78+
79+
if err = (&controllers.NodeUpdateReconciler{
80+
Client: mgr.GetClient(),
81+
Scheme: mgr.GetScheme(),
82+
}).SetupWithManager(mgr); err != nil {
83+
setupLog.Error(err, "unable to create controller", "controller", "NodeUpdate")
84+
os.Exit(1)
85+
}
86+
//+kubebuilder:scaffold:builder
87+
88+
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
89+
setupLog.Error(err, "unable to set up health check")
90+
os.Exit(1)
91+
}
92+
if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
93+
setupLog.Error(err, "unable to set up ready check")
94+
os.Exit(1)
95+
}
96+
97+
setupLog.Info("starting manager")
98+
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
99+
setupLog.Error(err, "problem running manager")
100+
os.Exit(1)
101+
}
102+
}

go.mod

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,28 @@ require (
1414
github.com/kubernetes-csi/csi-test v2.2.0+incompatible
1515
github.com/onsi/ginkgo v1.16.5
1616
github.com/onsi/gomega v1.18.1
17+
github.com/pkg/errors v0.9.1
1718
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e
1819
google.golang.org/grpc v1.44.0
1920
k8s.io/api v0.23.4
2021
k8s.io/apimachinery v0.23.4
2122
k8s.io/client-go v1.23.4
23+
k8s.io/klog v1.0.0
2224
k8s.io/klog/v2 v2.40.1
2325
k8s.io/kubernetes v1.23.4
2426
k8s.io/mount-utils v0.23.4
2527
k8s.io/utils v0.0.0-20211116205334-6203023598ed
28+
sigs.k8s.io/controller-runtime v0.11.1
2629
)
2730

2831
require (
32+
cloud.google.com/go v0.81.0 // indirect
33+
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
34+
github.com/Azure/go-autorest/autorest v0.11.18 // indirect
35+
github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect
36+
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
37+
github.com/Azure/go-autorest/logger v0.2.1 // indirect
38+
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
2939
github.com/PuerkitoBio/purell v1.1.1 // indirect
3040
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
3141
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
@@ -37,8 +47,10 @@ require (
3747
github.com/docker/distribution v2.7.1+incompatible // indirect
3848
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
3949
github.com/felixge/httpsnoop v1.0.1 // indirect
40-
github.com/fsnotify/fsnotify v1.4.9 // indirect
50+
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
51+
github.com/fsnotify/fsnotify v1.5.1 // indirect
4152
github.com/go-logr/logr v1.2.0 // indirect
53+
github.com/go-logr/zapr v1.2.0 // indirect
4254
github.com/go-openapi/analysis v0.21.2 // indirect
4355
github.com/go-openapi/errors v0.20.2 // indirect
4456
github.com/go-openapi/jsonpointer v0.19.5 // indirect
@@ -62,7 +74,7 @@ require (
6274
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
6375
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
6476
github.com/hashicorp/go-retryablehttp v0.7.0 // indirect
65-
github.com/imdario/mergo v0.3.5 // indirect
77+
github.com/imdario/mergo v0.3.12 // indirect
6678
github.com/inconshreveable/mousetrap v1.0.0 // indirect
6779
github.com/jmespath/go-jmespath v0.4.0 // indirect
6880
github.com/josharian/intern v1.0.0 // indirect
@@ -79,7 +91,6 @@ require (
7991
github.com/opencontainers/go-digest v1.0.0 // indirect
8092
github.com/opencontainers/runc v1.0.2 // indirect
8193
github.com/opentracing/opentracing-go v1.2.0 // indirect
82-
github.com/pkg/errors v0.9.1 // indirect
8394
github.com/prometheus/client_golang v1.11.0 // indirect
8495
github.com/prometheus/client_model v0.2.0 // indirect
8596
github.com/prometheus/common v0.28.0 // indirect
@@ -97,12 +108,16 @@ require (
97108
go.opentelemetry.io/otel/sdk/metric v0.20.0 // indirect
98109
go.opentelemetry.io/otel/trace v0.20.0 // indirect
99110
go.opentelemetry.io/proto/otlp v0.7.0 // indirect
111+
go.uber.org/atomic v1.7.0 // indirect
112+
go.uber.org/multierr v1.6.0 // indirect
113+
go.uber.org/zap v1.19.1 // indirect
100114
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
101115
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
102116
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect
103117
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
104118
golang.org/x/text v0.3.7 // indirect
105119
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
120+
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
106121
google.golang.org/appengine v1.6.7 // indirect
107122
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2 // indirect
108123
google.golang.org/protobuf v1.27.1 // indirect
@@ -111,6 +126,7 @@ require (
111126
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
112127
gopkg.in/yaml.v2 v2.4.0 // indirect
113128
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
129+
k8s.io/apiextensions-apiserver v0.23.0 // indirect
114130
k8s.io/apiserver v0.23.4 // indirect
115131
k8s.io/component-base v0.23.4 // indirect
116132
k8s.io/component-helpers v0.23.4 // indirect
@@ -120,7 +136,7 @@ require (
120136
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.27 // indirect
121137
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect
122138
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
123-
sigs.k8s.io/yaml v1.2.0 // indirect
139+
sigs.k8s.io/yaml v1.3.0 // indirect
124140
)
125141

126142
replace (

0 commit comments

Comments
 (0)