Skip to content

Commit

Permalink
Enable fake driver for use in functional tests
Browse files Browse the repository at this point in the history
  • Loading branch information
clintonk committed Jun 13, 2017
1 parent ee1b670 commit afa0916
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 77 deletions.
146 changes: 90 additions & 56 deletions drivers/fake/fake.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"errors"
"fmt"

log "github.com/Sirupsen/logrus"
dvp "github.com/netapp/netappdvp/storage_drivers"

"github.com/netapp/trident/config"
sa "github.com/netapp/trident/storage_attribute"
)
Expand All @@ -19,44 +19,50 @@ const (
)

type FakeStoragePool struct {
Attrs map[string]sa.Offer
Bytes uint64
Attrs map[string]sa.Offer `json:"attributes"`
Bytes uint64 `json:"sizeBytes"`
}

// UnmarshalJSON implements json.Unmarshaler and allows FakeStoragePool
// to be unmarshaled with the Attrs map correctly defined.
func (m *FakeStoragePool) UnmarshalJSON(data []byte) error {
func (p *FakeStoragePool) UnmarshalJSON(data []byte) error {
var tmp struct {
Attrs json.RawMessage
Bytes uint64
Attrs json.RawMessage `json:"attributes"`
Bytes uint64 `json:"sizeBytes"`
}

err := json.Unmarshal(data, &tmp)
if err != nil {
return err
}
m.Attrs, err = sa.UnmarshalOfferMap(tmp.Attrs)
p.Attrs, err = sa.UnmarshalOfferMap(tmp.Attrs)
if err != nil {
return err
}
m.Bytes = tmp.Bytes
p.Bytes = tmp.Bytes
return nil
}

type FakeStorageDriverConfig struct {
dvp.CommonStorageDriverConfig
Protocol config.Protocol
Protocol config.Protocol `json:"protocol"`
// pools represents the possible buckets into which a given volume should go
Pools map[string]*FakeStoragePool
InstanceName string
Pools map[string]*FakeStoragePool `json:"pools"`
InstanceName string `json:"instanceName"`
}

type FakeVolume struct {
name string
poolName string
sizeBytes uint64
}

type FakeStorageDriver struct {
Config FakeStorageDriverConfig
// Volumes maps volumes to the name of the pool in which the volume should
// be stored.
Volumes map[string]string // Maps
VolumesAdded int

// volumes saves info about volumes created on this driver
volumes map[string]FakeVolume

// DestroyedVolumes is here so that tests can check whether destroy
// has been called on a volume during or after bootstrapping, since
// different driver instances with the same config won't actually share
Expand Down Expand Up @@ -98,95 +104,123 @@ func NewFakeStorageDriverConfigJSON(
return newFakeStorageDriverConfigJSON(name, protocol, pools, false)
}

func (m *FakeStorageDriver) Name() string {
func (d *FakeStorageDriver) Name() string {
return FakeStorageDriverName
}

func (m *FakeStorageDriver) Initialize(configJSON string, commonConfig *dvp.CommonStorageDriverConfig) error {
err := json.Unmarshal([]byte(configJSON), &m.Config)
func (d *FakeStorageDriver) Initialize(configJSON string, commonConfig *dvp.CommonStorageDriverConfig) error {

err := json.Unmarshal([]byte(configJSON), &d.Config)
if err != nil {
return fmt.Errorf("Unable to initialize fake driver: %v", err)
return fmt.Errorf("Unable to initialize fake driver: %v", err)
}
m.Volumes = make(map[string]string)
m.VolumesAdded = 0
m.DestroyedVolumes = make(map[string]bool)

d.volumes = make(map[string]FakeVolume)
d.DestroyedVolumes = make(map[string]bool)

s, err := json.Marshal(d.Config)
log.Debugf("FakeStorageDriverConfig: %s", string(s))

return nil
}

func (m *FakeStorageDriver) Validate() error {
func (d *FakeStorageDriver) Validate() error {
return nil
}

func (m *FakeStorageDriver) Create(name string, sizeBytes uint64, opts map[string]string) error {
func (d *FakeStorageDriver) Create(name string, sizeBytes uint64, opts map[string]string) error {

poolName, ok := opts[FakePoolAttribute]
if !ok {
return fmt.Errorf("No pool specified. Expected %s in opts map",
FakePoolAttribute)
return fmt.Errorf("No pool specified. Expected %s in opts map", FakePoolAttribute)
}
pool, ok := m.Config.Pools[poolName]

pool, ok := d.Config.Pools[poolName]
if !ok {
return fmt.Errorf("Invalid pool %s.", pool)
return fmt.Errorf("Could not find pool %s.", pool)
}
if _, ok = m.Volumes[name]; ok {

if _, ok = d.volumes[name]; ok {
return fmt.Errorf("Volume %s already exists", name)
}

if sizeBytes > pool.Bytes {
return fmt.Errorf("Requested volume is too large. Requested %d bytes;"+
" have %d available in pool %s.", sizeBytes, pool.Bytes, poolName)
return fmt.Errorf("Requested volume is too large. Requested %d bytes; "+
"have %d available in pool %s.", sizeBytes, pool.Bytes, poolName)
}
m.Volumes[name] = poolName
m.VolumesAdded++

d.volumes[name] = FakeVolume{
name: name,
poolName: poolName,
sizeBytes: sizeBytes,
}
d.DestroyedVolumes[name] = false
pool.Bytes -= sizeBytes

log.WithFields(log.Fields{
"backend": d.Config.InstanceName,
"name": name,
"poolName": poolName,
"sizeBytes": sizeBytes,
}).Debug("Created fake volume.")

return nil
}

func (m *FakeStorageDriver) Destroy(name string) error {
m.DestroyedVolumes[name] = true
if _, ok := m.Volumes[name]; !ok {
// TODO: return the standard volume not found error once that gets
// added to the nDVP.
func (d *FakeStorageDriver) CreateClone(name, source, snapshot string, opts map[string]string) error {
return errors.New("Fake driver does not support CreateClone")
}

func (d *FakeStorageDriver) Destroy(name string) error {

d.DestroyedVolumes[name] = true

volume, ok := d.volumes[name]
if !ok {
return nil
}
delete(m.Volumes, name)
return nil
}

func (m *FakeStorageDriver) Attach(name, mountpoint string, opts map[string]string) error {
return errors.New("Fake driver does not support attaching.")
}
pool, ok := d.Config.Pools[volume.poolName]
if !ok {
return fmt.Errorf("Could not find pool %s.", volume.poolName)
}

func (m *FakeStorageDriver) Detach(name, mountpoint string) error {
return errors.New("Fake driver does not support detaching.")
}
pool.Bytes += volume.sizeBytes
delete(d.volumes, name)

func (m *FakeStorageDriver) DefaultStoragePrefix() string {
return "fake"
log.WithFields(log.Fields{
"backend": d.Config.InstanceName,
"name": name,
"poolName": volume.poolName,
"sizeBytes": volume.sizeBytes,
}).Debug("Deleted fake volume.")

return nil
}

func (d *FakeStorageDriver) CreateClone(name, source, snapshot string, opts map[string]string) error {
return errors.New("Fake driver does not support CreateClone")
func (d *FakeStorageDriver) Attach(name, mountpoint string, opts map[string]string) error {
return errors.New("Fake driver does not support attaching.")
}

func (d *FakeStorageDriver) DefaultSnapshotPrefix() string {
return ""
func (d *FakeStorageDriver) Detach(name, mountpoint string) error {
return errors.New("Fake driver does not support detaching.")
}

func (d *FakeStorageDriver) SnapshotList(name string) ([]dvp.CommonSnapshot, error) {
return nil, errors.New("Fake driver does not support SnapshotList")
}

func (m *FakeStorageDriver) List() ([]string, error) {
func (d *FakeStorageDriver) List() ([]string, error) {
vols := []string{}
for vol := range m.Volumes {
for vol := range d.volumes {
vols = append(vols, vol)
}
return vols, nil
}

func (d *FakeStorageDriver) Get(name string) error {

_, ok := d.Volumes[name]
_, ok := d.volumes[name]
if !ok {
return fmt.Errorf("Could not find volume %s.", name)
}
Expand Down
9 changes: 9 additions & 0 deletions frontend/kubernetes/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (

"github.com/netapp/trident/config"
"github.com/netapp/trident/core"
"github.com/netapp/trident/drivers/fake"
"github.com/netapp/trident/storage"
"github.com/netapp/trident/storage_attribute"
"github.com/netapp/trident/storage_class"
Expand Down Expand Up @@ -607,6 +608,14 @@ func (p *KubernetesPlugin) createVolumeAndPV(uniqueName string,
case driverType == dvp.OntapNASStorageDriverName:
nfsSource = CreateNFSVolumeSource(vol.Config)
pv.Spec.NFS = nfsSource
case driverType == fake.FakeStorageDriverName:
if vol.Config.Protocol == config.File {
nfsSource = CreateNFSVolumeSource(vol.Config)
pv.Spec.NFS = nfsSource
} else if vol.Config.Protocol == config.Block {
iscsiSource = CreateISCSIVolumeSource(vol.Config)
pv.Spec.ISCSI = iscsiSource
}
default:
// Unknown driver for the frontend plugin or for Kubernetes.
// Provisioned volume should get deleted.
Expand Down
43 changes: 22 additions & 21 deletions storage/fake/fake.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,23 @@ type FakeStorageDriver struct {
fake.FakeStorageDriver
}

func (m *FakeStorageDriver) GetStorageBackendSpecs(
backend *storage.StorageBackend,
) error {
backend.Name = m.Config.InstanceName
for name, pool := range m.Config.Pools {
func (d *FakeStorageDriver) GetStorageBackendSpecs(backend *storage.StorageBackend) error {
backend.Name = d.Config.InstanceName
for name, pool := range d.Config.Pools {
vc := &storage.StoragePool{
Name: name,
StorageClasses: make([]string, 0),
Volumes: make(map[string]*storage.Volume, 0),
Backend: backend,
Attributes: pool.Attrs,
}
vc.Attributes[sa.BackendType] = sa.NewStringOffer(m.Name())
vc.Attributes[sa.BackendType] = sa.NewStringOffer(d.Name())
backend.AddStoragePool(vc)
}
return nil
}

func (m *FakeStorageDriver) GetVolumeOpts(
func (d *FakeStorageDriver) GetVolumeOpts(
volConfig *storage.VolumeConfig,
pool *storage.StoragePool,
requests map[string]sa.Request,
Expand All @@ -41,21 +39,27 @@ func (m *FakeStorageDriver) GetVolumeOpts(
return opts, nil
}

func (m *FakeStorageDriver) GetInternalVolumeName(name string) string {
func (d *FakeStorageDriver) GetInternalVolumeName(name string) string {
return storage.GetCommonInternalVolumeName(
&m.Config.CommonStorageDriverConfig, name)
&d.Config.CommonStorageDriverConfig, name)
}

func (m *FakeStorageDriver) CreatePrepare(
volConfig *storage.VolumeConfig,
) bool {
volConfig.InternalName = m.GetInternalVolumeName(volConfig.Name)
func (d *FakeStorageDriver) CreatePrepare(volConfig *storage.VolumeConfig) bool {
volConfig.InternalName = d.GetInternalVolumeName(volConfig.Name)
return true
}

func (m *FakeStorageDriver) CreateFollowup(
volConfig *storage.VolumeConfig,
) error {
func (d *FakeStorageDriver) CreateFollowup(volConfig *storage.VolumeConfig) error {

switch d.Config.Protocol {
case config.File:
volConfig.AccessInfo.NfsServerIP = "192.0.2.1" // unrouteable test address, see RFC 5737
volConfig.AccessInfo.NfsPath = "/" + volConfig.InternalName
case config.Block:
volConfig.AccessInfo.IscsiTargetPortal = "192.0.2.1"
volConfig.AccessInfo.IscsiTargetIQN = "iqn.2017-06.com.netapp:fake"
volConfig.AccessInfo.IscsiLunNumber = 0
}
return nil
}

Expand All @@ -67,11 +71,8 @@ func (d *FakeStorageDriver) GetDriverName() string {
return d.Config.StorageDriverName
}

func (d *FakeStorageDriver) StoreConfig(
b *storage.PersistentStorageBackendConfig,
) {
storage.SanitizeCommonStorageDriverConfig(
&d.Config.CommonStorageDriverConfig)
func (d *FakeStorageDriver) StoreConfig(b *storage.PersistentStorageBackendConfig) {
storage.SanitizeCommonStorageDriverConfig(&d.Config.CommonStorageDriverConfig)
b.FakeStorageDriverConfig = &d.Config
}

Expand Down

0 comments on commit afa0916

Please sign in to comment.