Fresh dep ensure

This commit is contained in:
Mike Cronce
2018-11-26 13:23:56 -05:00
parent 93cb8a04d7
commit 407478ab9a
9016 changed files with 551394 additions and 279685 deletions

View File

@ -18,7 +18,12 @@ package hostpath
import (
"fmt"
"math"
"os"
"sort"
"strconv"
"github.com/golang/protobuf/ptypes"
"github.com/golang/glog"
"github.com/pborman/uuid"
@ -26,13 +31,15 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/container-storage-interface/spec/lib/go/csi/v0"
"github.com/container-storage-interface/spec/lib/go/csi"
"github.com/kubernetes-csi/drivers/pkg/csi-common"
utilexec "k8s.io/utils/exec"
)
const (
deviceID = "deviceID"
provisionRoot = "/tmp/"
snapshotRoot = "/tmp/"
maxStorageCapacity = tib
)
@ -64,9 +71,9 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
// TODO (sbezverk) Do I need to make sure that RBD volume still exists?
return &csi.CreateVolumeResponse{
Volume: &csi.Volume{
Id: exVol.VolID,
VolumeId: exVol.VolID,
CapacityBytes: int64(exVol.VolSize),
Attributes: req.GetParameters(),
VolumeContext: req.GetParameters(),
},
}, nil
}
@ -84,6 +91,26 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
glog.V(3).Infof("failed to create volume: %v", err)
return nil, err
}
if req.GetVolumeContentSource() != nil {
contentSource := req.GetVolumeContentSource()
if contentSource.GetSnapshot() != nil {
snapshotId := contentSource.GetSnapshot().GetSnapshotId()
snapshot, ok := hostPathVolumeSnapshots[snapshotId]
if !ok {
return nil, status.Errorf(codes.NotFound, "cannot find snapshot %v", snapshotId)
}
if snapshot.ReadyToUse != true {
return nil, status.Errorf(codes.Internal, "Snapshot %v is not yet ready to use.", snapshotId)
}
snapshotPath := snapshot.Path
args := []string{"zxvf", snapshotPath, "-C", path}
executor := utilexec.New()
out, err := executor.Command("tar", args...).CombinedOutput()
if err != nil {
return nil, status.Error(codes.Internal, fmt.Sprintf("failed pre-populate data for volume: %v: %s", err, out))
}
}
}
glog.V(4).Infof("create volume %s", path)
hostPathVol := hostPathVolume{}
hostPathVol.VolName = req.GetName()
@ -93,9 +120,9 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
hostPathVolumes[volumeID] = hostPathVol
return &csi.CreateVolumeResponse{
Volume: &csi.Volume{
Id: volumeID,
VolumeId: volumeID,
CapacityBytes: req.GetCapacityRange().GetRequiredBytes(),
Attributes: req.GetParameters(),
VolumeContext: req.GetParameters(),
},
}, nil
}
@ -120,22 +147,221 @@ func (cs *controllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVol
}
func (cs *controllerServer) ValidateVolumeCapabilities(ctx context.Context, req *csi.ValidateVolumeCapabilitiesRequest) (*csi.ValidateVolumeCapabilitiesResponse, error) {
return cs.DefaultControllerServer.ValidateVolumeCapabilities(ctx, req)
}
// CreateSnapshot uses tar command to create snapshot for hostpath volume. The tar command can quickly create
// archives of entire directories. The host image must have "tar" binaries in /bin, /usr/sbin, or /usr/bin.
func (cs *controllerServer) CreateSnapshot(ctx context.Context, req *csi.CreateSnapshotRequest) (*csi.CreateSnapshotResponse, error) {
if err := cs.Driver.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT); err != nil {
glog.V(3).Infof("invalid create snapshot req: %v", req)
return nil, err
}
if len(req.GetName()) == 0 {
return nil, status.Error(codes.InvalidArgument, "Name missing in request")
}
// Check arguments
if len(req.GetVolumeId()) == 0 {
return nil, status.Error(codes.InvalidArgument, "Volume ID missing in request")
}
if req.GetVolumeCapabilities() == nil {
return nil, status.Error(codes.InvalidArgument, "Volume capabilities missing in request")
}
if _, ok := hostPathVolumes[req.GetVolumeId()]; !ok {
return nil, status.Error(codes.NotFound, "Volume does not exist")
if len(req.GetSourceVolumeId()) == 0 {
return nil, status.Error(codes.InvalidArgument, "SourceVolumeId missing in request")
}
for _, cap := range req.VolumeCapabilities {
if cap.GetAccessMode().GetMode() != csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER {
return &csi.ValidateVolumeCapabilitiesResponse{Supported: false, Message: ""}, nil
// Need to check for already existing snapshot name, and if found check for the
// requested sourceVolumeId and sourceVolumeId of snapshot that has been created.
if exSnap, err := getSnapshotByName(req.GetName()); err == nil {
// Since err is nil, it means the snapshot with the same name already exists need
// to check if the sourceVolumeId of existing snapshot is the same as in new request.
if exSnap.VolID == req.GetSourceVolumeId() {
// same snapshot has been created.
return &csi.CreateSnapshotResponse{
Snapshot: &csi.Snapshot{
SnapshotId: exSnap.Id,
SourceVolumeId: exSnap.VolID,
CreationTime: &exSnap.CreationTime,
SizeBytes: exSnap.SizeBytes,
ReadyToUse: exSnap.ReadyToUse,
},
}, nil
}
return nil, status.Error(codes.AlreadyExists, fmt.Sprintf("snapshot with the same name: %s but with different SourceVolumeId already exist", req.GetName()))
}
volumeID := req.GetSourceVolumeId()
hostPathVolume, ok := hostPathVolumes[volumeID]
if !ok {
return nil, status.Error(codes.Internal, "volumeID is not exist")
}
snapshotID := uuid.NewUUID().String()
creationTime := ptypes.TimestampNow()
volPath := hostPathVolume.VolPath
file := snapshotRoot + snapshotID + ".tgz"
args := []string{"czf", file, "-C", volPath, "."}
executor := utilexec.New()
out, err := executor.Command("tar", args...).CombinedOutput()
if err != nil {
return nil, status.Error(codes.Internal, fmt.Sprintf("failed create snapshot: %v: %s", err, out))
}
glog.V(4).Infof("create volume snapshot %s", file)
snapshot := hostPathSnapshot{}
snapshot.Name = req.GetName()
snapshot.Id = snapshotID
snapshot.VolID = volumeID
snapshot.Path = file
snapshot.CreationTime = *creationTime
snapshot.SizeBytes = hostPathVolume.VolSize
snapshot.ReadyToUse = true
hostPathVolumeSnapshots[snapshotID] = snapshot
return &csi.CreateSnapshotResponse{
Snapshot: &csi.Snapshot{
SnapshotId: snapshot.Id,
SourceVolumeId: snapshot.VolID,
CreationTime: &snapshot.CreationTime,
SizeBytes: snapshot.SizeBytes,
ReadyToUse: snapshot.ReadyToUse,
},
}, nil
}
func (cs *controllerServer) DeleteSnapshot(ctx context.Context, req *csi.DeleteSnapshotRequest) (*csi.DeleteSnapshotResponse, error) {
// Check arguments
if len(req.GetSnapshotId()) == 0 {
return nil, status.Error(codes.InvalidArgument, "Snapshot ID missing in request")
}
if err := cs.Driver.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT); err != nil {
glog.V(3).Infof("invalid delete snapshot req: %v", req)
return nil, err
}
snapshotID := req.GetSnapshotId()
glog.V(4).Infof("deleting volume %s", snapshotID)
path := snapshotRoot + snapshotID + ".tgz"
os.RemoveAll(path)
delete(hostPathVolumeSnapshots, snapshotID)
return &csi.DeleteSnapshotResponse{}, nil
}
func (cs *controllerServer) ListSnapshots(ctx context.Context, req *csi.ListSnapshotsRequest) (*csi.ListSnapshotsResponse, error) {
if err := cs.Driver.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_LIST_SNAPSHOTS); err != nil {
glog.V(3).Infof("invalid list snapshot req: %v", req)
return nil, err
}
// case 1: SnapshotId is not empty, return snapshots that match the snapshot id.
if len(req.GetSnapshotId()) != 0 {
snapshotID := req.SnapshotId
if snapshot, ok := hostPathVolumeSnapshots[snapshotID]; ok {
return convertSnapshot(snapshot), nil
}
}
return &csi.ValidateVolumeCapabilitiesResponse{Supported: true, Message: ""}, nil
// case 2: SourceVolumeId is not empty, return snapshots that match the source volume id.
if len(req.GetSourceVolumeId()) != 0 {
for _, snapshot := range hostPathVolumeSnapshots {
if snapshot.VolID == req.SourceVolumeId {
return convertSnapshot(snapshot), nil
}
}
}
var snapshots []csi.Snapshot
// case 3: no parameter is set, so we return all the snapshots.
sortedKeys := make([]string, 0)
for k := range hostPathVolumeSnapshots {
sortedKeys = append(sortedKeys, k)
}
sort.Strings(sortedKeys)
for _, key := range sortedKeys {
snap := hostPathVolumeSnapshots[key]
snapshot := csi.Snapshot{
SnapshotId: snap.Id,
SourceVolumeId: snap.VolID,
CreationTime: &snap.CreationTime,
SizeBytes: snap.SizeBytes,
ReadyToUse: snap.ReadyToUse,
}
snapshots = append(snapshots, snapshot)
}
var (
ulenSnapshots = int32(len(snapshots))
maxEntries = req.MaxEntries
startingToken int32
)
if v := req.StartingToken; v != "" {
i, err := strconv.ParseUint(v, 10, 32)
if err != nil {
return nil, status.Errorf(
codes.Aborted,
"startingToken=%d !< int32=%d",
startingToken, math.MaxUint32)
}
startingToken = int32(i)
}
if startingToken > ulenSnapshots {
return nil, status.Errorf(
codes.Aborted,
"startingToken=%d > len(snapshots)=%d",
startingToken, ulenSnapshots)
}
// Discern the number of remaining entries.
rem := ulenSnapshots - startingToken
// If maxEntries is 0 or greater than the number of remaining entries then
// set maxEntries to the number of remaining entries.
if maxEntries == 0 || maxEntries > rem {
maxEntries = rem
}
var (
i int
j = startingToken
entries = make(
[]*csi.ListSnapshotsResponse_Entry,
maxEntries)
)
for i = 0; i < len(entries); i++ {
entries[i] = &csi.ListSnapshotsResponse_Entry{
Snapshot: &snapshots[j],
}
j++
}
var nextToken string
if j < ulenSnapshots {
nextToken = fmt.Sprintf("%d", j)
}
return &csi.ListSnapshotsResponse{
Entries: entries,
NextToken: nextToken,
}, nil
}
func convertSnapshot(snap hostPathSnapshot) *csi.ListSnapshotsResponse {
entries := []*csi.ListSnapshotsResponse_Entry{
{
Snapshot: &csi.Snapshot{
SnapshotId: snap.Id,
SourceVolumeId: snap.VolID,
CreationTime: &snap.CreationTime,
SizeBytes: snap.SizeBytes,
ReadyToUse: snap.ReadyToUse,
},
},
}
rsp := &csi.ListSnapshotsResponse{
Entries: entries,
}
return rsp
}

