Skip to content

Commit

Permalink
Adding IP reservation functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
krunaljain committed Jul 23, 2018
1 parent 3b99727 commit ba769f8
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 323 deletions.
24 changes: 22 additions & 2 deletions pkg/cloud_provider/file/fake.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,26 @@ func (manager *fakeServiceManager) GetInstance(ctx context.Context, obj *Service
}
}

func (manager *fakeServiceManager) ListInstances (ctx context.Context) ([]*ServiceInstance, error) {
return nil, nil
func (manager *fakeServiceManager) ListInstances(ctx context.Context, parent string) ([]*ServiceInstance, error) {
instances := []*ServiceInstance{
&ServiceInstance{
Project: "test-project",
Location: "test-location",
Name: "test",
Tier: "test_tier",
Network: Network{
ReservedIpRange: "192.168.92.32/29",
},
},
&ServiceInstance{
Project: "test-project",
Location: "test-location",
Name: "test",
Tier: "test_tier",
Network: Network{
ReservedIpRange: "192.168.92.40/29",
},
},
}
return instances, nil
}
8 changes: 4 additions & 4 deletions pkg/cloud_provider/file/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ type Service interface {
CreateInstance(ctx context.Context, obj *ServiceInstance) (*ServiceInstance, error)
DeleteInstance(ctx context.Context, obj *ServiceInstance) error
GetInstance(ctx context.Context, obj *ServiceInstance) (*ServiceInstance, error)
ListInstances(ctx context.Context) ([]*ServiceInstance, error)
ListInstances(ctx context.Context, parent string) ([]*ServiceInstance, error)
}

type gcfsServiceManager struct {
Expand Down Expand Up @@ -232,14 +232,14 @@ func (manager *gcfsServiceManager) DeleteInstance(ctx context.Context, obj *Serv
return nil
}

func (manager *gcfsServiceManager) ListInstances(ctx context.Context) ([]*ServiceInstance, error) {
instances, err := manager.instancesService.List("-").Context(ctx).Do()
func (manager *gcfsServiceManager) ListInstances(ctx context.Context, parent string) ([]*ServiceInstance, error) {
instances, err := manager.instancesService.List(parent).Context(ctx).Do()
if err != nil {
return nil, err
}
var activeInstances []*ServiceInstance
for _, activeInstance := range instances.Instances {
serviceInstance, err := cloudInstanceToServiceInstance(activeInstance)
serviceInstance, err := cloudInstanceToServiceInstance(activeInstance)
if err != nil {
return nil, err
}
Expand Down
87 changes: 34 additions & 53 deletions pkg/csi_driver/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package driver
import (
"fmt"
"strings"
"time"
"sync"

csi "github.com/container-storage-interface/spec/lib/go/csi/v0"
"github.com/golang/glog"
Expand Down Expand Up @@ -49,9 +49,10 @@ const (

// CreateVolume parameters
const (
paramTier = "tier"
paramLocation = "location"
paramNetwork = "network"
paramTier = "tier"
paramLocation = "location"
paramNetwork = "network"
paramReservedIPV4CIDR = "cidr"
)

// controllerServer handles volume provisioning
Expand All @@ -60,40 +61,15 @@ type controllerServer struct {
}

type controllerServerConfig struct {
driver *GCFSDriver
fileService file.Service
metaService metadata.Service
ipAllocator *util.IPAllocator
driver *GCFSDriver
fileService file.Service
metaService metadata.Service
reservedIPRanges map[string]bool
mutex sync.Mutex
}

func newControllerServer(config *controllerServerConfig) (csi.ControllerServer, error) {
ipAllocator, err := config.newIPAllocator()
if err != nil {
return nil, err
}
config.ipAllocator = ipAllocator
return &controllerServer{config: config}, nil
}

func (config *controllerServerConfig) newIPAllocator() (*util.IPAllocator, error) {
activeInstances, err := getReservedInstances(config)
if err != nil {
return nil, err
}
ipAllocator := util.NewIPAllocator(make(map[string][]string), make(map[string]bool))
for _, activeInstance := range activeInstances {
ipAllocator.ReserveIPs(activeInstance.Network.ReservedIpRange)
}
return ipAllocator, nil
}

func getReservedInstances(config *controllerServerConfig) ([]* file.ServiceInstance, error){
ctx, _ := context.WithTimeout(context.Background(), 1*time.Minute)
reservedInstances, err := config.fileService.ListInstances(ctx)
if err != nil {
return nil, err
}
return reservedInstances, nil
func newControllerServer(config *controllerServerConfig) csi.ControllerServer {
return &controllerServer{config: config}
}

// CreateVolume creates a GCFS instance
Expand All @@ -109,12 +85,20 @@ func (s *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolu
if err := s.config.driver.validateVolumeCapabilities(req.GetVolumeCapabilities()); err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error())
}
s.config.mutex.Lock()
instances, err := s.config.fileService.ListInstances(ctx, "-")
if err != nil {
return nil, status.Error(codes.Aborted, err.Error())
}

s.config.reservedIPRanges = make(map[string]bool)
for _, instance := range instances {
s.config.reservedIPRanges[instance.Network.ReservedIpRange] = true
}
capBytes := getRequestCapacity(req.GetCapacityRange())
glog.V(5).Infof("Using capacity bytes %q for volume %q", capBytes, name)

newFiler, err := s.generateNewFileInstance(name, capBytes, req.GetParameters())

if err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error())
}
Expand All @@ -124,7 +108,6 @@ func (s *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolu
if err != nil && !file.IsNotFoundErr(err) {
return nil, status.Error(codes.Internal, err.Error())
}

if filer != nil {
// Instance already exists, check if it meets the request
if err = file.CompareInstances(newFiler, filer); err != nil {
Expand All @@ -137,6 +120,7 @@ func (s *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolu
return nil, status.Error(codes.Internal, err.Error())
}
}
s.config.mutex.Unlock()
return &csi.CreateVolumeResponse{Volume: fileInstanceToCSIVolume(filer, modeInstance)}, nil
}

Expand All @@ -161,17 +145,6 @@ func (s *controllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVolu
return nil, status.Error(codes.Internal, err.Error())
}


activeInstances, err := getReservedInstances(s.config)
if err != nil {
return nil, err
}

reservedUpdated := make(map[string]bool)
for _, instance := range activeInstances {
reservedUpdated[instance.Network.Ip] = true
}
err = s.config.ipAllocator.FreeIPBlocks(reservedUpdated)
return &csi.DeleteVolumeResponse{}, nil
}

Expand Down Expand Up @@ -252,7 +225,7 @@ func (s *controllerServer) generateNewFileInstance(name string, capBytes int64,
tier := defaultTier
network := defaultNetwork
location := s.config.metaService.GetZone()

reservedIPV4CIDR := ""
// Validate parameters (case-insensitive).
for k, v := range params {
switch strings.ToLower(k) {
Expand All @@ -263,7 +236,15 @@ func (s *controllerServer) generateNewFileInstance(name string, capBytes int64,
location = v
case paramNetwork:
network = v
// Unused
case paramReservedIPV4CIDR:
reservedIPV4CIDR, err := util.GetUnreservedIPBlock(s.config.reservedIPRanges, v)
if err != nil {
return nil, err
}
if reservedIPV4CIDR == "" {
return nil, fmt.Errorf("Invalid unreserved IP block received for cidr %s", v)
}

case "csiprovisionersecretname", "csiprovisionersecretnamespace":
default:
return nil, fmt.Errorf("invalid parameter %q", k)
Expand All @@ -275,8 +256,8 @@ func (s *controllerServer) generateNewFileInstance(name string, capBytes int64,
Location: location,
Tier: tier,
Network: file.Network{
Name: network,
// ReservedIpRange: "10.3.0.0/29", // TODO
Name: network,
ReservedIpRange: reservedIPV4CIDR,
},
Volume: file.Volume{
Name: newInstanceVolume,
Expand Down
6 changes: 1 addition & 5 deletions pkg/csi_driver/gcfs_driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,11 @@ func NewGCFSDriver(config *GCFSDriverConfig) (*GCFSDriver, error) {
driver.addControllerServiceCapabilities(csc)

// Configure controller server
controllerServer, err := newControllerServer(&controllerServerConfig{
driver.cs = newControllerServer(&controllerServerConfig{
driver: driver,
fileService: config.Cloud.File,
metaService: config.Cloud.Meta,
})
if err != nil {
return nil, err
}
driver.cs = controllerServer
}

return driver, nil
Expand Down
Loading

0 comments on commit ba769f8

Please sign in to comment.