github.com/vmware/govmomi@v0.43.0/govc/library/clone.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/vapi/vcenter"
    27  )
    28  
    29  type clone struct {
    30  	*flags.ClusterFlag
    31  	*flags.DatastoreFlag
    32  	*flags.FolderFlag
    33  	*flags.ResourcePoolFlag
    34  	*flags.HostSystemFlag
    35  	*flags.VirtualMachineFlag
    36  	*flags.StorageProfileFlag
    37  
    38  	ovf   bool
    39  	extra bool
    40  	mac   bool
    41  }
    42  
    43  func init() {
    44  	cli.Register("library.clone", &clone{})
    45  }
    46  
    47  func (cmd *clone) Register(ctx context.Context, f *flag.FlagSet) {
    48  	cmd.ClusterFlag, ctx = flags.NewClusterFlag(ctx)
    49  	cmd.ClusterFlag.Register(ctx, f)
    50  
    51  	cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
    52  	cmd.DatastoreFlag.Register(ctx, f)
    53  
    54  	cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx)
    55  	cmd.ResourcePoolFlag.Register(ctx, f)
    56  
    57  	cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
    58  	cmd.HostSystemFlag.Register(ctx, f)
    59  
    60  	cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx)
    61  	cmd.FolderFlag.Register(ctx, f)
    62  
    63  	cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
    64  	cmd.VirtualMachineFlag.Register(ctx, f)
    65  
    66  	cmd.StorageProfileFlag, ctx = flags.NewStorageProfileFlag(ctx)
    67  	cmd.StorageProfileFlag.Register(ctx, f)
    68  
    69  	f.BoolVar(&cmd.ovf, "ovf", false, "Clone as OVF (default is VM Template)")
    70  	f.BoolVar(&cmd.extra, "e", false, "Include extra configuration")
    71  	f.BoolVar(&cmd.mac, "m", false, "Preserve MAC-addresses on network adapters")
    72  }
    73  
    74  func (cmd *clone) Process(ctx context.Context) error {
    75  	if err := cmd.ClusterFlag.Process(ctx); err != nil {
    76  		return err
    77  	}
    78  	if err := cmd.DatastoreFlag.Process(ctx); err != nil {
    79  		return err
    80  	}
    81  	if err := cmd.ResourcePoolFlag.Process(ctx); err != nil {
    82  		return err
    83  	}
    84  	if err := cmd.HostSystemFlag.Process(ctx); err != nil {
    85  		return err
    86  	}
    87  	if err := cmd.FolderFlag.Process(ctx); err != nil {
    88  		return err
    89  	}
    90  	if err := cmd.StorageProfileFlag.Process(ctx); err != nil {
    91  		return err
    92  	}
    93  	return cmd.VirtualMachineFlag.Process(ctx)
    94  }
    95  
    96  func (cmd *clone) Usage() string {
    97  	return "PATH NAME"
    98  }
    99  
   100  func (cmd *clone) Description() string {
   101  	return `Clone VM to Content Library PATH.
   102  
   103  By default, clone as a VM template (requires vCenter version 6.7U1 or higher).
   104  Clone as an OVF when the '-ovf' flag is specified.
   105  
   106  Examples:
   107    govc library.clone -vm template-vm my-content template-vm-item
   108    govc library.clone -ovf -vm template-vm my-content ovf-item`
   109  }
   110  
   111  func (cmd *clone) Run(ctx context.Context, f *flag.FlagSet) error {
   112  	path := f.Arg(0)
   113  	name := f.Arg(1)
   114  
   115  	vm, err := cmd.VirtualMachine()
   116  	if err != nil {
   117  		return err
   118  	}
   119  	if vm == nil || name == "" {
   120  		return flag.ErrHelp
   121  	}
   122  	ds, err := cmd.DatastoreIfSpecified()
   123  	if err != nil {
   124  		return err
   125  	}
   126  	folder, err := cmd.FolderOrDefault("vm")
   127  	if err != nil {
   128  		return err
   129  	}
   130  	host, err := cmd.HostSystemIfSpecified()
   131  	if err != nil {
   132  		return err
   133  	}
   134  	cluster, err := cmd.ClusterIfSpecified()
   135  	if err != nil {
   136  		return err
   137  	}
   138  	pool, err := cmd.ResourcePoolIfSpecified()
   139  	if err != nil {
   140  		return err
   141  	}
   142  
   143  	dsID := ""
   144  	if ds != nil {
   145  		dsID = ds.Reference().Value
   146  	}
   147  
   148  	c, err := cmd.FolderFlag.RestClient()
   149  	if err != nil {
   150  		return err
   151  	}
   152  
   153  	l, err := flags.ContentLibrary(ctx, c, path)
   154  	if err != nil {
   155  		return err
   156  	}
   157  
   158  	if cmd.ovf {
   159  		ovf := vcenter.OVF{
   160  			Spec: vcenter.CreateSpec{
   161  				Name: name,
   162  			},
   163  			Source: vcenter.ResourceID{
   164  				Value: vm.Reference().Value,
   165  			},
   166  			Target: vcenter.LibraryTarget{
   167  				LibraryID: l.ID,
   168  			},
   169  		}
   170  		if cmd.extra {
   171  			ovf.Spec.Flags = append(ovf.Spec.Flags, "EXTRA_CONFIG")
   172  		}
   173  		if cmd.mac {
   174  			ovf.Spec.Flags = append(ovf.Spec.Flags, "PRESERVE_MAC")
   175  		}
   176  		id, err := vcenter.NewManager(c).CreateOVF(ctx, ovf)
   177  		if err != nil {
   178  			return err
   179  		}
   180  		fmt.Println(id)
   181  		return nil
   182  	}
   183  
   184  	profile, err := cmd.StorageProfile(ctx)
   185  	if err != nil {
   186  		return err
   187  	}
   188  
   189  	storage := &vcenter.DiskStorage{
   190  		Datastore: dsID,
   191  		StoragePolicy: &vcenter.StoragePolicy{
   192  			Policy: profile,
   193  			Type:   "USE_SOURCE_POLICY",
   194  		},
   195  	}
   196  	if profile != "" {
   197  		storage.StoragePolicy.Type = "USE_SPECIFIED_POLICY"
   198  	}
   199  
   200  	spec := vcenter.Template{
   201  		Name:          name,
   202  		Library:       l.ID,
   203  		DiskStorage:   storage,
   204  		VMHomeStorage: storage,
   205  		SourceVM:      vm.Reference().Value,
   206  		Placement: &vcenter.Placement{
   207  			Folder: folder.Reference().Value,
   208  		},
   209  	}
   210  	if pool != nil {
   211  		spec.Placement.ResourcePool = pool.Reference().Value
   212  	}
   213  	if host != nil {
   214  		spec.Placement.Host = host.Reference().Value
   215  	}
   216  	if cluster != nil {
   217  		spec.Placement.Cluster = cluster.Reference().Value
   218  	}
   219  
   220  	id, err := vcenter.NewManager(c).CreateTemplate(ctx, spec)
   221  	if err != nil {
   222  		return err
   223  	}
   224  
   225  	fmt.Println(id)
   226  
   227  	return nil
   228  }