This repository has been archived by the owner on Jul 1, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 175
/
clone_vm.rb
89 lines (70 loc) · 2.33 KB
/
clone_vm.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#!/usr/bin/env ruby
# frozen_string_literal: true
# Copyright (c) 2011-2017 VMware, Inc. All Rights Reserved.
# SPDX-License-Identifier: MIT
require 'optimist'
require 'rbvmomi'
require 'rbvmomi/optimist'
VIM = RbVmomi::VIM
opts = Optimist.options do
banner <<~EOS
Clone a VM.
Usage:
clone_vm.rb [options] source_vm dest_vm
VIM connection options:
EOS
rbvmomi_connection_opts
text <<~EOS
VM location options:
EOS
rbvmomi_datacenter_opt
text <<~EOS
Other options:
EOS
opt :linked_clone, 'Use a linked clone instead of a full clone'
end
Optimist.die('must specify host') unless opts[:host]
ARGV.size == 2 or abort 'must specify VM source name and VM target name'
vm_source = ARGV[0]
vm_target = ARGV[1]
vim = VIM.connect opts
dc = vim.serviceInstance.find_datacenter(opts[:datacenter]) or abort 'datacenter not found'
vm = dc.find_vm(vm_source) or abort 'VM not found'
if opts[:linked_clone]
# The API for linked clones is quite strange. We can't create a linked
# straight from any VM. The disks of the VM for which we can create a
# linked clone need to be read-only and thus VC demands that the VM we
# are cloning from uses delta-disks. Only then it will allow us to
# share the base disk.
#
# Thus, this code first create a delta disk on top of the base disk for
# the to-be-cloned VM, if delta disks aren't used already.
disks = vm.config.hardware.device.grep(VIM::VirtualDisk)
disks.select { |x| x.backing.parent == nil }.each do |disk|
spec = {
deviceChange: [
{
operation: :remove,
device: disk
},
{
operation: :add,
fileOperation: :create,
device: disk.dup.tap { |x|
x.backing = x.backing.dup
x.backing.fileName = "[#{disk.backing.datastore.name}]"
x.backing.parent = disk.backing
},
}
]
}
vm.ReconfigVM_Task(spec: spec).wait_for_completion
end
relocateSpec = VIM.VirtualMachineRelocateSpec(diskMoveType: :moveChildMostDiskBacking)
else
relocateSpec = VIM.VirtualMachineRelocateSpec
end
spec = VIM.VirtualMachineCloneSpec(location: relocateSpec,
powerOn: false,
template: false)
vm.CloneVM_Task(folder: vm.parent, name: vm_target, spec: spec).wait_for_completion