forked from projectcalico/calico
-
Notifications
You must be signed in to change notification settings - Fork 0
/
driver.go
158 lines (136 loc) · 4.97 KB
/
driver.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Copyright (c) 2022 Tigera, Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package driver
import (
"encoding/json"
"errors"
"fmt"
"net"
"os"
"strings"
csi "github.com/container-storage-interface/spec/lib/go/csi"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc"
)
const (
driverVersion string = "0.1"
configFile string = "/etc/calico/csi/nodeagent.json"
nodeagentHome string = "/var/run/nodeagent"
mountDir string = "/mount"
credsDir string = "/creds"
logLevelWarn string = "WARNING"
csiSockPath string = "/csi/csi.sock"
)
// ConfigurationOptions may be used to setup the driver.
// These are optional and most users will not depend on them and will instead use the defaults.
type ConfigurationOptions struct {
// Location on the node's filesystem where the driver will host the
// per workload directory and the credentials for the workload.
// Default: /var/run/nodeagent
NodeAgentManagementHomeDir string `json:"nodeagent_management_home,omitempty"`
// Relative location to NodeAgentManagementHomeDir where per workload directory
// will be created.
// Default: /mount
// For example: /mount here implies /var/run/nodeagent/mount/ directory
// on the node.
NodeAgentWorkloadHomeDir string `json:"nodeagent_workload_home,omitempty"`
// Relative location to NodeAgentManagementHomeDir where per workload credential
// files will be created.
// Default: /creds
// For example: /creds here implies /var/run/nodeagent/creds/ directory
NodeAgentCredentialsHomeDir string `json:"nodeagent_credentials_home,omitempty"`
// Log level for loggint to node syslog. Options: INFO|WARNING
// Default: WARNING
LogLevel string `json:"log_level,omitempty"`
// Node ID used for node service calls.
// Default: ""
NodeID string `json:"node_id,omitempty"`
// Location of the unix domain socket that the Kubelet communicates with the CSI plugin over.
// Default: /csi/csi.sock
Endpoint string `json:"endpoint,omitempty"`
}
type Driver struct {
nodeService
server *grpc.Server
options *ConfigurationOptions
}
func NewDriver(config *ConfigurationOptions) *Driver {
return &Driver{
options: config,
server: grpc.NewServer(),
nodeService: newNodeService(config),
}
}
func (d *Driver) Run() error {
// register the node server since that should be all that we need.
csi.RegisterIdentityServer(d.server, d)
csi.RegisterNodeServer(d.server, d)
// Remove any leftover socket from a previous run
if err := os.Remove(d.options.Endpoint); err != nil && !os.IsNotExist(err) {
log.Errorf("Could not remove unix domain socket %s: %v", d.options.Endpoint, err)
return err
}
// Create an http listener here to provide to the grpc server to serve.
listener, err := net.Listen("unix", d.options.Endpoint)
if err != nil {
log.Errorf("Server could not listen at %s: %v", d.options.Endpoint, err)
return err
}
log.Infof("Server listening at %v", listener.Addr())
return d.server.Serve(listener)
}
func RetrieveConfig() (*ConfigurationOptions, error) {
config := ConfigurationOptions{}
if _, err := os.Stat(configFile); err == nil {
// Read the config from the file.
bytes, err := os.ReadFile(configFile)
if err != nil {
return nil, fmt.Errorf("Unable to read configuration at %s: %v", configFile, err)
}
err = json.Unmarshal(bytes, &config)
if err != nil {
return nil, fmt.Errorf("Unable to parse configuration at %s: %v", configFile, err)
}
} else if !errors.Is(err, os.ErrNotExist) {
return nil, err
}
// Add the default values to the configuration if required.
if len(config.NodeAgentManagementHomeDir) == 0 {
config.NodeAgentManagementHomeDir = nodeagentHome
}
if len(config.NodeAgentWorkloadHomeDir) == 0 {
config.NodeAgentWorkloadHomeDir = mountDir
}
if len(config.NodeAgentCredentialsHomeDir) == 0 {
config.NodeAgentCredentialsHomeDir = credsDir
}
if len(config.LogLevel) == 0 {
config.LogLevel = logLevelWarn
}
if len(config.Endpoint) == 0 {
config.Endpoint = csiSockPath
}
// Convert to absolute paths.
var prefix string = ""
if !strings.HasPrefix(config.NodeAgentWorkloadHomeDir, "/") {
prefix = "/"
}
config.NodeAgentWorkloadHomeDir = strings.Join([]string{config.NodeAgentManagementHomeDir, config.NodeAgentWorkloadHomeDir}, prefix)
prefix = ""
if !strings.HasPrefix(config.NodeAgentCredentialsHomeDir, "/") {
prefix = "/"
}
config.NodeAgentCredentialsHomeDir = strings.Join([]string{config.NodeAgentManagementHomeDir, config.NodeAgentCredentialsHomeDir}, prefix)
return &config, nil
}