1/* 2Copyright (c) 2016 VMware, Inc. All Rights Reserved. 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15*/ 16 17package snapshot 18 19import ( 20 "context" 21 "flag" 22 "fmt" 23 "path" 24 "strings" 25 26 "github.com/vmware/govmomi/govc/cli" 27 "github.com/vmware/govmomi/govc/flags" 28 "github.com/vmware/govmomi/vim25/mo" 29 "github.com/vmware/govmomi/vim25/types" 30) 31 32type tree struct { 33 *flags.VirtualMachineFlag 34 35 fullPath bool 36 current bool 37 currentName bool 38 date bool 39 id bool 40 41 info *types.VirtualMachineSnapshotInfo 42} 43 44func init() { 45 cli.Register("snapshot.tree", &tree{}) 46} 47 48func (cmd *tree) Register(ctx context.Context, f *flag.FlagSet) { 49 cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx) 50 cmd.VirtualMachineFlag.Register(ctx, f) 51 52 f.BoolVar(&cmd.fullPath, "f", false, "Print the full path prefix for snapshot") 53 f.BoolVar(&cmd.currentName, "C", false, "Print the current snapshot name only") 54 f.BoolVar(&cmd.current, "c", true, "Print the current snapshot") 55 f.BoolVar(&cmd.date, "D", false, "Print the snapshot creation date") 56 f.BoolVar(&cmd.id, "i", false, "Print the snapshot id") 57} 58 59func (cmd *tree) Description() string { 60 return `List VM snapshots in a tree-like format. 61 62The command will exit 0 with no output if VM does not have any snapshots. 63 64Examples: 65 govc snapshot.tree -vm my-vm 66 govc snapshot.tree -vm my-vm -D -i` 67} 68 69func (cmd *tree) Process(ctx context.Context) error { 70 if err := cmd.VirtualMachineFlag.Process(ctx); err != nil { 71 return err 72 } 73 return nil 74} 75 76func (cmd *tree) write(level int, parent string, st []types.VirtualMachineSnapshotTree) { 77 for _, s := range st { 78 sname := s.Name 79 80 if cmd.fullPath && parent != "" { 81 sname = path.Join(parent, sname) 82 } 83 84 var names []string 85 86 if !cmd.currentName { 87 names = append(names, sname) 88 } 89 90 if s.Snapshot == *cmd.info.CurrentSnapshot { 91 if cmd.current { 92 names = append(names, ".") 93 } else if cmd.currentName { 94 fmt.Println(sname) 95 return 96 } 97 } 98 99 for _, name := range names { 100 var attr []string 101 var meta string 102 103 if cmd.id { 104 attr = append(attr, s.Snapshot.Value) 105 } 106 107 if cmd.date { 108 attr = append(attr, s.CreateTime.Format("Jan 2 15:04")) 109 } 110 111 if len(attr) > 0 { 112 meta = fmt.Sprintf("[%s] ", strings.Join(attr, " ")) 113 } 114 115 fmt.Printf("%s%s%s\n", strings.Repeat(" ", level), meta, name) 116 } 117 118 cmd.write(level+2, sname, s.ChildSnapshotList) 119 } 120} 121 122func (cmd *tree) Run(ctx context.Context, f *flag.FlagSet) error { 123 if f.NArg() != 0 { 124 return flag.ErrHelp 125 } 126 127 vm, err := cmd.VirtualMachine() 128 if err != nil { 129 return err 130 } 131 132 if vm == nil { 133 return flag.ErrHelp 134 } 135 136 var o mo.VirtualMachine 137 138 err = vm.Properties(ctx, vm.Reference(), []string{"snapshot"}, &o) 139 if err != nil { 140 return err 141 } 142 143 if o.Snapshot == nil { 144 return nil 145 } 146 147 if o.Snapshot.CurrentSnapshot == nil || cmd.currentName { 148 cmd.current = false 149 } 150 151 cmd.info = o.Snapshot 152 153 cmd.write(0, "", o.Snapshot.RootSnapshotList) 154 155 return nil 156} 157