github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/cmd/juju/storage/storage.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package storage 5 6 import ( 7 "github.com/juju/cmd" 8 "github.com/juju/errors" 9 "github.com/juju/loggo" 10 "github.com/juju/names" 11 12 "github.com/juju/juju/api/storage" 13 "github.com/juju/juju/apiserver/params" 14 "github.com/juju/juju/cmd/envcmd" 15 ) 16 17 var logger = loggo.GetLogger("juju.cmd.juju.storage") 18 19 const storageCmdDoc = ` 20 "juju storage" is used to manage storage instances in 21 the Juju environment. 22 ` 23 24 const storageCmdPurpose = "manage storage instances" 25 26 // NewSuperCommand creates the storage supercommand and 27 // registers the subcommands that it supports. 28 func NewSuperCommand() cmd.Command { 29 storagecmd := cmd.NewSuperCommand( 30 cmd.SuperCommandParams{ 31 Name: "storage", 32 Doc: storageCmdDoc, 33 UsagePrefix: "juju", 34 Purpose: storageCmdPurpose, 35 }) 36 storagecmd.Register(envcmd.Wrap(&ShowCommand{})) 37 storagecmd.Register(envcmd.Wrap(&ListCommand{})) 38 storagecmd.Register(envcmd.Wrap(&AddCommand{})) 39 storagecmd.Register(NewPoolSuperCommand()) 40 storagecmd.Register(NewVolumeSuperCommand()) 41 return storagecmd 42 } 43 44 // StorageCommandBase is a helper base structure that has a method to get the 45 // storage managing client. 46 type StorageCommandBase struct { 47 envcmd.EnvCommandBase 48 } 49 50 // NewStorageAPI returns a storage api for the root api endpoint 51 // that the environment command returns. 52 func (c *StorageCommandBase) NewStorageAPI() (*storage.Client, error) { 53 root, err := c.NewAPIRoot() 54 if err != nil { 55 return nil, err 56 } 57 return storage.NewClient(root), nil 58 } 59 60 // StorageInfo defines the serialization behaviour of the storage information. 61 type StorageInfo struct { 62 StorageName string `yaml:"storage" json:"storage"` 63 Kind string `yaml:"kind" json:"kind"` 64 Status string `yaml:"status,omitempty" json:"status,omitempty"` 65 Persistent bool `yaml:"persistent" json:"persistent"` 66 Location string `yaml:"location,omitempty" json:"location,omitempty"` 67 } 68 69 // formatStorageDetails takes a set of StorageDetail and creates a 70 // mapping keyed on unit and storage id. 71 func formatStorageDetails(storages []params.StorageDetails) (map[string]map[string]StorageInfo, error) { 72 if len(storages) == 0 { 73 return nil, nil 74 } 75 output := make(map[string]map[string]StorageInfo) 76 for _, one := range storages { 77 storageTag, err := names.ParseStorageTag(one.StorageTag) 78 if err != nil { 79 return nil, errors.Annotate(err, "invalid storage tag") 80 } 81 unitTag, err := names.ParseTag(one.UnitTag) 82 if err != nil { 83 return nil, errors.Annotate(err, "invalid unit tag") 84 } 85 86 storageName, err := names.StorageName(storageTag.Id()) 87 if err != nil { 88 panic(err) // impossible 89 } 90 si := StorageInfo{ 91 StorageName: storageName, 92 Kind: one.Kind.String(), 93 Status: one.Status, 94 Location: one.Location, 95 Persistent: one.Persistent, 96 } 97 unit := unitTag.Id() 98 unitColl, ok := output[unit] 99 if !ok { 100 unitColl = map[string]StorageInfo{} 101 output[unit] = unitColl 102 } 103 unitColl[storageTag.Id()] = si 104 } 105 return output, nil 106 }