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 }