github.com/vmware/govmomi@v0.43.0/govc/library/deploy.go (about)

     1  /*
     2  Copyright (c) 2019-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 library
    18  
    19  import (
    20  	"context"
    21  	"flag"
    22  	"fmt"
    23  
    24  	"github.com/vmware/govmomi/govc/cli"
    25  	"github.com/vmware/govmomi/govc/flags"
    26  	"github.com/vmware/govmomi/govc/importx"
    27  	"github.com/vmware/govmomi/object"
    28  	"github.com/vmware/govmomi/vapi/library"
    29  	"github.com/vmware/govmomi/vapi/vcenter"
    30  	"github.com/vmware/govmomi/vim25/types"
    31  )
    32  
    33  type deploy struct {
    34  	*flags.DatastoreFlag
    35  	*flags.ResourcePoolFlag
    36  	*flags.HostSystemFlag
    37  	*flags.FolderFlag
    38  	*flags.StorageProfileFlag
    39  	*importx.OptionsFlag
    40  
    41  	config string
    42  }
    43  
    44  func init() {
    45  	cli.Register("library.deploy", &deploy{})
    46  }
    47  
    48  func (cmd *deploy) Register(ctx context.Context, f *flag.FlagSet) {
    49  	cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
    50  	cmd.DatastoreFlag.Register(ctx, f)
    51  
    52  	cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx)
    53  	cmd.ResourcePoolFlag.Register(ctx, f)
    54  
    55  	cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
    56  	cmd.HostSystemFlag.Register(ctx, f)
    57  
    58  	cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx)
    59  	cmd.FolderFlag.Register(ctx, f)
    60  
    61  	cmd.StorageProfileFlag, ctx = flags.NewStorageProfileFlag(ctx)
    62  	cmd.StorageProfileFlag.Register(ctx, f)
    63  
    64  	cmd.OptionsFlag = new(importx.OptionsFlag)
    65  	cmd.OptionsFlag.Register(ctx, f)
    66  
    67  	if cli.ShowUnreleased() {
    68  		f.StringVar(&cmd.config, "config", "", "VM config spec")
    69  	}
    70  }
    71  
    72  func (cmd *deploy) Process(ctx context.Context) error {
    73  	if err := cmd.DatastoreFlag.Process(ctx); err != nil {
    74  		return err
    75  	}
    76  	if err := cmd.ResourcePoolFlag.Process(ctx); err != nil {
    77  		return err
    78  	}
    79  	if err := cmd.HostSystemFlag.Process(ctx); err != nil {
    80  		return err
    81  	}
    82  	if err := cmd.FolderFlag.Process(ctx); err != nil {
    83  		return err
    84  	}
    85  	if err := cmd.StorageProfileFlag.Process(ctx); err != nil {
    86  		return err
    87  	}
    88  	return cmd.OptionsFlag.Process(ctx)
    89  }
    90  
    91  func (cmd *deploy) Usage() string {
    92  	return "TEMPLATE [NAME]"
    93  }
    94  
    95  func (cmd *deploy) Description() string {
    96  	return `Deploy library OVF template.
    97  
    98  Examples:
    99    govc library.deploy /library_name/ovf_template vm_name
   100    govc library.export /library_name/ovf_template/*.ovf # save local copy of .ovf
   101    govc import.spec *.ovf > deploy.json # generate options from .ovf
   102    # edit deploy.json as needed
   103    govc library.deploy -options deploy.json /library_name/ovf_template`
   104  }
   105  
   106  func (cmd *deploy) Run(ctx context.Context, f *flag.FlagSet) error {
   107  	if f.NArg() > 2 {
   108  		return flag.ErrHelp
   109  	}
   110  	path := f.Arg(0)
   111  	name := f.Arg(1)
   112  
   113  	if name == "" && cmd.Options.Name != nil {
   114  		name = *cmd.Options.Name
   115  	}
   116  
   117  	vc, err := cmd.DatastoreFlag.Client()
   118  	if err != nil {
   119  		return err
   120  	}
   121  	cmd.FolderFlag.KeepAlive(vc)
   122  
   123  	c, err := cmd.DatastoreFlag.RestClient()
   124  	if err != nil {
   125  		return err
   126  	}
   127  	cmd.FolderFlag.KeepAlive(c)
   128  
   129  	m := vcenter.NewManager(c)
   130  
   131  	item, err := flags.ContentLibraryItem(ctx, c, path)
   132  	if err != nil {
   133  		return err
   134  	}
   135  
   136  	ds, err := cmd.DatastoreIfSpecified()
   137  	if err != nil {
   138  		return err
   139  	}
   140  	rp, err := cmd.ResourcePoolIfSpecified()
   141  	if err != nil {
   142  		return err
   143  	}
   144  	host, err := cmd.HostSystemIfSpecified()
   145  	if err != nil {
   146  		return err
   147  	}
   148  	hostID := ""
   149  	if rp == nil {
   150  		if host == nil {
   151  			rp, err = cmd.ResourcePoolFlag.ResourcePool()
   152  		} else {
   153  			rp, err = host.ResourcePool(ctx)
   154  			hostID = host.Reference().Value
   155  		}
   156  		if err != nil {
   157  			return err
   158  		}
   159  	}
   160  	folder, err := cmd.Folder()
   161  	if err != nil {
   162  		return err
   163  	}
   164  	finder, err := cmd.FolderFlag.Finder(false)
   165  	if err != nil {
   166  		return err
   167  	}
   168  
   169  	var networks []vcenter.NetworkMapping
   170  	for _, net := range cmd.Options.NetworkMapping {
   171  		if net.Network == "" {
   172  			continue
   173  		}
   174  		obj, err := finder.Network(ctx, net.Network)
   175  		if err != nil {
   176  			return err
   177  		}
   178  		networks = append(networks, vcenter.NetworkMapping{
   179  			Key:   net.Name,
   180  			Value: obj.Reference().Value,
   181  		})
   182  	}
   183  
   184  	var properties []vcenter.Property
   185  	for _, prop := range cmd.Options.PropertyMapping {
   186  		properties = append(properties, vcenter.Property{
   187  			ID:    prop.Key,
   188  			Value: prop.Value,
   189  		})
   190  	}
   191  
   192  	dsID := ""
   193  	if ds != nil {
   194  		dsID = ds.Reference().Value
   195  	}
   196  
   197  	cmd.FolderFlag.Log("Deploying library item...\n")
   198  
   199  	var ref *types.ManagedObjectReference
   200  
   201  	profile, err := cmd.StorageProfile(ctx)
   202  	if err != nil {
   203  		return err
   204  	}
   205  
   206  	switch item.Type {
   207  	case library.ItemTypeOVF:
   208  		deploy := vcenter.Deploy{
   209  			DeploymentSpec: vcenter.DeploymentSpec{
   210  				Name:               name,
   211  				DefaultDatastoreID: dsID,
   212  				AcceptAllEULA:      true,
   213  				Annotation:         cmd.Options.Annotation,
   214  				AdditionalParams: []vcenter.AdditionalParams{
   215  					{
   216  						Class:       vcenter.ClassDeploymentOptionParams,
   217  						Type:        vcenter.TypeDeploymentOptionParams,
   218  						SelectedKey: cmd.Options.Deployment,
   219  					},
   220  					{
   221  						Class:       vcenter.ClassPropertyParams,
   222  						Type:        vcenter.TypePropertyParams,
   223  						SelectedKey: cmd.Options.Deployment,
   224  						Properties:  properties,
   225  					},
   226  				},
   227  				NetworkMappings:     networks,
   228  				StorageProvisioning: cmd.Options.DiskProvisioning,
   229  				StorageProfileID:    profile,
   230  			},
   231  			Target: vcenter.Target{
   232  				ResourcePoolID: rp.Reference().Value,
   233  				HostID:         hostID,
   234  				FolderID:       folder.Reference().Value,
   235  			},
   236  		}
   237  
   238  		if cmd.config != "" {
   239  			deploy.VmConfigSpec = &vcenter.VmConfigSpec{
   240  				Provider: "XML",
   241  				XML:      cmd.config,
   242  			}
   243  		}
   244  
   245  		ref, err = m.DeployLibraryItem(ctx, item.ID, deploy)
   246  		if err != nil {
   247  			return err
   248  		}
   249  	case library.ItemTypeVMTX:
   250  		storage := &vcenter.DiskStorage{
   251  			Datastore: dsID,
   252  			StoragePolicy: &vcenter.StoragePolicy{
   253  				Policy: profile,
   254  				Type:   "USE_SOURCE_POLICY",
   255  			},
   256  		}
   257  		if profile != "" {
   258  			storage.StoragePolicy.Type = "USE_SPECIFIED_POLICY"
   259  		}
   260  
   261  		deploy := vcenter.DeployTemplate{
   262  			Name:          name,
   263  			Description:   cmd.Options.Annotation,
   264  			DiskStorage:   storage,
   265  			VMHomeStorage: storage,
   266  			Placement: &vcenter.Placement{
   267  				ResourcePool: rp.Reference().Value,
   268  				Host:         hostID,
   269  				Folder:       folder.Reference().Value,
   270  			},
   271  		}
   272  		ref, err = m.DeployTemplateLibraryItem(ctx, item.ID, deploy)
   273  		if err != nil {
   274  			return err
   275  		}
   276  	default:
   277  		return fmt.Errorf("unsupported library item type: %s", item.Type)
   278  	}
   279  
   280  	obj, err := finder.ObjectReference(ctx, *ref)
   281  	if err != nil {
   282  		return err
   283  	}
   284  
   285  	vm := obj.(*object.VirtualMachine)
   286  
   287  	return cmd.Deploy(vm, cmd.FolderFlag.OutputFlag)
   288  }