Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
L
Local Path Provisioner
Manage
Activity
Members
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Model registry
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Mirror
Local Path Provisioner
Commits
58fe87e7
Commit
58fe87e7
authored
Oct 2, 2018
by
Sheng Yang
Browse files
Options
Downloads
Patches
Plain Diff
Add NodePathMap for configuration
parent
451ce50e
No related branches found
No related tags found
No related merge requests found
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
deploy/example-configmap.yaml
+24
-0
24 additions, 0 deletions
deploy/example-configmap.yaml
deploy/provisioner.yaml
+10
-1
10 additions, 1 deletion
deploy/provisioner.yaml
main.go
+12
-2
12 additions, 2 deletions
main.go
provisioner.go
+115
-12
115 additions, 12 deletions
provisioner.go
with
161 additions
and
15 deletions
deploy/example-configmap.yaml
0 → 100644
+
24
−
0
View file @
58fe87e7
kind
:
ConfigMap
apiVersion
:
v1
metadata
:
name
:
local-path-config
namespace
:
default
data
:
config.json
:
|-
{
"nodePathMap":[
{
"node":"yasker-lp-dev1",
"paths":["/opt", "/data1"]
},
{
"node":"yasker-lp-dev2",
"paths":["/opt"]
},
{
"node":"yasker-lp-dev3",
"paths":["/data3"]
}
]
}
This diff is collapsed.
Click to expand it.
deploy/provisioner.yaml
+
10
−
1
View file @
58fe87e7
...
@@ -52,6 +52,7 @@ spec:
...
@@ -52,6 +52,7 @@ spec:
labels
:
labels
:
app
:
local-path-provisioner
app
:
local-path-provisioner
spec
:
spec
:
serviceAccountName
:
local-path-provisioner-service-account
containers
:
containers
:
-
name
:
local-path-provisioner
-
name
:
local-path-provisioner
image
:
yasker/local-path-provisioner:63df7c1
image
:
yasker/local-path-provisioner:63df7c1
...
@@ -60,4 +61,12 @@ spec:
...
@@ -60,4 +61,12 @@ spec:
-
local-path-provisioner
-
local-path-provisioner
-
--debug
-
--debug
-
start
-
start
serviceAccountName
:
local-path-provisioner-service-account
-
--config
-
/etc/config/config.json
volumeMounts
:
-
name
:
config-volume
mountPath
:
/etc/config/
volumes
:
-
name
:
config-volume
configMap
:
name
:
local-path-config
This diff is collapsed.
Click to expand it.
main.go
+
12
−
2
View file @
58fe87e7
...
@@ -22,6 +22,7 @@ var (
...
@@ -22,6 +22,7 @@ var (
FlagProvisionerName
=
"provisioner-name"
FlagProvisionerName
=
"provisioner-name"
EnvProvisionerName
=
"PROVISIONER_NAME"
EnvProvisionerName
=
"PROVISIONER_NAME"
FlagConfigFile
=
"config"
)
)
func
cmdNotFound
(
c
*
cli
.
Context
,
command
string
)
{
func
cmdNotFound
(
c
*
cli
.
Context
,
command
string
)
{
...
@@ -48,10 +49,15 @@ func StartCmd() cli.Command {
...
@@ -48,10 +49,15 @@ func StartCmd() cli.Command {
Flags
:
[]
cli
.
Flag
{
Flags
:
[]
cli
.
Flag
{
cli
.
StringFlag
{
cli
.
StringFlag
{
Name
:
FlagProvisionerName
,
Name
:
FlagProvisionerName
,
Usage
:
"Specify provisioner name"
,
Usage
:
"
Optional.
Specify provisioner name
.
"
,
EnvVar
:
EnvProvisionerName
,
EnvVar
:
EnvProvisionerName
,
Value
:
DefaultProvisionerName
,
Value
:
DefaultProvisionerName
,
},
},
cli
.
StringFlag
{
Name
:
FlagConfigFile
,
Usage
:
"Required. Provisioner configuration file."
,
Value
:
""
,
},
},
},
Action
:
func
(
c
*
cli
.
Context
)
{
Action
:
func
(
c
*
cli
.
Context
)
{
if
err
:=
startDaemon
(
c
);
err
!=
nil
{
if
err
:=
startDaemon
(
c
);
err
!=
nil
{
...
@@ -84,7 +90,11 @@ func startDaemon(c *cli.Context) error {
...
@@ -84,7 +90,11 @@ func startDaemon(c *cli.Context) error {
if
provisionerName
==
""
{
if
provisionerName
==
""
{
return
fmt
.
Errorf
(
"invalid empty provisioner name"
)
return
fmt
.
Errorf
(
"invalid empty provisioner name"
)
}
}
provisioner
:=
NewProvisioner
(
kubeClient
)
configFile
:=
c
.
String
(
FlagConfigFile
)
provisioner
,
err
:=
NewProvisioner
(
kubeClient
,
configFile
)
if
err
!=
nil
{
return
err
}
pc
:=
pvController
.
NewProvisionController
(
pc
:=
pvController
.
NewProvisionController
(
kubeClient
,
kubeClient
,
provisionerName
,
provisionerName
,
...
...
This diff is collapsed.
Click to expand it.
provisioner.go
+
115
−
12
View file @
58fe87e7
package
main
package
main
import
(
import
(
"encoding/json"
"fmt"
"fmt"
"os"
"path/filepath"
"path/filepath"
"time"
"time"
...
@@ -19,18 +21,55 @@ const (
...
@@ -19,18 +21,55 @@ const (
)
)
var
(
var
(
DefaultPath
=
"/opt"
CleanupTimeoutCounts
=
120
CleanupCounts
=
120
)
)
type
LocalPathProvisioner
struct
{
type
LocalPathProvisioner
struct
{
kubeClient
*
clientset
.
Clientset
kubeClient
*
clientset
.
Clientset
configFile
string
}
}
func
NewProvisioner
(
kubeClient
*
clientset
.
Clientset
)
*
LocalPathProvisioner
{
type
NodePathMapData
struct
{
Node
string
`json:"node,omitempty"`
Paths
[]
string
`json:"paths,omitempty"`
}
type
ConfigData
struct
{
NodePathMap
[]
*
NodePathMapData
`json:"nodePathMap,omitempty"`
}
type
NodePathMap
struct
{
Paths
map
[
string
]
struct
{}
}
type
Config
struct
{
NodePathMap
map
[
string
]
*
NodePathMap
}
func
(
c
*
Config
)
getRandomPathOnNode
(
node
string
)
(
string
,
error
)
{
npMap
:=
c
.
NodePathMap
[
node
]
if
npMap
==
nil
{
return
""
,
fmt
.
Errorf
(
"config doesn't contain node %v"
,
node
)
}
paths
:=
npMap
.
Paths
if
len
(
paths
)
==
0
{
return
""
,
fmt
.
Errorf
(
"no local path available on node %v"
,
node
)
}
path
:=
""
for
path
=
range
paths
{
break
}
return
path
,
nil
}
func
NewProvisioner
(
kubeClient
*
clientset
.
Clientset
,
configFile
string
)
(
*
LocalPathProvisioner
,
error
)
{
if
_
,
err
:=
getConfig
(
configFile
);
err
!=
nil
{
return
nil
,
errors
.
Wrapf
(
err
,
"invalidate config file %v"
,
configFile
)
}
return
&
LocalPathProvisioner
{
return
&
LocalPathProvisioner
{
kubeClient
:
kubeClient
,
kubeClient
:
kubeClient
,
}
configFile
:
configFile
,
},
nil
}
}
func
(
p
*
LocalPathProvisioner
)
Provision
(
opts
pvController
.
VolumeOptions
)
(
*
v1
.
PersistentVolume
,
error
)
{
func
(
p
*
LocalPathProvisioner
)
Provision
(
opts
pvController
.
VolumeOptions
)
(
*
v1
.
PersistentVolume
,
error
)
{
...
@@ -47,10 +86,20 @@ func (p *LocalPathProvisioner) Provision(opts pvController.VolumeOptions) (*v1.P
...
@@ -47,10 +86,20 @@ func (p *LocalPathProvisioner) Provision(opts pvController.VolumeOptions) (*v1.P
if
opts
.
SelectedNode
==
nil
{
if
opts
.
SelectedNode
==
nil
{
return
nil
,
fmt
.
Errorf
(
"configuration error, no node was specified"
)
return
nil
,
fmt
.
Errorf
(
"configuration error, no node was specified"
)
}
}
cfg
,
err
:=
getConfig
(
p
.
configFile
)
if
err
!=
nil
{
return
nil
,
err
}
basePath
,
err
:=
cfg
.
getRandomPathOnNode
(
node
.
Name
)
if
err
!=
nil
{
return
nil
,
err
}
name
:=
opts
.
PVName
name
:=
opts
.
PVName
path
:=
filepath
.
Join
(
Default
Path
,
name
)
path
:=
filepath
.
Join
(
base
Path
,
name
)
logrus
.
Infof
(
"Created volume %v
"
,
name
)
logrus
.
Infof
(
"Created volume %v
at %v:%v"
,
name
,
node
.
Name
,
path
)
fs
:=
v1
.
PersistentVolumeFilesystem
fs
:=
v1
.
PersistentVolumeFilesystem
hostPathType
:=
v1
.
HostPathDirectoryOrCreate
hostPathType
:=
v1
.
HostPathDirectoryOrCreate
...
@@ -159,9 +208,12 @@ func (p *LocalPathProvisioner) cleanupVolume(name, path, node string) (err error
...
@@ -159,9 +208,12 @@ func (p *LocalPathProvisioner) cleanupVolume(name, path, node string) (err error
if
name
==
""
||
path
==
""
||
node
==
""
{
if
name
==
""
||
path
==
""
||
node
==
""
{
return
fmt
.
Errorf
(
"invalid empty name or path or node"
)
return
fmt
.
Errorf
(
"invalid empty name or path or node"
)
}
}
//TODO match up with node prefixes, make sure it's one of them (and not `/`)
path
,
err
=
filepath
.
Abs
(
path
)
if
filepath
.
Clean
(
path
)
==
"/"
{
if
err
!=
nil
{
return
fmt
.
Errorf
(
"not sure why you want to DESTROY the root directory"
)
return
err
}
if
path
==
"/"
{
return
fmt
.
Errorf
(
"not sure why you want to DESTROY THE ROOT DIRECTORY"
)
}
}
hostPathType
:=
v1
.
HostPathDirectoryOrCreate
hostPathType
:=
v1
.
HostPathDirectoryOrCreate
cleanupPod
:=
&
v1
.
Pod
{
cleanupPod
:=
&
v1
.
Pod
{
...
@@ -170,6 +222,7 @@ func (p *LocalPathProvisioner) cleanupVolume(name, path, node string) (err error
...
@@ -170,6 +222,7 @@ func (p *LocalPathProvisioner) cleanupVolume(name, path, node string) (err error
},
},
Spec
:
v1
.
PodSpec
{
Spec
:
v1
.
PodSpec
{
RestartPolicy
:
v1
.
RestartPolicyNever
,
RestartPolicy
:
v1
.
RestartPolicyNever
,
NodeName
:
node
,
Containers
:
[]
v1
.
Container
{
Containers
:
[]
v1
.
Container
{
{
{
Name
:
"local-path-cleanup"
,
Name
:
"local-path-cleanup"
,
...
@@ -213,7 +266,7 @@ func (p *LocalPathProvisioner) cleanupVolume(name, path, node string) (err error
...
@@ -213,7 +266,7 @@ func (p *LocalPathProvisioner) cleanupVolume(name, path, node string) (err error
}()
}()
completed
:=
false
completed
:=
false
for
i
:=
0
;
i
<
CleanupCounts
;
i
++
{
for
i
:=
0
;
i
<
Cleanup
Timeout
Counts
;
i
++
{
if
pod
,
err
:=
p
.
kubeClient
.
CoreV1
()
.
Pods
(
namespace
)
.
Get
(
pod
.
Name
,
metav1
.
GetOptions
{});
err
!=
nil
{
if
pod
,
err
:=
p
.
kubeClient
.
CoreV1
()
.
Pods
(
namespace
)
.
Get
(
pod
.
Name
,
metav1
.
GetOptions
{});
err
!=
nil
{
return
err
return
err
}
else
if
pod
.
Status
.
Phase
==
v1
.
PodSucceeded
{
}
else
if
pod
.
Status
.
Phase
==
v1
.
PodSucceeded
{
...
@@ -223,9 +276,59 @@ func (p *LocalPathProvisioner) cleanupVolume(name, path, node string) (err error
...
@@ -223,9 +276,59 @@ func (p *LocalPathProvisioner) cleanupVolume(name, path, node string) (err error
time
.
Sleep
(
1
*
time
.
Second
)
time
.
Sleep
(
1
*
time
.
Second
)
}
}
if
!
completed
{
if
!
completed
{
return
fmt
.
Errorf
(
"cleanup process timeout after %v seconds"
,
CleanupCounts
)
return
fmt
.
Errorf
(
"cleanup process timeout after %v seconds"
,
Cleanup
Timeout
Counts
)
}
}
logrus
.
Infof
(
"Volume %v has been cleaned up
"
,
name
)
logrus
.
Infof
(
"Volume %v has been cleaned up
from %v:%v"
,
name
,
node
,
path
)
return
nil
return
nil
}
}
func
getConfig
(
configFile
string
)
(
cfg
*
Config
,
err
error
)
{
defer
func
()
{
err
=
errors
.
Wrapf
(
err
,
"fail to load config file %v"
,
configFile
)
}()
f
,
err
:=
os
.
Open
(
configFile
)
if
err
!=
nil
{
return
nil
,
err
}
defer
f
.
Close
()
var
data
ConfigData
if
err
:=
json
.
NewDecoder
(
f
)
.
Decode
(
&
data
);
err
!=
nil
{
return
nil
,
err
}
cfg
,
err
=
canonicalizeConfig
(
&
data
)
if
err
!=
nil
{
return
nil
,
err
}
return
cfg
,
nil
}
func
canonicalizeConfig
(
data
*
ConfigData
)
(
cfg
*
Config
,
err
error
)
{
defer
func
()
{
err
=
errors
.
Wrapf
(
err
,
"config canonicalization failed"
)
}()
cfg
=
&
Config
{}
cfg
.
NodePathMap
=
map
[
string
]
*
NodePathMap
{}
for
_
,
n
:=
range
data
.
NodePathMap
{
if
cfg
.
NodePathMap
[
n
.
Node
]
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"duplicate node %v"
,
n
.
Node
)
}
npMap
:=
&
NodePathMap
{
Paths
:
map
[
string
]
struct
{}{}}
cfg
.
NodePathMap
[
n
.
Node
]
=
npMap
for
_
,
p
:=
range
n
.
Paths
{
if
p
[
0
]
!=
'/'
{
return
nil
,
fmt
.
Errorf
(
"path must start with / for path %v on node %v"
,
p
,
n
.
Node
)
}
path
,
err
:=
filepath
.
Abs
(
p
)
if
err
!=
nil
{
return
nil
,
err
}
if
_
,
ok
:=
npMap
.
Paths
[
path
];
ok
{
return
nil
,
fmt
.
Errorf
(
"duplicate path %v on node %v"
,
p
,
n
.
Node
)
}
npMap
.
Paths
[
path
]
=
struct
{}{}
}
}
return
cfg
,
nil
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment