I have a standalone (not clustered, but in the domain) Windows Server 2016 with Hyper-V role installed. I need to clone VMs on a daily basis, so I wrote a few small "things" using C# and PowerShell.
Parallel Copy of VHD
public static void Main(string[] args) {
var sourceFile = args[0];
var distanationDir = args[1];
int numOfCopies = Int32.Parse(args[2]);
//var sourceFile = $@"C:\temp\123.VHD";
//var distanationDir = $@"C:\temp\vhds\";
//int numOfCopies = 15;
StartJob(sourceFile, distanationDir, numOfCopies, random);
}
private static void StartJob(string sourcefile, string distanationdir, int numOfCopies, Random random) {
int count = 0;
Parallel.For(0, numOfCopies, i => {
Console.WriteLine("i = {0}, thread = {1}", i, Thread.CurrentThread.ManagedThreadId);
try {
string atrib = Path.GetExtension(sourcefile);
string guid = Guid.NewGuid().ToString("N");
var copyNew = Path.GetFileNameWithoutExtension(sourcefile) + guid + atrib;
File.Copy(sourcefile, Path.Combine(distanationdir + '\\', copyNew));
Console.WriteLine(@"Started{copyNew}");
} catch (IOException copyError) {
Console.WriteLine(copyError.Message);
}
}
}
The second step is to create VMs with this PowerShell script that creates a VM with existing VHDX.
$from = 81
$howmany = 30
$files = Get-ChildItem -Path "E:\Hyper-v" -Filter *.vhdx
if ($files) {
Write-Host "variable is not null"
try {
$vmIndex = $from
for ($i = 0; $i -lt $howmany; $i++) {
Write-Host "Start "
New-Vm -Name "AUT-TA$vmIndex" -Path "E:\Hyper-v\Virtual Machines" -MemoryStartupBytes 4294967296 -VHDPath $files[$i].FullName -SwitchName "Broadcom NetXtreme Gigabit Ethernet #4 - Virtual Switch"
Write-Host "Vm created " + "AUT-TA$vmIndex"
$vmIndex++
Write-Host "End"
}
exit
} catch {
[System.Exception]"caught a system exception"
}
} else {
Write-Host "No such files"
exit
}
Last I need join them to the domain but I need some script that will be running for each VM on this host and adding it to the domain.
This is a solution: run this commands on both client and server (before clone or copy of VHD)
Enable-PSRemoting -Force
winrm set winrm/config/client '@{TrustedHosts="*"}'
After it run from hyper-v Host this (this only for add one VM , but you can create it ForEach ip of vm on host)
#Local Cred
$passwordLoc = "Password"
$usernameLoc = "localhost\Administrator"
$credentialsLoc = New-Object System.Management.Automation.PsCredential($usernameLoc, (ConvertTo-SecureString $passwordLoc -AsPlainText -Force))
$ses = New-PSSession 192.168.90.91 -Credential $credentialsLoc
##Domain Cred
$domain = "domain.com"
$password = "Password"
$username = "$domain\PowerUser"
$credentials = New-Object System.Management.Automation.PsCredential($username, (ConvertTo-SecureString $password -AsPlainText -Force))
Invoke-command -Session $ses -ScriptBlock {
Add-Computer -DomainName $using:domain -Credential $using:credentials -ErrorAction Stop
Rename-Computer -NewName "AUT-TA41" -DomainCredential $using:credentials -Force -ErrorAction Stop
Restart-Computer -ErrorAction Stop}
And this Works!