Skip to content

Commit 08f66f2

Browse files
committed
Add deep VM clone support
1 parent 47690d0 commit 08f66f2

File tree

1 file changed

+29
-6
lines changed

1 file changed

+29
-6
lines changed

Sources/hostmgr/commands/vm/VMClone.swift

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,16 @@ struct VMCloneCommand: ParsableCommand {
4545
)
4646
var networkingType: StoppedVM.NetworkType = .bridged
4747

48+
@Option(
49+
help: "Clone type"
50+
)
51+
var depth: CloneType = .shallow
52+
4853
func run() throws {
4954

5055
let startDate = Date()
5156

52-
try cloneVM(vm: source, wait: wait || start, startDate: startDate)
57+
try clone(vm: source, wait: wait || start, startDate: startDate, type: depth)
5358

5459
guard let newVM = try Parallels().lookupVM(named: destination)?.asStoppedVM() else {
5560
print("Error finding cloned VM")
@@ -60,27 +65,29 @@ struct VMCloneCommand: ParsableCommand {
6065

6166
let totalSystemMemory = Int(ProcessInfo().physicalMemory / (1024 * 1024)) // In MB
6267
let vmAvailableMemory = totalSystemMemory - 4096 // Always leave 4GB available to the VM host – the VM can have the rest
68+
let cpuCoreCount = ProcessInfo().physicalProcessorCount
6369

6470
logger.debug("Total System Memory: \(totalSystemMemory) MB")
6571
logger.debug("Allocating \(vmAvailableMemory) MB to VM")
72+
try newVM.set(.memorySize(vmAvailableMemory))
6673

67-
let cpuCoreCount = ProcessInfo().physicalProcessorCount
6874
logger.debug("Allocating \(cpuCoreCount) cores to VM")
69-
7075
try newVM.set(.cpuCount(cpuCoreCount))
71-
try newVM.set(.memorySize(vmAvailableMemory))
7276
}
7377

78+
logger.debug("Setting Hypervisor type to \(hypervisorType)")
7479
try newVM.set(.hypervisorType(hypervisorType))
80+
81+
logger.debug("Setting Networking type to \(networkingType)")
7582
try newVM.set(.networkType(networkingType))
7683

7784
if start {
7885
try startVM(vm: newVM, wait: wait, startDate: startDate)
7986
}
8087
}
8188

82-
func cloneVM(vm: StoppedVM, wait: Bool, startDate: Date) throws {
83-
try vm.clone(as: destination, fast: true)
89+
func clone(vm: StoppedVM, wait: Bool, startDate: Date, type: CloneType = .shallow) throws {
90+
try vm.clone(as: destination, fast: type.shouldUseFastClone)
8491

8592
guard wait else {
8693
return
@@ -108,7 +115,23 @@ struct VMCloneCommand: ParsableCommand {
108115

109116
print(String(format: "VM cloned and booted in %.2f seconds", Date().timeIntervalSince(startDate)))
110117
}
118+
119+
enum CloneType: String {
120+
/// Shallow clones are far faster and are most useful when the cloned VM will be discarded
121+
case shallow
122+
123+
/// Deep clones are slower, but are easier to export as a new VM
124+
case full
125+
126+
var shouldUseFastClone: Bool {
127+
switch self {
128+
case .shallow: return true
129+
case .full: return false
130+
}
131+
}
132+
}
111133
}
112134

113135
extension StoppedVM.NetworkType: ExpressibleByArgument {}
114136
extension StoppedVM.HypervisorType: ExpressibleByArgument {}
137+
extension VMCloneCommand.CloneType: ExpressibleByArgument {}

0 commit comments

Comments
 (0)