Automatizando a criação de máquinas virtuais com PowerShell

Automatizando a criação de máquinas virtuais com PowerShell

  • Comments 1
  • Likes

Curry turnovers

Uma das coisas que eu acho entediante é montar laboratório para testes. Digo, no sentido de criar os servidores um a um, pois é uma tarefa demorada e trabalhosa. Muitos colegas utilizam o VMM (Virtual Machine Manager) em seus ambientes para facilitar nessa atividade e acho que é a solução ideal. Entretanto, nem sempre tenho disponível o VMM no ambiente do cliente e precisava  de algo mais simples para montar várias máquinas virtuais de uma só vez. Então resolvi montar um script para facilitar a minha vida. Geralmente precisamos montar vários servidores de uma só vez. Dado isso, o script lê um arquivo CSV que define as configurações mínimas das máquinas virtuais que serão montadas.

IMPORTANTE - O script utiliza o modulo HyperV, que pode ser obtido em http://www.codeplex.com/psHyperV. Lá tem toda a informação de como instalar o módulo no computador onde o script vai rodar.

Abaixo a estrutura do arquivo CSV com três exemplos que irei comentar:

Name,CPU,Memory,NetName,IDEDisk,VHDParent
LAB01,4,4096,Rede Dados,W7Test.VHD,,
LAB02,1,1024,Rede Publica,new,,
LAB03,2,2048,Rede Dados,new,G:\VMs\Parent\parent.vhd
#LAB04,1,1024,Rede Dados,new,

O CSV tem 5 campos: Nome, CPU - quantidade de CPU, Memory - quantidade de memória em MB, NetName - nome da rede Hyper-V em que vai ser conectado, IDEDisk - Disco IDE que vai ser configurado na máquina virtual e por último VHDParent - o VHD do parente caso você escolha usar um diferential disk.

Analisando os registros do exemplo acima consigo explicar o funcionamento do script.

LAB01 – Quando fizer uma referência a um arquivo VHD explicitamente no campo IDEDisk, como na linha do LAB01, o mesmo deve existir no diretório padrão, dentro de um subdiretório com o mesmo nome da máquina virtual. Por exemplo, o VHD do LAB01, tendo como premissa o diretório padrão G:\VMs, deve estar em G:\VMs\LAB01\W7Test.VHD.
Esse é o caso de quando você criar uma VM base, faz um sysprep e copia a VM para um ou vários diretórios. A ferramenta mais indicada para copiar arquivos grande é o robocopy. Eu fiz um .bat que copia tudo que eu preciso, mas a estrutura principal é a linha abaixo:
robocopy [Diretório de Origem] [Diretório de Destino] *.vhd /mt:8

LAB02- Para criar um VHD novo basta colocar a palavra new no campo IDEDisk. Neste caso será criado o arquivo G:\VMs\LAB02\LAB-02-DriveC.VHD.

LAB03 – Quando for usar um disco diferencial, a referencia do VHDParent deve conter o caminho completo, pois muitas vezes os arquivos do tipo parente não ficam no mesmos discos que os arquivos das VMs.
Caso o nome da rede não corresponda a uma já existente no servidor Hyper-V, ou o arquivo VHD referenciado ou do parent não existam, o script não processa aquele registro e emite uma mensagem de Warning.

LAB04 - Não vai ser processado pois o caracter # na frente do nome diz ao script para pular o registro

Abaixo o script que eu chamei CreateVMs.ps1. Espero que ajude.

Import-Module 'C:\Program Files\modules\HyperV\HyperV.psd1'

Function Check-SwitchName([string]$strName, [string]$strComputerName) {
$VirtualServerSwitches = Get-WmiObject -NameSpace  "root\virtualization" -Class "MsVM_VirtualSwitch" -ComputerName $strComputerName
foreach ($vmSwitch in $VirtualServerSwitches) {
   if ($vmSwitch.ElementName -eq $strName) { return $true }  
}
return $false
}

function Read-Default([string]$strmessage, [string]$strDefault)
{
Write-Host $strmessage -NoNewline -ForegroundColor White
if ($strDefault.length -gt 0) { Write-Host " [$strDefault] : " -NoNewline -ForegroundColor Yellow }
else { Write-Host ": " -NoNewline }
$result = Read-Host
if ($result.length -eq 0 ) {$result = $strDefault}
$result
}

