Skip to content

Commit a8915cb

Browse files
authored
Merge pull request #137 from Leaseweb/feat/split_mode
feat: Split controller and node mode, add max volumes per node flag
2 parents f86537c + f1fd6b8 commit a8915cb

File tree

19 files changed

+490
-156
lines changed

19 files changed

+490
-156
lines changed

.github/dependabot.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ updates:
4040
update-types: ["version-update:semver-minor"]
4141
- dependency-name: "k8s.io/apimachinery"
4242
update-types: ["version-update:semver-minor"]
43+
- dependency-name: "k8s.io/component-base"
44+
update-types: ["version-update:semver-minor"]
4345
- dependency-name: "k8s.io/client-go"
4446
update-types: ["version-update:semver-minor"]
4547
- dependency-name: "k8s.io/mount-utils"

.golangci.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ issues:
22
exclude-use-default: true
33
max-issues-per-linter: 50
44
max-same-issues: 0 # disable
5+
exclude-rules:
6+
- path: _test.go
7+
linters:
8+
- funlen
9+
- nestif
510

611
linters-settings:
712
gci:

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
CMDS=cloudstack-csi-driver cloudstack-csi-sc-syncer
22

3+
PKG=github.com/leaseweb/cloudstack-csi-driver
34
# Revision that gets built into each binary via the main.version
45
# string. Uses the `git describe` output based on the most recent
56
# version tag with a short revision suffix or, if nothing has been
@@ -8,10 +9,12 @@ CMDS=cloudstack-csi-driver cloudstack-csi-sc-syncer
89
# Beware that tags may also be missing in shallow clones as done by
910
# some CI systems (like TravisCI, which pulls only 50 commits).
1011
REV=$(shell git describe --long --tags --match='v*' --dirty 2>/dev/null || git rev-list -n1 HEAD)
12+
GIT_COMMIT?=$(shell git rev-parse HEAD)
13+
BUILD_DATE?=$(shell date -u -Iseconds)
1114

1215
DOCKER?=docker
1316

14-
IMPORTPATH_LDFLAGS = -X main.version=$(REV)
17+
IMPORTPATH_LDFLAGS = -X ${PKG}/pkg/driver.driverVersion=$(REV) -X ${PKG}/pkg/driver.gitCommit=${GIT_COMMIT} -X ${PKG}/pkg/driver.buildDate=${BUILD_DATE}
1518
LDFLAGS = -s -w
1619
FULL_LDFLAGS = $(LDFLAGS) $(IMPORTPATH_LDFLAGS)
1720

charts/cloudstack-csi/templates/csi-controller-deploy.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ spec:
4343
image: "{{ .Values.controller.csiDriverController.image.repository }}:{{ .Values.controller.csiDriverController.image.tag | default .Chart.AppVersion }}"
4444
imagePullPolicy: {{ .Values.controller.csiDriverController.image.pullPolicy }}
4545
args:
46+
- "controller"
4647
- "--endpoint=$(CSI_ENDPOINT)"
47-
- "--cloudstackconfig=$(CLOUD_CONFIG)"
48+
- "--cloudstack-config=$(CLOUD_CONFIG)"
4849
- "--logging-format={{ .Values.logFormat }}"
4950
- "--v={{ .Values.logVerbosityLevel }}"
5051
{{- if .Values.controller.csiDriverController.extraArgs }}

charts/cloudstack-csi/templates/csi-node-ds.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@ spec:
3131
image: "{{ .Values.node.csiDriver.image.repository }}:{{ .Values.node.csiDriver.image.tag | default .Chart.AppVersion }}"
3232
imagePullPolicy: {{ .Values.node.csiDriver.image.pullPolicy }}
3333
args:
34+
- "node"
3435
- "--endpoint=$(CSI_ENDPOINT)"
35-
- "--cloudstackconfig=$(CLOUD_CONFIG)"
36+
- "--cloudstack-config=$(CLOUD_CONFIG)"
3637
- "--logging-format={{ .Values.logFormat }}"
37-
- "--nodeName=$(NODE_NAME)"
38+
- "--node-name=$(NODE_NAME)"
3839
- "--v={{ .Values.logVerbosityLevel }}"
3940
{{- if .Values.node.csiDriver.extraArgs }}
4041
{{- with .Values.node.csiDriver.extraArgs }}

