Search code examples
c#powershellclonehyper-vwindows-server-2016

Cloning and Adding Hyper-V VM to Domain


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.

  1. 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);
            }
        }
    }
    
  2. 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
    }
    
  3. 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.


Solution

  • 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!