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