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 }