func (s *providerRegistrySuite) TestRegisterEnvironProvidersMultipleCalls(c *gc.C) { ptypeFoo := storage.ProviderType("foo") ptypeBar := storage.ProviderType("bar") registry.RegisterEnvironStorageProviders("ec2", ptypeFoo) registry.RegisterEnvironStorageProviders("ec2", ptypeBar) registry.RegisterEnvironStorageProviders("ec2", ptypeBar) c.Assert(registry.IsProviderSupported("ec2", ptypeFoo), jc.IsTrue) c.Assert(registry.IsProviderSupported("ec2", ptypeBar), jc.IsTrue) }
func (s *providerRegistrySuite) TestSupportedEnvironProviders(c *gc.C) { ptypeFoo := storage.ProviderType("foo") ptypeBar := storage.ProviderType("bar") registry.RegisterEnvironStorageProviders("ec2", ptypeFoo, ptypeBar) c.Assert(registry.IsProviderSupported("ec2", ptypeFoo), jc.IsTrue) c.Assert(registry.IsProviderSupported("ec2", ptypeBar), jc.IsTrue) c.Assert(registry.IsProviderSupported("ec2", storage.ProviderType("foobar")), jc.IsFalse) c.Assert(registry.IsProviderSupported("openstack", ptypeBar), jc.IsFalse) }
func (s *poolSuite) TestCreate(c *gc.C) { created, err := s.poolManager.Create("testpool", storage.ProviderType("loop"), map[string]interface{}{"foo": "bar"}) c.Assert(err, jc.ErrorIsNil) p, err := s.poolManager.Get("testpool") c.Assert(created, gc.DeepEquals, p) c.Assert(err, jc.ErrorIsNil) c.Assert(p.Attrs(), gc.DeepEquals, map[string]interface{}{"foo": "bar"}) c.Assert(p.Name(), gc.Equals, "testpool") c.Assert(p.Provider(), gc.Equals, storage.ProviderType("loop")) }
func (s *providerRegistrySuite) TestRegisterProviderDuplicate(c *gc.C) { defer func() { if v := recover(); v != nil { c.Assert(v, gc.ErrorMatches, `.*duplicate storage provider type "foo"`) } }() p1 := &mockProvider{} p2 := &mockProvider{} registry.RegisterProvider(storage.ProviderType("foo"), p1) registry.RegisterProvider(storage.ProviderType("foo"), p2) c.Errorf("panic expected") }
func (s *providerRegistrySuite) TestUnregisterProvider(c *gc.C) { ptype := storage.ProviderType("foo") // No-op, since there's nothing registered yet. registry.RegisterProvider(ptype, nil) // Register and then unregister, ensure that the provider cannot // be accessed. registry.RegisterProvider(ptype, &mockProvider{}) registry.RegisterProvider(ptype, nil) _, err := registry.StorageProvider(storage.ProviderType("foo")) c.Assert(err, gc.ErrorMatches, `storage provider "foo" not found`) }
func poolStorageProvider(st *State, poolName string) (storage.ProviderType, storage.Provider, error) { registry, err := st.storageProviderRegistry() if err != nil { return "", nil, errors.Annotate(err, "getting storage provider registry") } poolManager := poolmanager.New(NewStateSettings(st), registry) pool, err := poolManager.Get(poolName) if errors.IsNotFound(err) { // If there's no pool called poolName, maybe a provider type // has been specified directly. providerType := storage.ProviderType(poolName) provider, err1 := registry.StorageProvider(providerType) if err1 != nil { // The name can't be resolved as a storage provider type, // so return the original "pool not found" error. return "", nil, errors.Trace(err) } return providerType, provider, nil } else if err != nil { return "", nil, errors.Trace(err) } providerType := pool.Provider() provider, err := registry.StorageProvider(providerType) if err != nil { return "", nil, errors.Trace(err) } return providerType, provider, nil }
func constructStartInstanceParams( machine *apiprovisioner.Machine, instanceConfig *instancecfg.InstanceConfig, provisioningInfo *params.ProvisioningInfo, possibleTools coretools.List, ) (environs.StartInstanceParams, error) { volumes := make([]storage.VolumeParams, len(provisioningInfo.Volumes)) for i, v := range provisioningInfo.Volumes { volumeTag, err := names.ParseVolumeTag(v.VolumeTag) if err != nil { return environs.StartInstanceParams{}, errors.Trace(err) } if v.Attachment == nil { return environs.StartInstanceParams{}, errors.Errorf("volume params missing attachment") } machineTag, err := names.ParseMachineTag(v.Attachment.MachineTag) if err != nil { return environs.StartInstanceParams{}, errors.Trace(err) } if machineTag != machine.Tag() { return environs.StartInstanceParams{}, errors.Errorf("volume attachment params has invalid machine tag") } if v.Attachment.InstanceId != "" { return environs.StartInstanceParams{}, errors.Errorf("volume attachment params specifies instance ID") } volumes[i] = storage.VolumeParams{ volumeTag, v.Size, storage.ProviderType(v.Provider), v.Attributes, v.Tags, &storage.VolumeAttachmentParams{ AttachmentParams: storage.AttachmentParams{ Machine: machineTag, ReadOnly: v.Attachment.ReadOnly, }, Volume: volumeTag, }, } } var subnetsToZones map[network.Id][]string if provisioningInfo.SubnetsToZones != nil { // Convert subnet provider ids from string to network.Id. subnetsToZones = make(map[network.Id][]string, len(provisioningInfo.SubnetsToZones)) for providerId, zones := range provisioningInfo.SubnetsToZones { subnetsToZones[network.Id(providerId)] = zones } } return environs.StartInstanceParams{ Constraints: provisioningInfo.Constraints, Tools: possibleTools, InstanceConfig: instanceConfig, Placement: provisioningInfo.Placement, DistributionGroup: machine.DistributionGroup, Volumes: volumes, SubnetsToZones: subnetsToZones, }, nil }
// CreatePool creates a new pool with specified parameters. func (a *API) CreatePool(p params.StoragePool) error { _, err := a.poolManager.Create( p.Name, storage.ProviderType(p.Provider), p.Attrs) return err }
// machineVolumeParams retrieves VolumeParams for the volumes that should be // provisioned with, and attached to, the machine. The client should ignore // parameters that it does not know how to handle. func (p *ProvisionerAPI) machineVolumeParams(m *state.Machine) ([]params.VolumeParams, error) { volumeAttachments, err := m.VolumeAttachments() if err != nil { return nil, err } if len(volumeAttachments) == 0 { return nil, nil } envConfig, err := p.st.EnvironConfig() if err != nil { return nil, err } poolManager := poolmanager.New(state.NewStateSettings(p.st)) allVolumeParams := make([]params.VolumeParams, 0, len(volumeAttachments)) for _, volumeAttachment := range volumeAttachments { volumeTag := volumeAttachment.Volume() volume, err := p.st.Volume(volumeTag) if err != nil { return nil, errors.Annotatef(err, "getting volume %q", volumeTag.Id()) } storageInstance, err := storagecommon.MaybeAssignedStorageInstance( volume.StorageInstance, p.st.StorageInstance, ) if err != nil { return nil, errors.Annotatef(err, "getting volume %q storage instance", volumeTag.Id()) } volumeParams, err := storagecommon.VolumeParams(volume, storageInstance, envConfig, poolManager) if err != nil { return nil, errors.Annotatef(err, "getting volume %q parameters", volumeTag.Id()) } provider, err := registry.StorageProvider(storage.ProviderType(volumeParams.Provider)) if err != nil { return nil, errors.Annotate(err, "getting storage provider") } if provider.Dynamic() { // Leave dynamic storage to the storage provisioner. continue } volumeAttachmentParams, ok := volumeAttachment.Params() if !ok { // Attachment is already provisioned; this is an insane // state, so we should not proceed with the volume. return nil, errors.Errorf( "volume %s already attached to machine %s", volumeTag.Id(), m.Id(), ) } // Not provisioned yet, so ask the cloud provisioner do it. volumeParams.Attachment = ¶ms.VolumeAttachmentParams{ volumeTag.String(), m.Tag().String(), "", // we're creating the volume, so it has no volume ID. "", // we're creating the machine, so it has no instance ID. volumeParams.Provider, volumeAttachmentParams.ReadOnly, } allVolumeParams = append(allVolumeParams, volumeParams) } return allVolumeParams, nil }
func (s *providerRegistrySuite) TestRegisterProvider(c *gc.C) { p1 := &mockProvider{} ptype := storage.ProviderType("foo") registry.RegisterProvider(ptype, p1) p, err := registry.StorageProvider(ptype) c.Assert(err, jc.ErrorIsNil) c.Assert(p, gc.Equals, p1) }
func (s *poolSuite) TestList(c *gc.C) { s.createSettings(c) pools, err := s.poolManager.List() c.Assert(err, jc.ErrorIsNil) c.Assert(pools, gc.HasLen, 1) c.Assert(pools[0].Attrs(), gc.DeepEquals, map[string]interface{}{"foo": "bar"}) c.Assert(pools[0].Name(), gc.Equals, "testpool") c.Assert(pools[0].Provider(), gc.Equals, storage.ProviderType("loop")) }
func (a *API) validateProviderCriteria(providers []string) error { for _, p := range providers { _, err := a.registry.StorageProvider(storage.ProviderType(p)) if err != nil { return errors.Trace(err) } } return nil }
func (s *defaultStoragePoolsSuite) TestDefaultStoragePools(c *gc.C) { 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) settings := state.NewStateSettings(s.State) err = poolmanager.AddDefaultStoragePools(settings) c.Assert(err, jc.ErrorIsNil) pm := poolmanager.New(settings) for _, pool := range defaultPools { p, err := pm.Get(pool.Name()) c.Assert(err, jc.ErrorIsNil) c.Assert(p.Provider(), gc.Equals, pool.Provider()) c.Assert(p.Attrs(), gc.DeepEquals, pool.Attrs()) } }
func (a *API) isValidProviderCriteria(providers []string) (bool, error) { envName, err := a.storage.EnvName() if err != nil { return false, errors.Annotate(err, "getting env name") } for _, p := range providers { if !registry.IsProviderSupported(envName, storage.ProviderType(p)) { return false, errors.NotSupportedf("%q for environment %q", p, envName) } } return true, nil }
func (a *API) validateProviderCriteria(providers []string) error { envName, err := a.storage.ModelName() if err != nil { return errors.Annotate(err, "getting model name") } for _, p := range providers { if !registry.IsProviderSupported(envName, storage.ProviderType(p)) { return errors.NotSupportedf("%q", p) } } return nil }
func (s *defaultStoragePoolsSuite) TestDefaultStoragePools(c *gc.C) { p1, err := storage.NewConfig("pool1", storage.ProviderType("whatever"), map[string]interface{}{"1": "2"}) c.Assert(err, jc.ErrorIsNil) p2, err := storage.NewConfig("pool2", storage.ProviderType("whatever"), map[string]interface{}{"3": "4"}) c.Assert(err, jc.ErrorIsNil) provider := &dummystorage.StorageProvider{ DefaultPools_: []*storage.Config{p1, p2}, } settings := poolmanager.MemSettings{make(map[string]map[string]interface{})} pm := poolmanager.New(settings, storage.StaticProviderRegistry{ map[storage.ProviderType]storage.Provider{"whatever": provider}, }) err = poolmanager.AddDefaultStoragePools(provider, pm) c.Assert(err, jc.ErrorIsNil) c.Assert(settings.Settings, jc.DeepEquals, map[string]map[string]interface{}{ "pool#pool1": map[string]interface{}{"1": "2", "name": "pool1", "type": "whatever"}, "pool#pool2": map[string]interface{}{"3": "4", "name": "pool2", "type": "whatever"}, }) }
func (s *withoutControllerSuite) registerStorageProviders(c *gc.C, names ...string) { types := make([]storage.ProviderType, len(names)) for i, name := range names { types[i] = storage.ProviderType(name) if name == "dynamic" { s.registerDynamicStorageProvider(c) } else if name == "static" { s.registerStaticStorageProvider(c) } else { c.Fatalf("unknown storage provider type: %q, expected static or dynamic", name) } } registry.RegisterEnvironStorageProviders("dummy", types...) }
// StoragePoolConfig returns the storage provider type and // configuration for a named storage pool. If there is no // such pool with the specified name, but it identifies a // storage provider, then that type will be returned with a // nil configuration. func StoragePoolConfig(name string, poolManager poolmanager.PoolManager, registry storage.ProviderRegistry) (storage.ProviderType, *storage.Config, error) { pool, err := poolManager.Get(name) if errors.IsNotFound(err) { // If not a storage pool, then maybe a provider type. providerType := storage.ProviderType(name) if _, err1 := registry.StorageProvider(providerType); err1 != nil { return "", nil, errors.Trace(err) } return providerType, &storage.Config{}, nil } else if err != nil { return "", nil, errors.Annotatef(err, "getting pool %q", name) } return pool.Provider(), pool, nil }
func (i *importer) storagePools() error { registry, err := i.st.storageProviderRegistry() if err != nil { return errors.Annotate(err, "getting provider registry") } pm := poolmanager.New(NewStateSettings(i.st), registry) for _, pool := range i.model.StoragePools() { _, err := pm.Create(pool.Name(), storage.ProviderType(pool.Provider()), pool.Attributes()) if err != nil { return errors.Annotatef(err, "creating pool %q", pool.Name()) } } return nil }
// storageConfig returns the provider type and config attributes for the // specified poolName. If no such pool exists, we check to see if poolName is // actually a provider type, in which case config will be empty. func storageConfig(st *state.State, poolName string) (storage.ProviderType, map[string]interface{}, error) { pm := poolmanager.New(state.NewStateSettings(st)) p, err := pm.Get(poolName) // If not a storage pool, then maybe a provider type. if errors.IsNotFound(err) { providerType := storage.ProviderType(poolName) if _, err1 := registry.StorageProvider(providerType); err1 != nil { return "", nil, errors.Trace(err) } return providerType, nil, nil } if err != nil { return "", nil, errors.Trace(err) } return p.Provider(), p.Attrs(), nil }
func (s *providerRegistrySuite) TestListEnvProviderKnownEnv(c *gc.C) { ptypeFoo := storage.ProviderType("foo") registry.RegisterEnvironStorageProviders("ec2", ptypeFoo) all, exists := registry.EnvironStorageProviders("ec2") c.Assert(exists, jc.IsTrue) c.Assert(len(all) > 0, jc.IsTrue) found := false for _, one := range all { if one == ptypeFoo { found = true break } } c.Assert(found, jc.IsTrue) }
func volumeParamsFromParams(in params.VolumeParams) (storage.VolumeParams, error) { volumeTag, err := names.ParseVolumeTag(in.VolumeTag) if err != nil { return storage.VolumeParams{}, errors.Trace(err) } providerType := storage.ProviderType(in.Provider) var attachment *storage.VolumeAttachmentParams if in.Attachment != nil { if in.Attachment.Provider != in.Provider { return storage.VolumeParams{}, errors.Errorf( "storage provider mismatch: volume (%q), attachment (%q)", in.Provider, in.Attachment.Provider, ) } if in.Attachment.VolumeTag != in.VolumeTag { return storage.VolumeParams{}, errors.Errorf( "volume tag mismatch: volume (%q), attachment (%q)", in.VolumeTag, in.Attachment.VolumeTag, ) } machineTag, err := names.ParseMachineTag(in.Attachment.MachineTag) if err != nil { return storage.VolumeParams{}, errors.Annotate( err, "parsing attachment machine tag", ) } attachment = &storage.VolumeAttachmentParams{ AttachmentParams: storage.AttachmentParams{ Provider: providerType, Machine: machineTag, InstanceId: instance.Id(in.Attachment.InstanceId), ReadOnly: in.Attachment.ReadOnly, }, Volume: volumeTag, } } return storage.VolumeParams{ volumeTag, in.Size, providerType, in.Attributes, in.Tags, attachment, }, nil }
func configFromSettings(settings map[string]interface{}) (*storage.Config, error) { providerType := storage.ProviderType(settings[Type].(string)) name := settings[Name].(string) // Ensure returned attributes are stripped of name and type, // as these are not user-specified attributes. delete(settings, Name) delete(settings, Type) cfg, err := storage.NewConfig(name, providerType, settings) if err != nil { return nil, errors.Trace(err) } p, err := registry.StorageProvider(providerType) if err != nil { return nil, errors.Trace(err) } if err := provider.ValidateConfig(p, cfg); err != nil { return nil, errors.Trace(err) } return cfg, nil }
func volumeAttachmentParamsFromParams(in params.VolumeAttachmentParams) (storage.VolumeAttachmentParams, error) { machineTag, err := names.ParseMachineTag(in.MachineTag) if err != nil { return storage.VolumeAttachmentParams{}, errors.Trace(err) } volumeTag, err := names.ParseVolumeTag(in.VolumeTag) if err != nil { return storage.VolumeAttachmentParams{}, errors.Trace(err) } return storage.VolumeAttachmentParams{ AttachmentParams: storage.AttachmentParams{ Provider: storage.ProviderType(in.Provider), Machine: machineTag, InstanceId: instance.Id(in.InstanceId), ReadOnly: in.ReadOnly, }, Volume: volumeTag, VolumeId: in.VolumeId, }, nil }
func filesystemAttachmentParamsFromParams(in params.FilesystemAttachmentParams) (storage.FilesystemAttachmentParams, error) { machineTag, err := names.ParseMachineTag(in.MachineTag) if err != nil { return storage.FilesystemAttachmentParams{}, errors.Trace(err) } filesystemTag, err := names.ParseFilesystemTag(in.FilesystemTag) if err != nil { return storage.FilesystemAttachmentParams{}, errors.Trace(err) } return storage.FilesystemAttachmentParams{ AttachmentParams: storage.AttachmentParams{ Provider: storage.ProviderType(in.Provider), Machine: machineTag, InstanceId: instance.Id(in.InstanceId), ReadOnly: in.ReadOnly, }, Filesystem: filesystemTag, FilesystemId: in.FilesystemId, Path: in.MountPoint, }, nil }
func filesystemParamsFromParams(in params.FilesystemParams) (storage.FilesystemParams, error) { filesystemTag, err := names.ParseFilesystemTag(in.FilesystemTag) if err != nil { return storage.FilesystemParams{}, errors.Trace(err) } var volumeTag names.VolumeTag if in.VolumeTag != "" { volumeTag, err = names.ParseVolumeTag(in.VolumeTag) if err != nil { return storage.FilesystemParams{}, errors.Trace(err) } } providerType := storage.ProviderType(in.Provider) return storage.FilesystemParams{ filesystemTag, volumeTag, in.Size, providerType, in.Attributes, in.Tags, }, nil }
"github.com/juju/schema" "github.com/juju/utils" "github.com/juju/utils/set" "gopkg.in/amz.v3/ec2" "github.com/juju/juju/constraints" "github.com/juju/juju/environs/config" "github.com/juju/juju/environs/tags" "github.com/juju/juju/instance" "github.com/juju/juju/provider/common" "github.com/juju/juju/storage" "github.com/juju/juju/storage/poolmanager" ) const ( EBS_ProviderType = storage.ProviderType("ebs") // Config attributes // The volume type (default standard): // "gp2" for General Purpose (SSD) volumes // "io1" for Provisioned IOPS (SSD) volumes, // "standard" for Magnetic volumes. EBS_VolumeType = "volume-type" // The number of I/O operations per second (IOPS) per GiB // to provision for the volume. Only valid for Provisioned // IOPS (SSD) volumes. EBS_IOPS = "iops" // Specifies whether the volume should be encrypted.
package provider import ( "os" "path/filepath" "github.com/juju/errors" "github.com/juju/names" "github.com/juju/juju/environs/config" "github.com/juju/juju/storage" ) const ( RootfsProviderType = storage.ProviderType("rootfs") ) // rootfsProviders create storage sources which provide access to filesystems. type rootfsProvider struct { // run is a function type used for running commands on the local machine. run runCommandFunc } var ( _ storage.Provider = (*rootfsProvider)(nil) ) // ValidateConfig is defined on the Provider interface. func (p *rootfsProvider) ValidateConfig(cfg *storage.Config) error { // Rootfs provider has no configuration.
"sync" "time" "github.com/juju/errors" "github.com/juju/utils" "gopkg.in/goose.v1/cinder" "gopkg.in/goose.v1/nova" "github.com/juju/juju/environs/config" "github.com/juju/juju/environs/tags" "github.com/juju/juju/instance" "github.com/juju/juju/storage" ) const ( CinderProviderType = storage.ProviderType("cinder") // autoAssignedMountPoint specifies the value to pass in when // you'd like Cinder to automatically assign a mount point. autoAssignedMountPoint = "" volumeStatusAvailable = "available" volumeStatusDeleting = "deleting" volumeStatusError = "error" volumeStatusInUse = "in-use" ) type cinderProvider struct { newStorageAdapter func(*config.Config) (openstackStorage, error) } var _ storage.Provider = (*cinderProvider)(nil)
func (s *providerRegistrySuite) TestNoSuchProvider(c *gc.C) { _, err := registry.StorageProvider(storage.ProviderType("foo")) c.Assert(err, gc.ErrorMatches, `storage provider "foo" not found`) }