View File

@ -19,9 +19,10 @@ package hostpath
import (
"fmt"
"github.com/container-storage-interface/spec/lib/go/csi/v0"
"github.com/container-storage-interface/spec/lib/go/csi"
"github.com/golang/glog"
timestamp "github.com/golang/protobuf/ptypes/timestamp"
"github.com/kubernetes-csi/drivers/pkg/csi-common"
)
@ -52,15 +53,27 @@ type hostPathVolume struct {
VolPath string `json:"volPath"`
}
type hostPathSnapshot struct {
Name string `json:"name"`
Id string `json:"id"`
VolID string `json:"volID"`
Path string `json:"path"`
CreationTime timestamp.Timestamp `json:"creationTime"`
SizeBytes int64 `json:"sizeBytes"`
ReadyToUse bool `json:"readyToUse"`
}
var hostPathVolumes map[string]hostPathVolume
var hostPathVolumeSnapshots map[string]hostPathSnapshot
var (
hostPathDriver *hostPath
vendorVersion = "0.3.0"
vendorVersion = "dev"
)
func init() {
hostPathVolumes = map[string]hostPathVolume{}
hostPathVolumeSnapshots = map[string]hostPathSnapshot{}
}
func GetHostPathDriver() *hostPath {
@ -87,13 +100,19 @@ func NewNodeServer(d *csicommon.CSIDriver) *nodeServer {
func (hp *hostPath) Run(driverName, nodeID, endpoint string) {
glog.Infof("Driver: %v ", driverName)
glog.Infof("Version: %s", vendorVersion)
// Initialize default library driver
hp.driver = csicommon.NewCSIDriver(driverName, vendorVersion, nodeID)
if hp.driver == nil {
glog.Fatalln("Failed to initialize CSI Driver.")
}
hp.driver.AddControllerServiceCapabilities([]csi.ControllerServiceCapability_RPC_Type{csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME})
hp.driver.AddControllerServiceCapabilities(
[]csi.ControllerServiceCapability_RPC_Type{
csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME,
csi.ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT,
csi.ControllerServiceCapability_RPC_LIST_SNAPSHOTS,
})
hp.driver.AddVolumeCapabilityAccessModes([]csi.VolumeCapability_AccessMode_Mode{csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER})
// Create GRPC servers
@ -121,3 +140,12 @@ func getVolumeByName(volName string) (hostPathVolume, error) {
}
return hostPathVolume{}, fmt.Errorf("volume name %s does not exit in the volumes list", volName)
}
func getSnapshotByName(name string) (hostPathSnapshot, error) {
for _, snapshot := range hostPathVolumeSnapshots {
if snapshot.Name == name {
return snapshot, nil
}
}
return hostPathSnapshot{}, fmt.Errorf("snapshot name %s does not exit in the snapshots list", name)
}

View File

@ -22,7 +22,7 @@ import (
"github.com/golang/glog"
"golang.org/x/net/context"
"github.com/container-storage-interface/spec/lib/go/csi/v0"
"github.com/container-storage-interface/spec/lib/go/csi"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"k8s.io/kubernetes/pkg/util/mount"
@ -67,13 +67,13 @@ func (ns *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublis
fsType := req.GetVolumeCapability().GetMount().GetFsType()
deviceId := ""
if req.GetPublishInfo() != nil {
deviceId = req.GetPublishInfo()[deviceID]
if req.GetPublishContext() != nil {
deviceId = req.GetPublishContext()[deviceID]
}
readOnly := req.GetReadonly()
volumeId := req.GetVolumeId()
attrib := req.GetVolumeAttributes()
attrib := req.GetVolumeContext()
mountFlags := req.GetVolumeCapability().GetMount().GetMountFlags()
glog.V(4).Infof("target %v\nfstype %v\ndevice %v\nreadonly %v\nvolumeId %v\nattributes %v\nmountflags %v\n",