From f20a98bf01829676b9c91969766b4733b7bdd4ad Mon Sep 17 00:00:00 2001 From: Fedor Korotkov Date: Fri, 6 May 2022 13:38:56 -0400 Subject: [PATCH] Smart generation of new MAC addresses (#45) * Introduce --new-mac-address flag for Clone command Related to https://github.com/cirruslabs/tart/issues/20#issuecomment-1116732505 * Smart generation of new MAC addresses --- Sources/tart/Commands/Clone.swift | 31 +++++++++++++++++++++++++------ Sources/tart/VMDirectory.swift | 6 ++++-- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/Sources/tart/Commands/Clone.swift b/Sources/tart/Commands/Clone.swift index d228662..a175703 100644 --- a/Sources/tart/Commands/Clone.swift +++ b/Sources/tart/Commands/Clone.swift @@ -13,13 +13,21 @@ struct Clone: AsyncParsableCommand { func run() async throws { do { - // Pull the VM in case it's OCI-based and doesn't exist locally yet - if let remoteName = try? RemoteName(sourceName), !VMStorageOCI().exists(remoteName) { - let registry = try Registry(host: remoteName.host, namespace: remoteName.namespace) - try await VMStorageOCI().pull(remoteName, registry: registry) - } + if let remoteName = try? RemoteName(sourceName) { + if !VMStorageOCI().exists(remoteName) { + // Pull the VM in case it's OCI-based and doesn't exist locally yet + let registry = try Registry(host: remoteName.host, namespace: remoteName.namespace) + try await VMStorageOCI().pull(remoteName, registry: registry) + } + let removeVM = try VMStorageHelper.open(sourceName) - try VMStorageHelper.open(sourceName).clone(to: VMStorageLocal().create(newName)) + let removeConfig = try VMConfig.init(fromURL: removeVM.configURL) + let needToGenerateNewMAC = try localVMExistsWith(macAddress: removeConfig.macAddress.string) + + try removeVM.clone(to: VMStorageLocal().create(newName), generateMAC: needToGenerateNewMAC) + } else { + try VMStorageHelper.open(sourceName).clone(to: VMStorageLocal().create(newName), generateMAC: true) + } Foundation.exit(0) } catch { @@ -28,4 +36,15 @@ struct Clone: AsyncParsableCommand { Foundation.exit(1) } } + + private func localVMExistsWith(macAddress: String) throws -> Bool { + var needToGenerateNewMAC = false + for (_, localDir) in try VMStorageLocal().list() { + let localConfig = try VMConfig.init(fromURL: localDir.configURL) + if localConfig.macAddress.string == macAddress { + needToGenerateNewMAC = true + } + } + return needToGenerateNewMAC + } } diff --git a/Sources/tart/VMDirectory.swift b/Sources/tart/VMDirectory.swift index a675e0b..492eda3 100644 --- a/Sources/tart/VMDirectory.swift +++ b/Sources/tart/VMDirectory.swift @@ -48,14 +48,16 @@ struct VMDirectory { } } - func clone(to: VMDirectory) throws { + func clone(to: VMDirectory, generateMAC: Bool) throws { try FileManager.default.copyItem(at: configURL, to: to.configURL) try FileManager.default.copyItem(at: nvramURL, to: to.nvramURL) try FileManager.default.copyItem(at: diskURL, to: to.diskURL) // Re-generate MAC address var newVMConfig = try VMConfig(fromURL: to.configURL) - newVMConfig.macAddress = VZMACAddress.randomLocallyAdministered() + if generateMAC { + newVMConfig.macAddress = VZMACAddress.randomLocallyAdministered() + } try newVMConfig.save(toURL: to.configURL) }