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  }