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