github.com/vmware/govmomi@v0.51.0/cli/host/storage/info.go (about) 1 // © Broadcom. All Rights Reserved. 2 // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 3 // SPDX-License-Identifier: Apache-2.0 4 5 package storage 6 7 import ( 8 "context" 9 "flag" 10 "fmt" 11 "io" 12 "strings" 13 "text/tabwriter" 14 15 "github.com/vmware/govmomi/cli" 16 "github.com/vmware/govmomi/cli/flags" 17 "github.com/vmware/govmomi/units" 18 "github.com/vmware/govmomi/vim25/mo" 19 "github.com/vmware/govmomi/vim25/types" 20 ) 21 22 var infoTypes = []string{"hba", "lun"} 23 24 type infoType string 25 26 func (t *infoType) Set(s string) error { 27 s = strings.ToLower(s) 28 29 for _, e := range infoTypes { 30 if s == e { 31 *t = infoType(s) 32 return nil 33 } 34 } 35 36 return fmt.Errorf("invalid type") 37 } 38 39 func (t *infoType) String() string { 40 return string(*t) 41 } 42 43 func (t *infoType) Result(hss mo.HostStorageSystem) flags.OutputWriter { 44 switch string(*t) { 45 case "hba": 46 return hbaResult(hss) 47 case "lun": 48 return lunResult(hss) 49 default: 50 panic("unsupported") 51 } 52 } 53 54 type info struct { 55 *flags.HostSystemFlag 56 *flags.OutputFlag 57 58 typ infoType 59 rescan bool 60 refresh bool 61 rescanvmfs bool 62 unclaimed bool 63 } 64 65 func init() { 66 cli.Register("host.storage.info", &info{}) 67 } 68 69 func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) { 70 cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx) 71 cmd.HostSystemFlag.Register(ctx, f) 72 cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx) 73 cmd.OutputFlag.Register(ctx, f) 74 75 err := cmd.typ.Set("lun") 76 if err != nil { 77 panic(err) 78 } 79 80 f.Var(&cmd.typ, "t", fmt.Sprintf("Type (%s)", strings.Join(infoTypes, ","))) 81 82 f.BoolVar(&cmd.rescan, "rescan", false, "Rescan all host bus adapters") 83 f.BoolVar(&cmd.refresh, "refresh", false, "Refresh the storage system provider") 84 f.BoolVar(&cmd.rescanvmfs, "rescan-vmfs", false, "Rescan for new VMFSs") 85 f.BoolVar(&cmd.unclaimed, "unclaimed", false, "Only show disks that can be used as new VMFS datastores") 86 } 87 88 func (cmd *info) Description() string { 89 return `Show HOST storage system information. 90 91 Examples: 92 govc find / -type h | xargs -n1 govc host.storage.info -unclaimed -host` 93 } 94 95 func (cmd *info) Process(ctx context.Context) error { 96 if err := cmd.HostSystemFlag.Process(ctx); err != nil { 97 return err 98 } 99 if err := cmd.OutputFlag.Process(ctx); err != nil { 100 return err 101 } 102 return nil 103 } 104 105 func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error { 106 host, err := cmd.HostSystem() 107 if err != nil { 108 return err 109 } 110 111 ss, err := host.ConfigManager().StorageSystem(ctx) 112 if err != nil { 113 return err 114 } 115 116 if cmd.rescan { 117 err = ss.RescanAllHba(ctx) 118 if err != nil { 119 return err 120 } 121 } 122 123 if cmd.refresh { 124 err = ss.Refresh(ctx) 125 if err != nil { 126 return err 127 } 128 } 129 130 if cmd.rescanvmfs { 131 err = ss.RescanVmfs(ctx) 132 if err != nil { 133 return err 134 } 135 } 136 137 var hss mo.HostStorageSystem 138 err = ss.Properties(ctx, ss.Reference(), nil, &hss) 139 if err != nil { 140 return nil 141 } 142 143 if cmd.unclaimed { 144 ds, err := host.ConfigManager().DatastoreSystem(ctx) 145 if err != nil { 146 return err 147 } 148 149 disks, err := ds.QueryAvailableDisksForVmfs(ctx) 150 if err != nil { 151 return err 152 } 153 154 var luns []types.BaseScsiLun 155 for i := range disks { 156 luns = append(luns, &disks[i]) 157 } 158 hss.StorageDeviceInfo.ScsiLun = luns 159 } 160 161 return cmd.WriteResult(cmd.typ.Result(hss)) 162 } 163 164 type hbaResult mo.HostStorageSystem 165 166 func (r hbaResult) Write(w io.Writer) error { 167 tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0) 168 169 fmt.Fprintf(tw, "Device\t") 170 fmt.Fprintf(tw, "PCI\t") 171 fmt.Fprintf(tw, "Driver\t") 172 fmt.Fprintf(tw, "Status\t") 173 fmt.Fprintf(tw, "Model\t") 174 fmt.Fprintf(tw, "\n") 175 176 for _, e := range r.StorageDeviceInfo.HostBusAdapter { 177 hba := e.GetHostHostBusAdapter() 178 179 fmt.Fprintf(tw, "%s\t", hba.Device) 180 fmt.Fprintf(tw, "%s\t", hba.Pci) 181 fmt.Fprintf(tw, "%s\t", hba.Driver) 182 fmt.Fprintf(tw, "%s\t", hba.Status) 183 fmt.Fprintf(tw, "%s\t", hba.Model) 184 fmt.Fprintf(tw, "\n") 185 } 186 187 return tw.Flush() 188 } 189 190 type lunResult mo.HostStorageSystem 191 192 func (r lunResult) Write(w io.Writer) error { 193 tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0) 194 195 fmt.Fprintf(tw, "Name\t") 196 fmt.Fprintf(tw, "Type\t") 197 fmt.Fprintf(tw, "Capacity\t") 198 fmt.Fprintf(tw, "Model\t") 199 fmt.Fprintf(tw, "\n") 200 201 for _, e := range r.StorageDeviceInfo.ScsiLun { 202 var tags []string 203 var capacity int64 204 205 lun := e.GetScsiLun() 206 if disk, ok := e.(*types.HostScsiDisk); ok { 207 capacity = int64(disk.Capacity.Block) * int64(disk.Capacity.BlockSize) 208 if disk.LocalDisk != nil && *disk.LocalDisk { 209 tags = append(tags, "local") 210 } 211 if disk.Ssd != nil && *disk.Ssd { 212 tags = append(tags, "ssd") 213 } 214 } 215 216 fmt.Fprintf(tw, "%s\t", lun.DeviceName) 217 fmt.Fprintf(tw, "%s\t", lun.DeviceType) 218 219 if capacity == 0 { 220 fmt.Fprintf(tw, "-\t") 221 } else { 222 fmt.Fprintf(tw, "%s\t", units.ByteSize(capacity)) 223 } 224 225 fmt.Fprintf(tw, "%s", lun.Model) 226 if len(tags) > 0 { 227 fmt.Fprintf(tw, " (%s)", strings.Join(tags, ",")) 228 } 229 fmt.Fprintf(tw, "\n") 230 } 231 232 return tw.Flush() 233 }