github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/juju/storage/volumelistformatters.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 "io" 9 "sort" 10 "strings" 11 12 "github.com/dustin/go-humanize" 13 "github.com/juju/juju/cmd/output" 14 ) 15 16 // formatVolumeListTabular returns a tabular summary of volume instances. 17 func formatVolumeListTabular(writer io.Writer, infos map[string]VolumeInfo) error { 18 tw := output.TabWriter(writer) 19 20 print := func(values ...string) { 21 fmt.Fprintln(tw, strings.Join(values, "\t")) 22 } 23 print("MACHINE", "UNIT", "STORAGE", "ID", "PROVIDER-ID", "DEVICE", "SIZE", "STATE", "MESSAGE") 24 25 volumeAttachmentInfos := make(volumeAttachmentInfos, 0, len(infos)) 26 for volumeId, info := range infos { 27 volumeAttachmentInfo := volumeAttachmentInfo{ 28 VolumeId: volumeId, 29 VolumeInfo: info, 30 } 31 if info.Attachments == nil { 32 volumeAttachmentInfos = append(volumeAttachmentInfos, volumeAttachmentInfo) 33 continue 34 } 35 // Each unit attachment must have a corresponding volume 36 // attachment. Enumerate each of the volume attachments, 37 // and locate the corresponding unit attachment if any. 38 // Each volume attachment has at most one corresponding 39 // unit attachment. 40 for machineId, machineInfo := range info.Attachments.Machines { 41 volumeAttachmentInfo := volumeAttachmentInfo 42 volumeAttachmentInfo.MachineId = machineId 43 volumeAttachmentInfo.MachineVolumeAttachment = machineInfo 44 for unitId, unitInfo := range info.Attachments.Units { 45 if unitInfo.MachineId == machineId { 46 volumeAttachmentInfo.UnitId = unitId 47 volumeAttachmentInfo.UnitStorageAttachment = unitInfo 48 break 49 } 50 } 51 volumeAttachmentInfos = append(volumeAttachmentInfos, volumeAttachmentInfo) 52 } 53 } 54 sort.Sort(volumeAttachmentInfos) 55 56 for _, info := range volumeAttachmentInfos { 57 var size string 58 if info.Size > 0 { 59 size = humanize.IBytes(info.Size * humanize.MiByte) 60 } 61 print( 62 info.MachineId, info.UnitId, info.Storage, 63 info.VolumeId, info.ProviderVolumeId, 64 info.DeviceName, size, 65 string(info.Status.Current), info.Status.Message, 66 ) 67 } 68 69 return tw.Flush() 70 } 71 72 type volumeAttachmentInfo struct { 73 VolumeId string 74 VolumeInfo 75 76 MachineId string 77 MachineVolumeAttachment 78 79 UnitId string 80 UnitStorageAttachment 81 } 82 83 type volumeAttachmentInfos []volumeAttachmentInfo 84 85 func (v volumeAttachmentInfos) Len() int { 86 return len(v) 87 } 88 89 func (v volumeAttachmentInfos) Swap(i, j int) { 90 v[i], v[j] = v[j], v[i] 91 } 92 93 func (v volumeAttachmentInfos) Less(i, j int) bool { 94 switch compareStrings(v[i].MachineId, v[j].MachineId) { 95 case -1: 96 return true 97 case 1: 98 return false 99 } 100 101 switch compareSlashSeparated(v[i].UnitId, v[j].UnitId) { 102 case -1: 103 return true 104 case 1: 105 return false 106 } 107 108 switch compareSlashSeparated(v[i].Storage, v[j].Storage) { 109 case -1: 110 return true 111 case 1: 112 return false 113 } 114 115 return v[i].VolumeId < v[j].VolumeId 116 }