github.com/vmware/govmomi@v0.43.0/govc/host/storage/info.go (about)

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