github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/cmd/juju/storage/filesystem.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 "fmt" 8 9 "github.com/juju/cmd" 10 "github.com/juju/errors" 11 "github.com/juju/names" 12 13 "github.com/juju/juju/apiserver/params" 14 "github.com/juju/juju/cmd/juju/common" 15 ) 16 17 // FilesystemCommandBase is a helper base structure for filesystem commands. 18 type FilesystemCommandBase struct { 19 StorageCommandBase 20 } 21 22 // FilesystemInfo defines the serialization behaviour for storage filesystem. 23 type FilesystemInfo struct { 24 // from params.Filesystem. This is provider-supplied unique filesystem id. 25 ProviderFilesystemId string `yaml:"provider-id,omitempty" json:"provider-id,omitempty"` 26 27 // Volume is the ID of the volume that the filesystem is backed by, if any. 28 Volume string 29 30 // Storage is the ID of the storage instance that the filesystem is 31 // assigned to, if any. 32 Storage string 33 34 // Attachments is the set of entities attached to the filesystem. 35 Attachments *FilesystemAttachments 36 37 // from params.FilesystemInfo 38 Size uint64 `yaml:"size" json:"size"` 39 40 // from params.FilesystemInfo. 41 Status EntityStatus `yaml:"status,omitempty" json:"status,omitempty"` 42 } 43 44 type FilesystemAttachments struct { 45 Machines map[string]MachineFilesystemAttachment `yaml:"machines,omitempty" json:"machines,omitempty"` 46 Units map[string]UnitStorageAttachment `yaml:"units,omitempty" json:"units,omitempty"` 47 } 48 49 type MachineFilesystemAttachment struct { 50 MountPoint string `yaml:"mount-point" json:"mount-point"` 51 ReadOnly bool `yaml:"read-only" json:"read-only"` 52 } 53 54 // generateListFilesystemOutput returns a map filesystem IDs to filesystem info 55 func (c *listCommand) generateListFilesystemsOutput(ctx *cmd.Context, api StorageListAPI) (output interface{}, err error) { 56 57 results, err := api.ListFilesystems(c.ids) 58 if err != nil { 59 return nil, err 60 } 61 62 // filter out valid output, if any 63 var valid []params.FilesystemDetails 64 for _, result := range results { 65 if result.Error == nil { 66 valid = append(valid, result.Result...) 67 continue 68 } 69 // display individual error 70 fmt.Fprintf(ctx.Stderr, "%v\n", result.Error) 71 } 72 if len(valid) == 0 { 73 return nil, nil 74 } 75 info, err := convertToFilesystemInfo(valid) 76 if err != nil { 77 return nil, err 78 } 79 switch c.out.Name() { 80 case "yaml", "json": 81 output = map[string]map[string]FilesystemInfo{"filesystems": info} 82 default: 83 output = info 84 } 85 86 return output, nil 87 } 88 89 // convertToFilesystemInfo returns a map of filesystem IDs to filesystem info. 90 func convertToFilesystemInfo(all []params.FilesystemDetails) (map[string]FilesystemInfo, error) { 91 result := make(map[string]FilesystemInfo) 92 for _, one := range all { 93 filesystemTag, info, err := createFilesystemInfo(one) 94 if err != nil { 95 return nil, errors.Trace(err) 96 } 97 result[filesystemTag.Id()] = info 98 } 99 return result, nil 100 } 101 102 func createFilesystemInfo(details params.FilesystemDetails) (names.FilesystemTag, FilesystemInfo, error) { 103 filesystemTag, err := names.ParseFilesystemTag(details.FilesystemTag) 104 if err != nil { 105 return names.FilesystemTag{}, FilesystemInfo{}, errors.Trace(err) 106 } 107 108 var info FilesystemInfo 109 info.ProviderFilesystemId = details.Info.FilesystemId 110 info.Size = details.Info.Size 111 info.Status = EntityStatus{ 112 details.Status.Status, 113 details.Status.Info, 114 // TODO(axw) we should support formatting as ISO time 115 common.FormatTime(details.Status.Since, false), 116 } 117 118 if details.VolumeTag != "" { 119 volumeId, err := idFromTag(details.VolumeTag) 120 if err != nil { 121 return names.FilesystemTag{}, FilesystemInfo{}, errors.Trace(err) 122 } 123 info.Volume = volumeId 124 } 125 126 if len(details.MachineAttachments) > 0 { 127 machineAttachments := make(map[string]MachineFilesystemAttachment) 128 for machineTag, attachment := range details.MachineAttachments { 129 machineId, err := idFromTag(machineTag) 130 if err != nil { 131 return names.FilesystemTag{}, FilesystemInfo{}, errors.Trace(err) 132 } 133 machineAttachments[machineId] = MachineFilesystemAttachment{ 134 attachment.MountPoint, 135 attachment.ReadOnly, 136 } 137 } 138 info.Attachments = &FilesystemAttachments{ 139 Machines: machineAttachments, 140 } 141 } 142 143 if details.Storage != nil { 144 storageTag, storageInfo, err := createStorageInfo(*details.Storage) 145 if err != nil { 146 return names.FilesystemTag{}, FilesystemInfo{}, errors.Trace(err) 147 } 148 info.Storage = storageTag.Id() 149 if storageInfo.Attachments != nil { 150 info.Attachments.Units = storageInfo.Attachments.Units 151 } 152 } 153 154 return filesystemTag, info, nil 155 }