cmd/cloudstack-csi-driver/main.go

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ package main
77

88
import (
99
"context"
10-
"flag"
1110
"fmt"
1211
"os"
13-
"path"
12+
"strings"
1413

14+
flag "github.com/spf13/pflag"
1515
"k8s.io/component-base/featuregate"
1616
"k8s.io/component-base/logs"
1717
logsapi "k8s.io/component-base/logs/api/v1"
@@ -22,30 +22,51 @@ import (
2222
"github.com/leaseweb/cloudstack-csi-driver/pkg/driver"
2323
)
2424

25-
var (
26-
endpoint = flag.String("endpoint", "unix:///tmp/csi.sock", "CSI endpoint")
27-
cloudstackconfig = flag.String("cloudstackconfig", "./cloud-config", "CloudStack configuration file")
28-
nodeName = flag.String("nodeName", "", "Node name")
29-
showVersion = flag.Bool("version", false, "Show version")
30-
31-
// Version is set by the build process.
32-
version = ""
33-
)
34-
3525
func main() {
26+
fs := flag.NewFlagSet("cloudstack-csi-driver", flag.ExitOnError)
3627
if err := logsapi.RegisterLogFormat(logsapi.JSONLogFormat, json.Factory{}, logsapi.LoggingBetaOptions); err != nil {
3728
klog.ErrorS(err, "failed to register JSON log format")
3829
}
3930

31+
var (
32+
showVersion = fs.Bool("version", false, "Show version")
33+
args = os.Args[1:]
34+
cmd = string(driver.AllMode)
35+
options = driver.Options{}
36+
)
4037
fg := featuregate.NewFeatureGate()
4138
err := logsapi.AddFeatureGates(fg)
4239
if err != nil {
4340
klog.ErrorS(err, "failed to add feature gates")
4441
}
4542

4643
c := logsapi.NewLoggingConfiguration()
47-
logsapi.AddGoFlags(c, flag.CommandLine)
48-
flag.Parse()
44+
logsapi.AddFlags(c, fs)
45+
46+
if len(os.Args) > 1 && !strings.HasPrefix(os.Args[1], "-") {
47+
cmd = os.Args[1]
48+
args = os.Args[2:]
49+
}
50+
51+
switch cmd {
52+
case string(driver.ControllerMode), string(driver.NodeMode), string(driver.AllMode):
53+
options.Mode = driver.Mode(cmd)
54+
default:
55+
klog.Errorf("Unknown driver mode %s: Expected %s, %s, or %s", cmd, driver.ControllerMode, driver.NodeMode, driver.AllMode)
56+
klog.FlushAndExit(klog.ExitFlushTimeout, 0)
57+
}
58+
59+
options.AddFlags(fs)
60+
61+
if err = fs.Parse(args); err != nil {
62+
klog.ErrorS(err, "Failed to parse options")
63+
klog.FlushAndExit(klog.ExitFlushTimeout, 0)
64+
}
65+
if err = options.Validate(); err != nil {
66+
klog.ErrorS(err, "Invalid options")
67+
klog.FlushAndExit(klog.ExitFlushTimeout, 0)
68+
}
69+
4970
logs.InitLogs()
5071
logger := klog.Background()
5172
if err = logsapi.ValidateAndApply(c, fg); err != nil {
@@ -54,23 +75,27 @@ func main() {
5475
}
5576

5677
if *showVersion {
57-
baseName := path.Base(os.Args[0])
58-
fmt.Println(baseName, version) //nolint:forbidigo
78+
versionInfo, versionErr := driver.GetVersionJSON()
79+
if versionErr != nil {
80+
logger.Error(err, "failed to get version")
81+
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
82+
}
83+
fmt.Println(versionInfo) //nolint:forbidigo
5984
os.Exit(0)
6085
}
6186

6287
// Setup cloud connector.
63-
config, err := cloud.ReadConfig(*cloudstackconfig)
88+
config, err := cloud.ReadConfig(options.CloudStackConfig)
6489
if err != nil {
6590
logger.Error(err, "Cannot read CloudStack configuration")
6691
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
6792
}
68-
logger.Info("Successfully read CloudStack configuration", "cloudstackconfig", *cloudstackconfig)
93+
logger.Info("Successfully read CloudStack configuration", "cloudstackconfig", options.CloudStackConfig)
6994

7095
ctx := klog.NewContext(context.Background(), logger)
7196
csConnector := cloud.New(config)
7297

73-
d, err := driver.New(*endpoint, csConnector, nil, *nodeName, version)
98+
d, err := driver.New(ctx, csConnector, &options, nil)
7499
if err != nil {
75100
logger.Error(err, "Failed to initialize driver")
76101
klog.FlushAndExit(klog.ExitFlushTimeout, 1)

deploy/k8s/controller-deployment.yaml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,11 @@ spec:
3737
image: cloudstack-csi-driver
3838
imagePullPolicy: Always
3939
args:
40-
- "-endpoint=$(CSI_ENDPOINT)"
41-
- "-cloudstackconfig=/etc/cloudstack-csi-driver/cloud-config"
42-
- "-logging-format=text"
43-
- "-v=4"
40+
- "controller"
41+
- "--endpoint=$(CSI_ENDPOINT)"
42+
- "--cloudstack-config=/etc/cloudstack-csi-driver/cloud-config"
43+
- "--logging-format=text"
44+
- "--v=4"
4445
env:
4546
- name: CSI_ENDPOINT
4647
value: unix:///var/lib/csi/sockets/pluginproxy/csi.sock

deploy/k8s/node-daemonset.yaml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ spec:
2929
image: cloudstack-csi-driver
3030
imagePullPolicy: Always
3131
args:
32-
- "-endpoint=$(CSI_ENDPOINT)"
33-
- "-cloudstackconfig=/etc/cloudstack-csi-driver/cloud-config"
34-
- "-logging-format=text"
35-
- "-nodeName=$(NODE_NAME)"
36-
- "-v=4"
32+
- "node"
33+
- "--endpoint=$(CSI_ENDPOINT)"
34+
- "--cloudstack-config=/etc/cloudstack-csi-driver/cloud-config"
35+
- "--logging-format=text"
36+
- "--node-name=$(NODE_NAME)"
37+
- "--v=4"
3738
env:
3839
- name: CSI_ENDPOINT
3940
value: unix:///csi/csi.sock

pkg/driver/constants.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,38 @@ package driver
33
// DriverName is the name of the CSI plugin.
44
const DriverName = "csi.cloudstack.apache.org"
55

6+
// Mode is the operating mode of the CSI driver.
7+
type Mode string
8+
9+
// Driver operating modes.
10+
const (
11+
// ControllerMode is the mode that only starts the controller service.
12+
ControllerMode Mode = "controller"
13+
// NodeMode is the mode that only starts the node service.
14+
NodeMode Mode = "node"
15+
// AllMode is the mode that only starts both the controller and the node service.
16+
AllMode Mode = "all"
17+
)
18+
19+
// constants for default command line flag values.
20+
const (
21+
// DefaultCSIEndpoint is the default CSI endpoint for the driver.
22+
DefaultCSIEndpoint = "unix://tmp/csi.sock"
23+
DefaultMaxVolAttachLimit int64 = 256
24+
)
25+
26+
// Filesystem types.
27+
const (
28+
// FSTypeExt2 represents the ext2 filesystem type.
29+
FSTypeExt2 = "ext2"
30+
// FSTypeExt3 represents the ext3 filesystem type.
31+
FSTypeExt3 = "ext3"
32+
// FSTypeExt4 represents the ext4 filesystem type.
33+
FSTypeExt4 = "ext4"
34+
// FSTypeXfs represents the xfs filesystem type.
35+
FSTypeXfs = "xfs"
36+
)
37+
638
// Topology keys.
739
const (
840
ZoneKey = "topology." + DriverName + "/zone"

pkg/driver/driver.go

Lines changed: 82 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,16 @@ package driver
55

66
import (
77
"context"
8+
"fmt"
9+
"net"
10+
11+
"github.com/container-storage-interface/spec/lib/go/csi"
12+
"google.golang.org/grpc"
13+
"k8s.io/klog/v2"
814

915
"github.com/leaseweb/cloudstack-csi-driver/pkg/cloud"
1016
"github.com/leaseweb/cloudstack-csi-driver/pkg/mount"
17+
"github.com/leaseweb/cloudstack-csi-driver/pkg/util"
1118
)
1219

1320
// Interface is the CloudStack CSI driver interface.
@@ -17,29 +24,86 @@ type Interface interface {
1724
}
1825

1926
type cloudstackDriver struct {
20-
endpoint string
21-
nodeName string
22-
version string
23-
24-
connector cloud.Interface
25-
mounter mount.Interface
27+
controller csi.ControllerServer
28+
node csi.NodeServer
29+
options *Options
2630
}
2731

2832
// New instantiates a new CloudStack CSI driver.
29-
func New(endpoint string, csConnector cloud.Interface, mounter mount.Interface, nodeName string, version string) (Interface, error) {
30-
return &cloudstackDriver{
31-
endpoint: endpoint,
32-
nodeName: nodeName,
33-
version: version,
34-
connector: csConnector,
35-
mounter: mounter,
36-
}, nil
33+
func New(ctx context.Context, csConnector cloud.Interface, options *Options, mounter mount.Interface) (Interface, error) {
34+
logger := klog.FromContext(ctx)
35+
logger.Info("Driver starting", "Driver", DriverName, "Version", driverVersion)
36+
37+
if err := validateMode(options.Mode); err != nil {
38+
return nil, fmt.Errorf("invalid driver options: %w", err)
39+
}
40+
41+
driver := &cloudstackDriver{
42+
options: options,
43+
}
44+
45+
switch options.Mode {
46+
case ControllerMode:
47+
driver.controller = NewControllerServer(csConnector)
48+
case NodeMode:
49+
driver.node = NewNodeServer(csConnector, mounter, options)
50+
case AllMode:
51+
driver.controller = NewControllerServer(csConnector)
52+
driver.node = NewNodeServer(csConnector, mounter, options)
53+
default:
54+
return nil, fmt.Errorf("unknown mode: %s", options.Mode)
55+
}
56+
57+
return driver, nil
3758
}
3859

3960
func (cs *cloudstackDriver) Run(ctx context.Context) error {
40-
ids := NewIdentityServer(cs.version)
41-
ctrls := NewControllerServer(cs.connector)
42-
ns := NewNodeServer(cs.connector, cs.mounter, cs.nodeName)
61+
logger := klog.FromContext(ctx)
62+
scheme, addr, err := util.ParseEndpoint(cs.options.Endpoint)
63+
if err != nil {
64+
return err
65+
}
66+
67+
listener, err := net.Listen(scheme, addr)
68+
if err != nil {
69+
return fmt.Errorf("failed to listen: %w", err)
70+
}
71+
72+
// Log every request and payloads (request + response)
73+
opts := []grpc.ServerOption{
74+
grpc.UnaryInterceptor(func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
75+
resp, err := handler(klog.NewContext(ctx, logger), req)
76+
if err != nil {
77+
logger.Error(err, "GRPC method failed", "method", info.FullMethod)
78+
}
79+
80+
return resp, err
81+
}),
82+
}
83+
grpcServer := grpc.NewServer(opts...)
84+
85+
csi.RegisterIdentityServer(grpcServer, cs)
86+
switch cs.options.Mode {
87+
case ControllerMode:
88+
csi.RegisterControllerServer(grpcServer, cs.controller)
89+
case NodeMode:
90+
csi.RegisterNodeServer(grpcServer, cs.node)
91+
case AllMode:
92+
csi.RegisterControllerServer(grpcServer, cs.controller)
93+
csi.RegisterNodeServer(grpcServer, cs.node)
94+
default:
95+
return fmt.Errorf("unknown mode: %s", cs.options.Mode)
96+
}
97+
98+
logger.Info("Listening for connections", "address", listener.Addr())
99+
100+
return grpcServer.Serve(listener)
101+
}
102+
103+
func validateMode(mode Mode) error {
104+
if mode != AllMode && mode != ControllerMode && mode != NodeMode {
105+
return fmt.Errorf("mode is not supported (actual: %s, supported: %v)", mode, []Mode{AllMode, ControllerMode, NodeMode})
106+
}
43107

44-
return cs.serve(ctx, ids, ctrls, ns)
108+
return nil
45109
}

0 commit comments

Comments
 (0)