克隆 Hyper-V VM 并将其添加到域

Cloning and Adding Hyper-V VM to Domain

我有一个独立的(不是集群的,但在域中)Windows 安装了 Hyper-V 角色的 Server 2016。 我需要每天克隆 VM,所以我使用 C# 和 PowerShell 编写了一些小的 "things"。

  1. VHD 的平行拷贝

    public static void Main(string[] args) {
        var sourceFile = args[0];
        var distanationDir = args[1];
        int numOfCopies = Int32.Parse(args[2]);
    
        //var sourceFile = $@"C:\temp3.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. 第二步是使用此 PowerShell 脚本创建 VM,该脚本使用现有 VHDX 创建 VM。

    $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. 最后我需要将它们加入域,但我需要一些脚本,该脚本将为该主机上的每个虚拟机 运行 并将其添加到域中。

由于您应该能够使用 PowerShell Direct,因此您可以只获取要在其上执行的 VM,然后 Invoke-Command -VMName Add-Computer 命令。您的评论暗示您要将密码保存在脚本中。请记住这对安全的影响。

$domain = "myDomain" 
$password = "myPassword!" | ConvertTo-SecureString -asPlainText -Force 
$username = "$domain\myUserAccount" 
$credential = New-Object System.Management.Automation.PSCredential($username,$passwor‌​d) 
Get-VM | ForEach-Object { Invoke-Command -VMName $_.name -ScriptBlock {Add-Computer -DomainName $using:domain -Credential $using:credentia}}

这是一个解决方案: 运行 在客户端和服务器上执行此命令(在克隆或复制 VHD 之前)

Enable-PSRemoting -Force
winrm set winrm/config/client '@{TrustedHosts="*"}'

之后 运行 来自 hyper-v Host 这个(这只用于添加一个 VM,但你可以为主机上的每个虚拟机 ip 创建它)

#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}

这很有效!