github.com/vmware/govmomi@v0.51.0/cli/importx/options.go (about) 1 // © Broadcom. All Rights Reserved. 2 // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 3 // SPDX-License-Identifier: Apache-2.0 4 5 package importx 6 7 import ( 8 "context" 9 "encoding/json" 10 "flag" 11 "fmt" 12 "os" 13 14 "github.com/vmware/govmomi/cli/flags" 15 "github.com/vmware/govmomi/object" 16 "github.com/vmware/govmomi/ovf" 17 "github.com/vmware/govmomi/ovf/importer" 18 "github.com/vmware/govmomi/vim25/types" 19 ) 20 21 type OptionsFlag struct { 22 Options importer.Options 23 24 path string 25 } 26 27 func newOptionsFlag(ctx context.Context) (*OptionsFlag, context.Context) { 28 return &OptionsFlag{}, ctx 29 } 30 31 func (flag *OptionsFlag) Register(ctx context.Context, f *flag.FlagSet) { 32 f.StringVar(&flag.path, "options", "", "Options spec file path for VM deployment") 33 } 34 35 func (flag *OptionsFlag) Process(ctx context.Context) error { 36 if len(flag.path) == 0 { 37 return nil 38 } 39 40 var err error 41 in := os.Stdin 42 43 if flag.path != "-" { 44 in, err = os.Open(flag.path) 45 if err != nil { 46 return err 47 } 48 defer in.Close() 49 } 50 51 return json.NewDecoder(in).Decode(&flag.Options) 52 } 53 54 func (flag *OptionsFlag) powerOn(vm *object.VirtualMachine, out *flags.OutputFlag) error { 55 if !flag.Options.PowerOn || flag.Options.MarkAsTemplate { 56 return nil 57 } 58 59 out.Log("Powering on VM...\n") 60 61 task, err := vm.PowerOn(context.Background()) 62 if err != nil { 63 return err 64 } 65 66 return task.Wait(context.Background()) 67 } 68 69 func (flag *OptionsFlag) markAsTemplate(vm *object.VirtualMachine, out *flags.OutputFlag) error { 70 if !flag.Options.MarkAsTemplate { 71 return nil 72 } 73 74 out.Log("Marking VM as template...\n") 75 76 return vm.MarkAsTemplate(context.Background()) 77 } 78 79 func (flag *OptionsFlag) injectOvfEnv(vm *object.VirtualMachine, out *flags.OutputFlag) error { 80 if !flag.Options.InjectOvfEnv { 81 return nil 82 } 83 84 out.Log("Injecting OVF environment...\n") 85 86 var opts []types.BaseOptionValue 87 88 a := vm.Client().ServiceContent.About 89 90 // build up Environment in order to marshal to xml 91 var props []ovf.EnvProperty 92 for _, p := range flag.Options.PropertyMapping { 93 props = append(props, ovf.EnvProperty{ 94 Key: p.Key, 95 Value: p.Value, 96 }) 97 } 98 99 env := ovf.Env{ 100 EsxID: vm.Reference().Value, 101 Platform: &ovf.PlatformSection{ 102 Kind: a.Name, 103 Version: a.Version, 104 Vendor: a.Vendor, 105 Locale: "US", 106 }, 107 Property: &ovf.PropertySection{ 108 Properties: props, 109 }, 110 } 111 112 opts = append(opts, &types.OptionValue{ 113 Key: "guestinfo.ovfEnv", 114 Value: env.MarshalManual(), 115 }) 116 117 task, err := vm.Reconfigure(context.Background(), types.VirtualMachineConfigSpec{ 118 ExtraConfig: opts, 119 }) 120 121 if err != nil { 122 return err 123 } 124 125 return task.Wait(context.Background()) 126 } 127 128 func (flag *OptionsFlag) waitForIP(vm *object.VirtualMachine, out *flags.OutputFlag) error { 129 if !flag.Options.PowerOn || !flag.Options.WaitForIP || flag.Options.MarkAsTemplate { 130 return nil 131 } 132 133 out.Log("Waiting for IP address...\n") 134 ip, err := vm.WaitForIP(context.Background()) 135 if err != nil { 136 return err 137 } 138 139 out.Log(fmt.Sprintf("Received IP address: %s\n", ip)) 140 return nil 141 } 142 143 func (flag *OptionsFlag) Deploy(vm *object.VirtualMachine, out *flags.OutputFlag) error { 144 deploy := []func(*object.VirtualMachine, *flags.OutputFlag) error{ 145 flag.injectOvfEnv, 146 flag.markAsTemplate, 147 flag.powerOn, 148 flag.waitForIP, 149 } 150 151 for _, step := range deploy { 152 if err := step(vm, out); err != nil { 153 return err 154 } 155 } 156 157 return nil 158 }