github.com/vmware/govmomi@v0.43.0/govc/library/info.go (about) 1 /* 2 Copyright (c) 2018-2024 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 library 18 19 import ( 20 "context" 21 "encoding/json" 22 "flag" 23 "fmt" 24 "io" 25 "text/tabwriter" 26 "time" 27 28 "github.com/vmware/govmomi/govc/cli" 29 "github.com/vmware/govmomi/govc/flags" 30 "github.com/vmware/govmomi/object" 31 "github.com/vmware/govmomi/units" 32 "github.com/vmware/govmomi/vapi/library" 33 "github.com/vmware/govmomi/vapi/library/finder" 34 ) 35 36 type info struct { 37 *flags.ClientFlag 38 *flags.OutputFlag 39 *flags.DatacenterFlag 40 41 long bool 42 link bool 43 url bool 44 stor bool 45 Stor bool 46 47 pathFinder *finder.PathFinder 48 } 49 50 func init() { 51 cli.Register("library.info", &info{}) 52 } 53 54 func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) { 55 cmd.ClientFlag, ctx = flags.NewClientFlag(ctx) 56 cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx) 57 cmd.ClientFlag.Register(ctx, f) 58 cmd.OutputFlag.Register(ctx, f) 59 cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx) 60 cmd.DatacenterFlag.Register(ctx, f) 61 62 f.BoolVar(&cmd.long, "l", false, "Long listing format") 63 f.BoolVar(&cmd.link, "L", false, "List Datastore path only") 64 f.BoolVar(&cmd.url, "U", false, "List pub/sub URL(s) only") 65 f.BoolVar(&cmd.stor, "s", false, "Include file specific storage details") 66 if cli.ShowUnreleased() { 67 f.BoolVar(&cmd.Stor, "S", false, "Include file specific storage details (resolved)") 68 } 69 } 70 71 func (cmd *info) Process(ctx context.Context) error { 72 if err := cmd.ClientFlag.Process(ctx); err != nil { 73 return err 74 } 75 return nil 76 } 77 78 func (cmd *info) Description() string { 79 return `Display library information. 80 81 Note: the '-s' flag only applies to files, not items or the library itself. 82 83 Examples: 84 govc library.info 85 govc library.info /lib1 86 govc library.info -l /lib1 | grep Size: 87 govc library.info /lib1/item1 88 govc library.info /lib1/item1/ 89 govc library.info */ 90 govc library.info -L /lib1/item1/file1 # file path relative to Datastore 91 govc library.info -L -l /lib1/item1/file1 # file path including Datastore 92 govc library.info -json | jq . 93 govc library.info -json /lib1/item1 | jq .` 94 } 95 96 type infoResultsWriter struct { 97 Result []finder.FindResult `json:"result"` 98 m *library.Manager 99 cmd *info 100 ctx context.Context 101 } 102 103 func (r infoResultsWriter) MarshalJSON() ([]byte, error) { 104 return json.Marshal(r.Result) 105 } 106 107 func (r infoResultsWriter) Dump() interface{} { 108 res := make([]interface{}, len(r.Result)) 109 for i := range r.Result { 110 res[i] = r.Result[0].GetResult() 111 } 112 return res 113 } 114 115 func (r infoResultsWriter) Write(w io.Writer) error { 116 if r.cmd.link { 117 for _, j := range r.Result { 118 p, err := r.cmd.pathFinder.Path(context.Background(), j) 119 if err != nil { 120 return err 121 } 122 if !r.cmd.long { 123 var path object.DatastorePath 124 path.FromString(p) 125 p = path.Path 126 } 127 fmt.Fprintln(w, p) 128 } 129 return nil 130 } 131 132 tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0) 133 defer tw.Flush() 134 for _, j := range r.Result { 135 switch t := j.GetResult().(type) { 136 case library.Library: 137 if err := r.writeLibrary(tw, t, j); err != nil { 138 return err 139 } 140 case library.Item: 141 if err := r.writeItem(tw, t, j); err != nil { 142 return err 143 } 144 case library.File: 145 if err := r.writeFile(tw, t, j); err != nil { 146 return err 147 } 148 } 149 tw.Flush() 150 } 151 return nil 152 } 153 154 func (r infoResultsWriter) writeLibrary( 155 w io.Writer, v library.Library, res finder.FindResult) error { 156 157 published := v.Publication != nil && *v.Publication.Published 158 159 if r.cmd.url { 160 switch { 161 case v.Subscription != nil: 162 _, _ = fmt.Fprintf(w, "%s\n", v.Subscription.SubscriptionURL) 163 case published: 164 _, _ = fmt.Fprintf(w, "%s\n", v.Publication.PublishURL) 165 } 166 167 return nil 168 } 169 170 fmt.Fprintf(w, "Name:\t%s\n", v.Name) 171 fmt.Fprintf(w, " ID:\t%s\n", v.ID) 172 fmt.Fprintf(w, " Path:\t%s\n", res.GetPath()) 173 if v.Description != nil { 174 fmt.Fprintf(w, " Description:\t%s\n", *v.Description) 175 } 176 fmt.Fprintf(w, " Version:\t%s\n", v.Version) 177 fmt.Fprintf(w, " Created:\t%s\n", v.CreationTime.Format(time.ANSIC)) 178 fmt.Fprintf(w, " Security Policy ID\t%s\n", v.SecurityPolicyID) 179 fmt.Fprintf(w, " StorageBackings:\t\n") 180 for _, d := range v.Storage { 181 fmt.Fprintf(w, " DatastoreID:\t%s\n", d.DatastoreID) 182 fmt.Fprintf(w, " Type:\t%s\n", d.Type) 183 } 184 if r.cmd.long { 185 p, err := r.cmd.pathFinder.Path(r.ctx, res) 186 if err != nil { 187 return err 188 } 189 fmt.Fprintf(w, " Datastore Path:\t%s\n", p) 190 items, err := r.m.GetLibraryItems(r.ctx, v.ID) 191 if err != nil { 192 return err 193 } 194 var size int64 195 for i := range items { 196 size += items[i].Size 197 } 198 fmt.Fprintf(w, " Size:\t%s\n", units.ByteSize(size)) 199 fmt.Fprintf(w, " Items:\t%d\n", len(items)) 200 } 201 if v.Subscription != nil { 202 dl := "All" 203 if v.Subscription.OnDemand != nil && *v.Subscription.OnDemand { 204 dl = "On Demand" 205 } 206 207 fmt.Fprintf(w, " Subscription:\t\n") 208 fmt.Fprintf(w, " AutoSync:\t%t\n", *v.Subscription.AutomaticSyncEnabled) 209 fmt.Fprintf(w, " URL:\t%s\n", v.Subscription.SubscriptionURL) 210 fmt.Fprintf(w, " Auth:\t%s\n", v.Subscription.AuthenticationMethod) 211 fmt.Fprintf(w, " Download:\t%s\n", dl) 212 } 213 if published { 214 fmt.Fprintf(w, " Publication:\t\n") 215 fmt.Fprintf(w, " URL:\t%s\n", v.Publication.PublishURL) 216 fmt.Fprintf(w, " Auth:\t%s\n", v.Publication.AuthenticationMethod) 217 } 218 return nil 219 } 220 221 func (r infoResultsWriter) writeItem( 222 w io.Writer, v library.Item, res finder.FindResult) error { 223 224 fmt.Fprintf(w, "Name:\t%s\n", v.Name) 225 fmt.Fprintf(w, " ID:\t%s\n", v.ID) 226 fmt.Fprintf(w, " Path:\t%s\n", res.GetPath()) 227 if v.Description != nil { 228 fmt.Fprintf(w, " Description:\t%s\n", *v.Description) 229 } 230 fmt.Fprintf(w, " Type:\t%s\n", v.Type) 231 fmt.Fprintf(w, " Size:\t%s\n", units.ByteSize(v.Size)) 232 fmt.Fprintf(w, " Cached:\t%t\n", v.Cached) 233 fmt.Fprintf(w, " Created:\t%s\n", v.CreationTime.Format(time.ANSIC)) 234 fmt.Fprintf(w, " Modified:\t%s\n", v.LastModifiedTime.Format(time.ANSIC)) 235 fmt.Fprintf(w, " Version:\t%s\n", v.Version) 236 if v.SecurityCompliance != nil { 237 fmt.Fprintf(w, " Security Compliance:\t%t\n", *v.SecurityCompliance) 238 } 239 if v.CertificateVerification != nil { 240 fmt.Fprintf(w, " Certificate Status:\t%s\n", v.CertificateVerification.Status) 241 } 242 if r.cmd.long { 243 p, err := r.cmd.pathFinder.Path(r.ctx, res) 244 if err != nil { 245 return err 246 } 247 fmt.Fprintf(w, " Datastore Path:\t%s\n", p) 248 } 249 250 return nil 251 } 252 253 func (r infoResultsWriter) writeFile( 254 w io.Writer, v library.File, res finder.FindResult) error { 255 256 size := "-" 257 if v.Size != nil { 258 size = units.ByteSize(*v.Size).String() 259 } 260 fmt.Fprintf(w, "Name:\t%s\n", v.Name) 261 fmt.Fprintf(w, " Path:\t%s\n", res.GetPath()) 262 fmt.Fprintf(w, " Size:\t%s\n", size) 263 fmt.Fprintf(w, " Version:\t%s\n", v.Version) 264 265 if r.cmd.long { 266 p, err := r.cmd.pathFinder.Path(r.ctx, res) 267 if err != nil { 268 return err 269 } 270 fmt.Fprintf(w, " Datastore Path:\t%s\n", p) 271 } 272 if r.cmd.stor || r.cmd.Stor { 273 label := "Storage URI" 274 s, err := r.m.GetLibraryItemStorage(r.ctx, res.GetParent().GetID(), v.Name) 275 if err != nil { 276 return err 277 } 278 if r.cmd.Stor { 279 label = "Resolved URI" 280 err = r.cmd.pathFinder.ResolveLibraryItemStorage(r.ctx, s) 281 if err != nil { 282 return err 283 } 284 } 285 for i := range s { 286 for _, uri := range s[i].StorageURIs { 287 fmt.Fprintf(w, " %s:\t%s\n", label, uri) 288 } 289 } 290 } 291 292 return nil 293 } 294 295 func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error { 296 c, err := cmd.RestClient() 297 if err != nil { 298 return err 299 } 300 vc, err := cmd.Client() 301 if err != nil { 302 return err 303 } 304 305 m := library.NewManager(c) 306 cmd.pathFinder = finder.NewPathFinder(m, vc) 307 finder := finder.NewFinder(m) 308 findResults, err := finder.Find(ctx, f.Args()...) 309 if err != nil { 310 return err 311 } 312 313 return cmd.WriteResult(&infoResultsWriter{findResults, m, cmd, ctx}) 314 }