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 }