github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/cmd/juju/storage/volume.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/names" 10 11 "github.com/juju/juju/apiserver/params" 12 jujucmd "github.com/juju/juju/cmd" 13 "github.com/juju/juju/cmd/envcmd" 14 ) 15 16 const volumeCmdDoc = ` 17 "juju storage volume" is used to manage storage volumes in 18 the Juju environment. 19 ` 20 21 const volumeCmdPurpose = "manage storage volumes" 22 23 // NewVolumeSuperCommand creates the storage volume super subcommand and 24 // registers the subcommands that it supports. 25 func NewVolumeSuperCommand() cmd.Command { 26 poolcmd := Command{ 27 SuperCommand: *jujucmd.NewSubSuperCommand(cmd.SuperCommandParams{ 28 Name: "volume", 29 Doc: volumeCmdDoc, 30 UsagePrefix: "juju storage", 31 Purpose: volumeCmdPurpose, 32 })} 33 poolcmd.Register(envcmd.Wrap(&VolumeListCommand{})) 34 return &poolcmd 35 } 36 37 // VolumeCommandBase is a helper base structure for volume commands. 38 type VolumeCommandBase struct { 39 StorageCommandBase 40 } 41 42 // VolumeInfo defines the serialization behaviour for storage volume. 43 type VolumeInfo struct { 44 // from params.Volume. This is provider-supplied unique volume id. 45 VolumeId string `yaml:"id" json:"id"` 46 47 // from params.Volume 48 HardwareId string `yaml:"hardwareid" json:"hardwareid"` 49 50 // from params.Volume 51 Size uint64 `yaml:"size" json:"size"` 52 53 // from params.Volume 54 Persistent bool `yaml:"persistent" json:"persistent"` 55 56 // from params.VolumeAttachments 57 DeviceName string `yaml:"device,omitempty" json:"device,omitempty"` 58 59 // from params.VolumeAttachments 60 ReadOnly bool `yaml:"read-only" json:"read-only"` 61 62 // from params.Volume. This is juju volume id. 63 Volume string `yaml:"volume,omitempty" json:"volume,omitempty"` 64 } 65 66 // convertToVolumeInfo returns map of maps with volume info 67 // keyed first on machine_id and then on volume_id. 68 func convertToVolumeInfo(all []params.VolumeItem) (map[string]map[string]map[string]VolumeInfo, error) { 69 result := map[string]map[string]map[string]VolumeInfo{} 70 for _, one := range all { 71 if err := convertVolumeItem(one, result); err != nil { 72 return nil, errors.Trace(err) 73 } 74 } 75 return result, nil 76 } 77 78 func convertVolumeItem(item params.VolumeItem, all map[string]map[string]map[string]VolumeInfo) error { 79 if len(item.Attachments) != 0 { 80 // add info for volume attachments 81 return convertVolumeAttachments(item, all) 82 } 83 unattached, unit, storage := createInfo(item.Volume) 84 addOneToAll("unattached", unit, storage, unattached, all) 85 return nil 86 } 87 88 var idFromTag = func(s string) (string, error) { 89 tag, err := names.ParseTag(s) 90 if err != nil { 91 return "", errors.Annotatef(err, "invalid tag %v", tag) 92 } 93 return tag.Id(), nil 94 } 95 96 func convertVolumeAttachments(item params.VolumeItem, all map[string]map[string]map[string]VolumeInfo) error { 97 for _, one := range item.Attachments { 98 machine, err := idFromTag(one.MachineTag) 99 if err != nil { 100 return errors.Trace(err) 101 } 102 info, unit, storage := createInfo(item.Volume) 103 info.DeviceName = one.Info.DeviceName 104 info.ReadOnly = one.Info.ReadOnly 105 106 addOneToAll(machine, unit, storage, info, all) 107 } 108 return nil 109 } 110 111 func addOneToAll(machineId, unitId, storageId string, item VolumeInfo, all map[string]map[string]map[string]VolumeInfo) { 112 machineVolumes, ok := all[machineId] 113 if !ok { 114 machineVolumes = map[string]map[string]VolumeInfo{} 115 all[machineId] = machineVolumes 116 } 117 unitVolumes, ok := machineVolumes[unitId] 118 if !ok { 119 unitVolumes = map[string]VolumeInfo{} 120 machineVolumes[unitId] = unitVolumes 121 } 122 unitVolumes[storageId] = item 123 } 124 125 func createInfo(volume params.VolumeInstance) (info VolumeInfo, unit, storage string) { 126 info.VolumeId = volume.VolumeId 127 info.HardwareId = volume.HardwareId 128 info.Size = volume.Size 129 info.Persistent = volume.Persistent 130 131 if v, err := idFromTag(volume.VolumeTag); err == nil { 132 info.Volume = v 133 } 134 var err error 135 if storage, err = idFromTag(volume.StorageTag); err != nil { 136 storage = "unassigned" 137 } 138 if unit, err = idFromTag(volume.UnitTag); err != nil { 139 unit = "unattached" 140 } 141 return 142 }