github.com/vmware/govmomi@v0.43.0/govc/disk/ls.go (about) 1 /* 2 Copyright (c) 2018-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 disk 18 19 import ( 20 "context" 21 "flag" 22 "fmt" 23 "io" 24 "strings" 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/units" 31 "github.com/vmware/govmomi/vim25/soap" 32 "github.com/vmware/govmomi/vim25/types" 33 "github.com/vmware/govmomi/vslm" 34 ) 35 36 type ls struct { 37 *flags.DatastoreFlag 38 long bool 39 path bool 40 r bool 41 category string 42 tag string 43 tags bool 44 } 45 46 func init() { 47 cli.Register("disk.ls", &ls{}) 48 } 49 50 func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) { 51 cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx) 52 cmd.DatastoreFlag.Register(ctx, f) 53 54 f.BoolVar(&cmd.long, "l", false, "Long listing format") 55 f.BoolVar(&cmd.path, "L", false, "Print disk backing path instead of disk name") 56 f.BoolVar(&cmd.r, "R", false, "Reconcile the datastore inventory info") 57 f.StringVar(&cmd.category, "c", "", "Query tag category") 58 f.StringVar(&cmd.tag, "t", "", "Query tag name") 59 f.BoolVar(&cmd.tags, "T", false, "List attached tags") 60 } 61 62 func (cmd *ls) Usage() string { 63 return "[ID]..." 64 } 65 66 func (cmd *ls) Description() string { 67 return `List disk IDs on DS. 68 69 Examples: 70 govc disk.ls 71 govc disk.ls -l -T 72 govc disk.ls -l e9b06a8b-d047-4d3c-b15b-43ea9608b1a6 73 govc disk.ls -c k8s-region -t us-west-2` 74 } 75 76 type VStorageObject struct { 77 types.VStorageObject 78 Tags []types.VslmTagEntry `json:"tags"` 79 } 80 81 func (o *VStorageObject) tags() string { 82 var tags []string 83 for _, tag := range o.Tags { 84 tags = append(tags, tag.ParentCategoryName+":"+tag.TagName) 85 } 86 return strings.Join(tags, ",") 87 } 88 89 type lsResult struct { 90 cmd *ls 91 Objects []VStorageObject `json:"objects"` 92 } 93 94 func (r *lsResult) Write(w io.Writer) error { 95 tw := tabwriter.NewWriter(r.cmd.Out, 2, 0, 2, ' ', 0) 96 97 for _, o := range r.Objects { 98 name := o.Config.Name 99 if r.cmd.path { 100 if file, ok := o.Config.Backing.(*types.BaseConfigInfoDiskFileBackingInfo); ok { 101 name = file.FilePath 102 } 103 } 104 _, _ = fmt.Fprintf(tw, "%s\t%s", o.Config.Id.Id, name) 105 if r.cmd.long { 106 created := o.Config.CreateTime.Format(time.Stamp) 107 size := units.FileSize(o.Config.CapacityInMB * 1024 * 1024) 108 _, _ = fmt.Fprintf(tw, "\t%s\t%s", size, created) 109 } 110 if r.cmd.tags { 111 _, _ = fmt.Fprintf(tw, "\t%s", o.tags()) 112 } 113 _, _ = fmt.Fprintln(tw) 114 } 115 116 return tw.Flush() 117 } 118 119 func (r *lsResult) Dump() interface{} { 120 return r.Objects 121 } 122 123 func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error { 124 c, err := cmd.Client() 125 if err != nil { 126 return err 127 } 128 129 ds, err := cmd.Datastore() 130 if err != nil { 131 return err 132 } 133 134 m := vslm.NewObjectManager(c) 135 if cmd.r { 136 task, err := m.ReconcileDatastoreInventory(ctx, ds) 137 if err != nil { 138 return err 139 } 140 if err = task.Wait(ctx); err != nil { 141 return err 142 } 143 } 144 res := lsResult{cmd: cmd} 145 146 filterNotFound := false 147 ids := f.Args() 148 if len(ids) == 0 { 149 filterNotFound = true 150 var oids []types.ID 151 if cmd.category == "" { 152 oids, err = m.List(ctx, ds) 153 } else { 154 oids, err = m.ListAttachedObjects(ctx, cmd.category, cmd.tag) 155 } 156 157 if err != nil { 158 return err 159 } 160 for _, id := range oids { 161 ids = append(ids, id.Id) 162 } 163 } 164 165 for _, id := range ids { 166 o, err := m.Retrieve(ctx, ds, id) 167 if err != nil { 168 if filterNotFound && soap.IsSoapFault(err) { 169 fault := soap.ToSoapFault(err).Detail.Fault 170 if _, ok := fault.(types.NotFound); ok { 171 // The case when an FCD is deleted by something other than DeleteVStorageObject_Task, such as VM destroy 172 return fmt.Errorf("%s not found: use 'disk.ls -R' to reconcile datastore inventory", id) 173 } 174 } 175 return fmt.Errorf("retrieve %q: %s", id, err) 176 } 177 178 obj := VStorageObject{VStorageObject: *o} 179 if cmd.tags { 180 obj.Tags, err = m.ListAttachedTags(ctx, id) 181 if err != nil { 182 return err 183 } 184 } 185 res.Objects = append(res.Objects, obj) 186 } 187 188 return cmd.WriteResult(&res) 189 }