github.com/vmware/govmomi@v0.51.0/cli/storage/policy/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 policy
     6  
     7  import (
     8  	"context"
     9  	"flag"
    10  	"fmt"
    11  	"io"
    12  	"os"
    13  	"strings"
    14  	"text/tabwriter"
    15  
    16  	"github.com/vmware/govmomi/cli"
    17  	"github.com/vmware/govmomi/cli/flags"
    18  	"github.com/vmware/govmomi/pbm/types"
    19  	"github.com/vmware/govmomi/property"
    20  	vim "github.com/vmware/govmomi/vim25/types"
    21  )
    22  
    23  type info struct {
    24  	*flags.ClientFlag
    25  	*flags.OutputFlag
    26  
    27  	compliance bool
    28  	storage    bool
    29  	iofilters  bool
    30  }
    31  
    32  func init() {
    33  	cli.Register("storage.policy.info", &info{})
    34  }
    35  
    36  func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
    37  	cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
    38  	cmd.ClientFlag.Register(ctx, f)
    39  
    40  	cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
    41  	cmd.OutputFlag.Register(ctx, f)
    42  
    43  	f.BoolVar(&cmd.storage, "s", false, "Check Storage Compatibility")
    44  	f.BoolVar(&cmd.compliance, "c", false, "Check VM Compliance")
    45  
    46  	if cli.ShowUnreleased() {
    47  		f.BoolVar(&cmd.iofilters, "i", false, "Query IO Filters")
    48  	}
    49  }
    50  
    51  func (cmd *info) Process(ctx context.Context) error {
    52  	if err := cmd.ClientFlag.Process(ctx); err != nil {
    53  		return err
    54  	}
    55  	if err := cmd.OutputFlag.Process(ctx); err != nil {
    56  		return err
    57  	}
    58  	return nil
    59  }
    60  
    61  func (cmd *info) Usage() string {
    62  	return "[NAME]"
    63  }
    64  
    65  func (cmd *info) Description() string {
    66  	return `VM Storage Policy info.
    67  
    68  Examples:
    69    govc storage.policy.info
    70    govc storage.policy.info "vSAN Default Storage Policy"
    71    govc storage.policy.info -c -s`
    72  }
    73  
    74  type Policy struct {
    75  	Profile              types.BasePbmProfile            `json:"profile"`
    76  	CompliantVM          []string                        `json:"compliantVM"`
    77  	CompatibleDatastores []string                        `json:"compatibleDatastores"`
    78  	FilterMap            []types.PbmProfileToIofilterMap `json:"filterMap,omitempty"`
    79  }
    80  
    81  type infoResult struct {
    82  	Policies []Policy `json:"policies"`
    83  	cmd      *info
    84  }
    85  
    86  func (r *infoResult) Write(w io.Writer) error {
    87  	tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
    88  
    89  	for _, policy := range r.Policies {
    90  		p := policy.Profile.GetPbmProfile()
    91  		_, _ = fmt.Fprintf(tw, "Name:\t%s\n", p.Name)
    92  		_, _ = fmt.Fprintf(tw, "  ID:\t%s\n", p.ProfileId.UniqueId)
    93  		_, _ = fmt.Fprintf(tw, "  Description:\t%s\n", p.Description)
    94  		if r.cmd.compliance {
    95  			_, _ = fmt.Fprintf(tw, "  Compliant VMs:\t%s\n", strings.Join(policy.CompliantVM, ","))
    96  		}
    97  		if r.cmd.storage {
    98  			_, _ = fmt.Fprintf(tw, "  Compatible Datastores:\t%s\n", strings.Join(policy.CompatibleDatastores, ","))
    99  		}
   100  	}
   101  
   102  	return tw.Flush()
   103  }
   104  
   105  func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
   106  	vc, err := cmd.Client()
   107  	if err != nil {
   108  		return err
   109  	}
   110  
   111  	c, err := cmd.PbmClient()
   112  	if err != nil {
   113  		return err
   114  	}
   115  
   116  	pc := property.DefaultCollector(vc)
   117  
   118  	profiles, err := ListProfiles(ctx, c, f.Arg(0))
   119  	if err != nil {
   120  		return err
   121  	}
   122  
   123  	ds, err := c.DatastoreMap(ctx, vc, vc.ServiceContent.RootFolder)
   124  	if err != nil {
   125  		return err
   126  	}
   127  
   128  	var policies []Policy
   129  
   130  	for _, profile := range profiles {
   131  		p := profile.GetPbmProfile()
   132  
   133  		policy := Policy{
   134  			Profile: profile,
   135  		}
   136  
   137  		if cmd.compliance {
   138  			entities, err := c.QueryAssociatedEntity(ctx, p.ProfileId, string(types.PbmObjectTypeVirtualMachine))
   139  			if err != nil {
   140  				return err
   141  			}
   142  
   143  			if len(entities) == 0 {
   144  				continue
   145  			}
   146  
   147  			res, err := c.FetchComplianceResult(ctx, entities)
   148  			if err != nil {
   149  				return err
   150  			}
   151  
   152  			var refs []vim.ManagedObjectReference
   153  			for _, r := range res {
   154  				if r.ComplianceStatus == string(types.PbmComplianceStatusCompliant) {
   155  					refs = append(refs, vim.ManagedObjectReference{Type: "VirtualMachine", Value: r.Entity.Key})
   156  				}
   157  			}
   158  
   159  			var content []vim.ObjectContent
   160  			err = pc.Retrieve(ctx, refs, []string{"name"}, &content)
   161  			if err != nil {
   162  				return err
   163  			}
   164  
   165  			for _, c := range content {
   166  				policy.CompliantVM = append(policy.CompliantVM, c.PropSet[0].Val.(string))
   167  			}
   168  		}
   169  
   170  		if cmd.storage {
   171  			req := []types.BasePbmPlacementRequirement{
   172  				&types.PbmPlacementCapabilityProfileRequirement{
   173  					ProfileId: p.ProfileId,
   174  				},
   175  			}
   176  
   177  			res, err := c.CheckRequirements(ctx, ds.PlacementHub, nil, req)
   178  			if err != nil {
   179  				return err
   180  			}
   181  
   182  			for _, hub := range res.CompatibleDatastores() {
   183  				policy.CompatibleDatastores = append(policy.CompatibleDatastores, ds.Name[hub.HubId])
   184  			}
   185  		}
   186  
   187  		if cmd.iofilters {
   188  			policy.FilterMap, err = c.QueryIOFiltersFromProfileId(ctx, p.ProfileId.UniqueId)
   189  			if err != nil {
   190  				return err
   191  			}
   192  		}
   193  
   194  		policies = append(policies, policy)
   195  	}
   196  
   197  	return cmd.WriteResult(&infoResult{policies, cmd})
   198  }