130 lines
3.5 KiB
Go
130 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/golang/glog"
|
|
"github.com/kubernetes-incubator/external-storage/lib/controller"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/util/wait"
|
|
"k8s.io/client-go/kubernetes"
|
|
"k8s.io/client-go/pkg/api/v1"
|
|
"k8s.io/client-go/rest"
|
|
)
|
|
|
|
const (
|
|
provisionerNameKey = "PROVISIONER_NAME"
|
|
)
|
|
|
|
type nfsProvisioner struct {
|
|
client kubernetes.Interface
|
|
server string
|
|
path string
|
|
}
|
|
|
|
const (
|
|
mountPath = "/persistentvolumes"
|
|
)
|
|
|
|
var _ controller.Provisioner = &nfsProvisioner{}
|
|
|
|
func (p *nfsProvisioner) Provision(options controller.VolumeOptions) (*v1.PersistentVolume, error) {
|
|
if options.PVC.Spec.Selector != nil {
|
|
return nil, fmt.Errorf("claim Selector is not supported")
|
|
}
|
|
glog.V(4).Infof("nfs provisioner: VolumeOptions %v", options)
|
|
|
|
pvcNamespace := options.PVC.Namespace
|
|
pvcName := options.PVC.Name
|
|
|
|
pvName := strings.Join([]string{pvcNamespace, pvcName, options.PVName}, "-")
|
|
|
|
fullPath := filepath.Join(mountPath, pvName)
|
|
glog.V(4).Infof("creating path %s", fullPath)
|
|
if err := os.MkdirAll(fullPath, 0777); err != nil {
|
|
return nil, errors.New("unable to create directory to provision new pv: " + err.Error())
|
|
}
|
|
|
|
path := filepath.Join(p.path, pvName)
|
|
|
|
pv := &v1.PersistentVolume{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: pvName,
|
|
},
|
|
Spec: v1.PersistentVolumeSpec{
|
|
PersistentVolumeReclaimPolicy: options.PersistentVolumeReclaimPolicy,
|
|
AccessModes: options.PVC.Spec.AccessModes,
|
|
Capacity: v1.ResourceList{
|
|
v1.ResourceName(v1.ResourceStorage): options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)],
|
|
},
|
|
PersistentVolumeSource: v1.PersistentVolumeSource{
|
|
NFS: &v1.NFSVolumeSource{
|
|
Server: p.server,
|
|
Path: path,
|
|
ReadOnly: false,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
return pv, nil
|
|
}
|
|
|
|
func (p *nfsProvisioner) Delete(volume *v1.PersistentVolume) error {
|
|
path := volume.Spec.PersistentVolumeSource.NFS.Path
|
|
pvName := filepath.Base(path)
|
|
oldPath := filepath.Join(mountPath, pvName)
|
|
archivePath := filepath.Join(mountPath, "archieved-"+pvName)
|
|
glog.V(4).Infof("archiving path %s to %s", oldPath, archivePath)
|
|
return os.Rename(oldPath, archivePath)
|
|
}
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
flag.Set("logtostderr", "true")
|
|
|
|
server := os.Getenv("NFS_SERVER")
|
|
if server == "" {
|
|
glog.Fatal("NFS_SERVER not set")
|
|
}
|
|
path := os.Getenv("NFS_PATH")
|
|
if path == "" {
|
|
glog.Fatal("NFS_PATH not set")
|
|
}
|
|
provisionerName := os.Getenv(provisionerNameKey)
|
|
if provisionerName == "" {
|
|
glog.Fatalf("environment variable %s is not set! Please set it.", provisionerNameKey)
|
|
}
|
|
|
|
// Create an InClusterConfig and use it to create a client for the controller
|
|
// to use to communicate with Kubernetes
|
|
config, err := rest.InClusterConfig()
|
|
if err != nil {
|
|
glog.Fatalf("Failed to create config: %v", err)
|
|
}
|
|
clientset, err := kubernetes.NewForConfig(config)
|
|
if err != nil {
|
|
glog.Fatalf("Failed to create client: %v", err)
|
|
}
|
|
|
|
// The controller needs to know what the server version is because out-of-tree
|
|
// provisioners aren't officially supported until 1.5
|
|
serverVersion, err := clientset.Discovery().ServerVersion()
|
|
if err != nil {
|
|
glog.Fatalf("Error getting server version: %v", err)
|
|
}
|
|
|
|
clientNFSProvisioner := &nfsProvisioner{
|
|
server: server,
|
|
path: path,
|
|
}
|
|
// Start the provision controller which will dynamically provision efs NFS
|
|
// PVs
|
|
pc := controller.NewProvisionController(clientset, provisionerName, clientNFSProvisioner, serverVersion.GitVersion)
|
|
pc.Run(wait.NeverStop)
|
|
}
|