Skip to content

Commit

Permalink
Add provider validation on pool creation; add disallow persistent att…
Browse files Browse the repository at this point in the history
…ribute for unsupported providers
  • Loading branch information
wallyworld committed Mar 17, 2015
1 parent 2d63649 commit 687afda
Show file tree
Hide file tree
Showing 13 changed files with 62 additions and 12 deletions.
4 changes: 3 additions & 1 deletion provider/dummy/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
package dummy

import (
dummystorage "github.com/juju/juju/storage/provider/dummy"
"github.com/juju/juju/storage/provider/registry"
)

func init() {
registry.RegisterEnvironStorageProviders("dummy")
registry.RegisterEnvironStorageProviders("dummy", "dummy")
registry.RegisterProvider("dummy", &dummystorage.StorageProvider{})
}
1 change: 1 addition & 0 deletions provider/ec2/ebs.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type ebsProvider struct{}
var _ storage.Provider = (*ebsProvider)(nil)

var validConfigOptions = set.NewStrings(
storage.Persistent,
EBS_VolumeType,
EBS_IOPS,
EBS_Encrypted,
Expand Down
4 changes: 2 additions & 2 deletions storage/poolmanager/defaultpool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ func (s *defaultStoragePoolsSuite) TestDefaultStoragePools(c *gc.C) {
s.SetFeatureFlags(feature.Storage)
featureflag.SetFlagsFromEnvironment(osenv.JujuFeatureFlagEnvKey)

p1, err := storage.NewConfig("pool1", storage.ProviderType("foo"), map[string]interface{}{"1": "2"})
p2, err := storage.NewConfig("pool2", storage.ProviderType("bar"), map[string]interface{}{"3": "4"})
p1, err := storage.NewConfig("pool1", storage.ProviderType("loop"), map[string]interface{}{"1": "2"})
p2, err := storage.NewConfig("pool2", storage.ProviderType("tmpfs"), map[string]interface{}{"3": "4"})
c.Assert(err, jc.ErrorIsNil)
defaultPools := []*storage.Config{p1, p2}
poolmanager.RegisterDefaultStoragePools(defaultPools)
Expand Down
10 changes: 10 additions & 0 deletions storage/poolmanager/poolmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/juju/errors"

"github.com/juju/juju/storage"
"github.com/juju/juju/storage/provider/registry"
)

const (
Expand Down Expand Up @@ -55,6 +56,15 @@ func (pm *poolManager) Create(name string, providerType storage.ProviderType, at
for k, v := range attrs {
poolAttrs[k] = v
}
// Instantiate the provider to validate config.
p, err := registry.StorageProvider(providerType)
if err != nil {
return nil, err
}
if err := p.ValidateConfig(cfg); err != nil {
return nil, err
}

poolAttrs[Name] = name
poolAttrs[Type] = string(providerType)
if err := pm.settings.CreateSettings(globalKey(name), poolAttrs); err != nil {
Expand Down
5 changes: 5 additions & 0 deletions storage/poolmanager/poolmanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ func (s *poolSuite) TestCreateMissingType(c *gc.C) {
c.Assert(err, gc.ErrorMatches, "provider type is missing")
}

func (s *poolSuite) TestCreateInvalidConfig(c *gc.C) {
_, err := s.poolManager.Create("testpool", storage.ProviderType("loop"), map[string]interface{}{"persistent": true})
c.Assert(err, gc.ErrorMatches, `machine scoped storage provider "testpool" does not support persistent storage`)
}

func (s *poolSuite) TestDelete(c *gc.C) {
s.createSettings(c)
err := s.poolManager.Delete("testpool")
Expand Down
14 changes: 13 additions & 1 deletion storage/provider/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@

package provider

import "github.com/juju/juju/storage"
import (
"github.com/juju/errors"

"github.com/juju/juju/storage"
)

// CommonProviders returns the storage providers used by all environments.
func CommonProviders() map[storage.ProviderType]storage.Provider {
Expand All @@ -13,3 +17,11 @@ func CommonProviders() map[storage.ProviderType]storage.Provider {
TmpfsProviderType: &tmpfsProvider{logAndExec},
}
}

// ValidateConfig performs common provider config validation.
func ValidateConfig(p storage.Provider, cfg *storage.Config) error {
if p.Scope() == storage.ScopeMachine && cfg.IsPersistent() {
return errors.Errorf("machine scoped storage provider %q does not support persistent storage", cfg.Name())
}
return nil
}
3 changes: 1 addition & 2 deletions storage/provider/loop.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ var _ storage.Provider = (*loopProvider)(nil)

// ValidateConfig is defined on the Provider interface.
func (lp *loopProvider) ValidateConfig(cfg *storage.Config) error {
// Loop provider has no configuration.
return nil
return ValidateConfig(lp, cfg)
}

// validateFullConfig validates a fully-constructed storage config,
Expand Down
8 changes: 8 additions & 0 deletions storage/provider/loop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ func (s *loopSuite) TestValidateConfig(c *gc.C) {
c.Assert(err, jc.ErrorIsNil)
}

func (s *loopSuite) TestPersistentNotAllowed(c *gc.C) {
p := s.loopProvider(c)
cfg, err := storage.NewConfig("name", provider.LoopProviderType, map[string]interface{}{"persistent": true})
c.Assert(err, jc.ErrorIsNil)
err = p.ValidateConfig(cfg)
c.Assert(err, gc.ErrorMatches, `machine scoped storage provider "name" does not support persistent storage`)
}

func (s *loopSuite) TestSupports(c *gc.C) {
p := s.loopProvider(c)
c.Assert(p.Supports(storage.StorageKindBlock), jc.IsTrue)
Expand Down
3 changes: 1 addition & 2 deletions storage/provider/rootfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ var (

// ValidateConfig is defined on the Provider interface.
func (p *rootfsProvider) ValidateConfig(cfg *storage.Config) error {
// Rootfs provider has no configuration.
return nil
return ValidateConfig(p, cfg)
}

// validateFullConfig validates a fully-constructed storage config,
Expand Down
8 changes: 8 additions & 0 deletions storage/provider/rootfs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ func (s *rootfsSuite) TestValidateConfig(c *gc.C) {
c.Assert(err, jc.ErrorIsNil)
}

func (s *rootfsSuite) TestPersistentNotAllowed(c *gc.C) {
p := s.rootfsProvider(c)
cfg, err := storage.NewConfig("name", provider.RootfsProviderType, map[string]interface{}{"persistent": true})
c.Assert(err, jc.ErrorIsNil)
err = p.ValidateConfig(cfg)
c.Assert(err, gc.ErrorMatches, `machine scoped storage provider "name" does not support persistent storage`)
}

func (s *rootfsSuite) TestSupports(c *gc.C) {
p := s.rootfsProvider(c)
c.Assert(p.Supports(storage.StorageKindBlock), jc.IsFalse)
Expand Down
3 changes: 1 addition & 2 deletions storage/provider/tmpfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ var (

// ValidateConfig is defined on the Provider interface.
func (p *tmpfsProvider) ValidateConfig(cfg *storage.Config) error {
// Tmpfs provider has no configuration.
return nil
return ValidateConfig(p, cfg)
}

// validateFullConfig validates a fully-constructed storage config,
Expand Down
8 changes: 8 additions & 0 deletions storage/provider/tmpfs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ func (s *tmpfsSuite) TestValidateConfig(c *gc.C) {
c.Assert(err, jc.ErrorIsNil)
}

func (s *tmpfsSuite) TestPersistentNotAllowed(c *gc.C) {
p := s.tmpfsProvider(c)
cfg, err := storage.NewConfig("name", provider.TmpfsProviderType, map[string]interface{}{"persistent": true})
c.Assert(err, jc.ErrorIsNil)
err = p.ValidateConfig(cfg)
c.Assert(err, gc.ErrorMatches, `machine scoped storage provider "name" does not support persistent storage`)
}

func (s *tmpfsSuite) TestSupports(c *gc.C) {
p := s.tmpfsProvider(c)
c.Assert(p.Supports(storage.StorageKindBlock), jc.IsFalse)
Expand Down
3 changes: 1 addition & 2 deletions worker/provisioner/provisioner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import (
"github.com/juju/juju/state/multiwatcher"
"github.com/juju/juju/storage"
"github.com/juju/juju/storage/poolmanager"
"github.com/juju/juju/storage/provider"
coretesting "github.com/juju/juju/testing"
coretools "github.com/juju/juju/tools"
"github.com/juju/juju/version"
Expand Down Expand Up @@ -831,7 +830,7 @@ func (s *CommonProvisionerSuite) addMachineWithRequestedVolumes(volumes []state.
func (s *ProvisionerSuite) TestProvisioningMachinesWithRequestedVolumes(c *gc.C) {
// Set up a persistent pool.
poolManager := poolmanager.New(state.NewStateSettings(s.State))
_, err := poolManager.Create("persistent-pool", provider.LoopProviderType, map[string]interface{}{"persistent": true})
_, err := poolManager.Create("persistent-pool", "dummy", map[string]interface{}{"persistent": true})
c.Assert(err, jc.ErrorIsNil)

p := s.newEnvironProvisioner(c)
Expand Down

0 comments on commit 687afda

Please sign in to comment.