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  }