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

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