github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/storage/import.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package storage 5 6 import ( 7 "regexp" 8 9 "gopkg.in/juju/names.v2" 10 11 "github.com/juju/cmd" 12 "github.com/juju/errors" 13 14 apistorage "github.com/juju/juju/api/storage" 15 jujucmd "github.com/juju/juju/cmd" 16 "github.com/juju/juju/cmd/modelcmd" 17 "github.com/juju/juju/jujuclient" 18 "github.com/juju/juju/storage" 19 ) 20 21 // NewImportFilesystemCommand returns a command used to import a filesystem. 22 // 23 // newStorageImporter is the function to use to acquire a StorageImporter. 24 // A non-nil function must be provided. 25 // 26 // store is an optional ClientStore to use for interacting with the client 27 // model/controller storage. If nil, the default file-based store will be 28 // used. 29 func NewImportFilesystemCommand( 30 newStorageImporter NewStorageImporterFunc, 31 store jujuclient.ClientStore, 32 ) cmd.Command { 33 cmd := &importFilesystemCommand{} 34 cmd.newAPIFunc = newStorageImporter 35 if store != nil { 36 cmd.SetClientStore(store) 37 } 38 return modelcmd.Wrap(cmd) 39 } 40 41 // NewStorageImporterFunc is the type of a function passed to 42 // NewImportFilesystemCommand, in order to acquire a StorageImporter. 43 type NewStorageImporterFunc func(*StorageCommandBase) (StorageImporter, error) 44 45 // NewStorageImporter returns a new StorageImporter, 46 // given a StorageCommandBase. 47 func NewStorageImporter(cmd *StorageCommandBase) (StorageImporter, error) { 48 api, err := cmd.NewStorageAPI() 49 return apiStorageImporter{api}, err 50 } 51 52 const ( 53 importFilesystemCommandDoc = ` 54 Import an existing filesystem into the model. This will lead to the model 55 taking ownership of the storage, so you must take care not to import storage 56 that is in use by another Juju model. 57 58 To import a filesystem, you must specify three things: 59 60 - the storage provider which manages the storage, and with 61 which the storage will be associated 62 - the storage provider ID for the filesystem, or 63 volume that backs the filesystem 64 - the storage name to assign to the filesystem, 65 corresponding to the storage name used by a charm 66 67 Once a filesystem is imported, Juju will create an associated storage 68 instance using the given storage name. 69 70 Examples: 71 # Import an existing filesystem backed by an EBS volume, 72 # and assign it the "pgdata" storage name. Juju will 73 # associate a storage instance ID like "pgdata/0" with 74 # the volume and filesystem contained within. 75 juju import-filesystem ebs vol-123456 pgdata 76 ` 77 importFilesystemCommandAgs = ` 78 <storage-provider> <provider-id> <storage-name> 79 ` 80 ) 81 82 // importFilesystemCommand imports filesystems into the model. 83 type importFilesystemCommand struct { 84 StorageCommandBase 85 modelcmd.IAASOnlyCommand 86 newAPIFunc NewStorageImporterFunc 87 88 storagePool string 89 storageProviderId string 90 storageName string 91 } 92 93 // Init implements Command.Init. 94 func (c *importFilesystemCommand) Init(args []string) error { 95 if len(args) < 3 { 96 return errors.New("import-filesystem requires a storage provider, provider ID, and storage name") 97 } 98 c.storagePool = args[0] 99 c.storageProviderId = args[1] 100 c.storageName = args[2] 101 102 if !storage.IsValidPoolName(c.storagePool) { 103 return errors.NotValidf("pool name %q", c.storagePool) 104 } 105 106 validStorageName, err := regexp.MatchString(names.StorageNameSnippet, c.storageName) 107 if err != nil { 108 return errors.Trace(err) 109 } 110 if !validStorageName { 111 return errors.Errorf("%q is not a valid storage name", c.storageName) 112 } 113 return nil 114 } 115 116 // Info implements Command.Info. 117 func (c *importFilesystemCommand) Info() *cmd.Info { 118 return jujucmd.Info(&cmd.Info{ 119 Name: "import-filesystem", 120 Purpose: "Imports a filesystem into the model.", 121 Doc: importFilesystemCommandDoc, 122 Args: importFilesystemCommandAgs, 123 }) 124 } 125 126 // Run implements Command.Run. 127 func (c *importFilesystemCommand) Run(ctx *cmd.Context) (err error) { 128 api, err := c.newAPIFunc(&c.StorageCommandBase) 129 if err != nil { 130 return err 131 } 132 defer api.Close() 133 134 ctx.Infof( 135 "importing %q from storage pool %q as storage %q", 136 c.storageProviderId, c.storagePool, c.storageName, 137 ) 138 storageTag, err := api.ImportStorage( 139 storage.StorageKindFilesystem, 140 c.storagePool, c.storageProviderId, c.storageName, 141 ) 142 if err != nil { 143 return err 144 } 145 ctx.Infof("imported storage %s", storageTag.Id()) 146 return nil 147 } 148 149 // StorageImporter provides a method for importing storage into the model. 150 type StorageImporter interface { 151 Close() error 152 153 ImportStorage( 154 kind storage.StorageKind, 155 storagePool, storageProviderId, storageName string, 156 ) (names.StorageTag, error) 157 } 158 159 type apiStorageImporter struct { 160 *apistorage.Client 161 } 162 163 func (a apiStorageImporter) ImportStorage( 164 kind storage.StorageKind, storagePool, storageProviderId, storageName string, 165 ) (names.StorageTag, error) { 166 return a.Import(kind, storagePool, storageProviderId, storageName) 167 }