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