[string]$defaultCSV =  Get-Location
$defaultCSV += "\VMs.csv"
$csvFile = Read-Default "Please enter CSV file name" $defaultCSV
$fTest = Test-Path $csvFile
if ($fTest -eq $false) {
   Write-Host $csvFile " File not found" -ForegroundColor Red -BackgroundColor black
   Exit (1)
}
$strHostName = hostname
$VMHost  = Read-Default "Please enter Hyper-V hostname" $strHostName

$strMachines  = Import-CSV $csvFile

foreach ($strVm in $strMachines){
 $vmName = $strVm.Name
 $vmCPU = $strVm.CPU
 $vmMemory = $strVm.Memory
 $vmNetName = $strVm.NetName
 $vmIDEDisk = $strVm.IDEDisk
 $vmVHDParent = $strVm.VHDParent
    
    if ($vmName.substring(0,1) -eq "#") { continue }
 
 if ($vmName -eq $null -or $vmCPU -eq $null -or $vmMemory -eq $null -or $vmName -eq $null -or $vmIDEDisk -eq $null) {
  write-host -ForegroundColor yellow -BackgroundColor black "Missing information, skipping record."
        continue
 }
 
 if ($vmIDEDisk.contains(":")) {
        write-host write-host -ForegroundColor yellow -BackgroundColor black "Skipping $vmName - Do not specify full path name for IDE disks."
        continue
    }
 
 $bNew = $false
 if ($vmIDEDisk.ToLower() -eq "new" ) {
    $vmIDEDisk = $(get-VHDdefaultPath) + $vmName + "\" + $vmName + "-DriveC.VHD"
    if ((Test-Path $vmIDEDisk) -eq $true) { Remove-Item $vmIDEDisk }
   
    $bNew = $true}
 else {
    $vmIDEDisk = $(get-VHDdefaultPath) + $vmName + "\" + $vmIDEDisk
       if ((Test-Path $vmIDEDisk) -eq $false) {
       write-host -ForegroundColor yellow -BackgroundColor black "Skipping $vmName - Disk $vmIDEDisk not found"
          continue
    }
 }
   
 if ((Check-SwitchName $vmNetName $VMHost) -eq $false) {
  write-host -ForegroundColor yellow -BackgroundColor black "Skipping $vmName - VirtualSwitch $vmNetName does not exist"
        continue
 }
 
 $bParent = $false
 if ($vmVHDParent -ne "" ) {
  if ($vmVHDParent.IndexOf(":") -lt 1) {
         write-host -ForegroundColor yellow -BackgroundColor black "Skipping $vmName - Please, specify full path name for VHD parent disk."
         continue
  }
  else {
   if ((Test-Path $vmVHDParent) -eq $false) {
        write-host -ForegroundColor yellow -BackgroundColor black "Skipping $vmName - VHDParent $vmVHDParent not found."
           continue
      }
  }
 $bParent = $true
    }
   
 # create a new virtual machine
 $vm = New-VM $vmName -server $VMHost
 Set-VMCPUCount $vmName $vmCPU  |Out-Null
 Set-VMMemory $vmName -Memory $vmMemory |Out-Null
 Add-vmNIC $vmName $vmNetName |Out-Null
 
  if ($bParent -and $bNew) {
        New-VHD -VHDPaths $vmIDEDisk -ParentVHDPath $vmVHDParent
        Add-VMDisk $vmName 0 0 -Path $vmIDEDisk
     }
    
     if ($bParent -eq $false -and $bNew) {
        New-VHD  -VHDPaths $vmIDEDisk
        Add-VMDisk $vmName 0 0 -Path $vmIDEDisk
     }
    
     if ($bParent -eq $false -and $bNew -eq $false) {
     Add-VMDisk $vmName 0 0 $vmIDEDisk
     }
     
 #Adds a DVD drive to IDE O slot 1
 Add-VMDRIVE $vmName -controllerID 0 -lun 1 -DVD  
}

  • Artur, show de bola!

    Segue um outro link com "PowerShell management library for Hyper-V"

    http://pshyperv.codeplex.com/

    Abraços.

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment