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

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