VMWare: Creazione VMs e Redistribuzione su Datastore

VMWare: Creazione VMs e Redistribuzione su Datastore

640 427 Nicola Montemurro

VMWare: Creazione Massiva di Virtual Machine e Redistribuzione su Datastore

L’implementazione di più macchine virtuali (VMs) VMware, da template, può semplificare la gestione della virtualizzazione e far risparmiare tempo. Come implementare in modo efficace più VMs da template?

Un metodo consiste nell’utilizzare utilizzare i modelli in vSphere personalizzando il sistema operativo guest durante la distribuzione di nuove macchine virtuali dal template, ma si tratta comunque di un’operazione lunga e noiosa, oppure un altro metodo consiste nel creare uno script PowerCLI (Powershell) che automatizzi completamente tale operazione.

Lo script PowerCLI, indicato in seguito, utilizzando un file CSV contenente i parametri specifici permette l’implementazione massiva di Virtual Machines assicurando che il deploy avvenga:

  • su datastore specifici (uno o più)  escludendone (eventualmente) altri, assicurando che sia mantenuto lo spazio residuo “vitale” sul datastore stesso.
  • installazione/aggiornamento dei vmware tools
  • assegnazione della scheda di rete specifica
  • assegnazione della vlan specifica
  • assegnazione del nome host (Sistema Operativo),
  • join a dominio

File: BulkVMFromTemplate.csv (dati di esempio)

"vmname","domain","vlan","vmlocation","template","datacenter","cluster"
VM-TEST01,company.loc,VLAN 551 Company-SmartWorking,TEST-DIR,WIN10-CLEAN,DATACENTER,TESTCLUSTER
VM-TEST02,company.loc,VLAN 551 Company-SmartWorking,TEST-DIR,WIN10-CLEAN,DATACENTER,TESTCLUSTER
VM-TEST03,company.loc,VLAN 551 Company-SmartWorking,TEST-DIR,WIN10-CLEAN,DATACENTER,TESTCLUSTER
VM-TEST04,company.loc,VLAN 551 Company-SmartWorking,TEST-DIR,WIN10-CLEAN,DATACENTER,TESTCLUSTER

Script: BulkVMFromTemplate.ps1

#----------------------------------------------------------------------------
# - File Name     : BulkVMFromTemplate.ps1
# - Author        : Nicola Montemurro
# - Administrator : Nicola Montemurro  -
# - Create        : 07/02/2022
# - Last Update   : 18/02/2022
# - Description   : Crea e Ditribuisce VM in modo automatizzato  
# - Position      : C:\vmtools\ps
# - Note          : NON modificare senza AUTORIZZAZIONE dell'AMMINISTRATORE
#----------------------------------------------------------------------------

#### USER DEFINED VARIABLES #################################################

## Versione 1.0.0

$viUser = "svcdeployvm@vsphere.local"

$viPassword = "***Deploy1.***"

$DEFvmname = "RAND-"                   # VMNAME - if empty in csv will be randomized by function
$DEFmsdomain = "MSDomain"              # AD Domain to join - if empty in csv this will be used
$DEFvlan = "VLAN 152"                  # vlan (portgroup) to use for VM - if empty in csv this will be used
$DEFvmlocation = "vmlocation"          # vCenter location (dir) to deploy VM - if empty in csv this will be used
$DEFvmtemplate = "WIN10CLEAN"          # vCenter template to deploy VM - if empty in csv this will be used
$DEFCluster = "CLUSTER1"               # vCenter cluster to deploy VM - if empty in csv this will be used

$filename = "C:\vcc_tools\Scripts\DeployVM\BulkVMFromTemplate.csv" # Name and Location of file .csv 

#Account locale del Template - deve essere previsto
$GuestUser  = "vmware"
$GuestUserPassword = "VMPassword"


#Active Directory Account - deve essere censito in ogni dominio per la join con diritti di Account Operators
$DomainUser = "domainuser"
$DomainPassword = "s^&tK8Ih^XZ@t=K?y5w}jztq"

############# DATASTORE

### GB
$RetSpace = 1024                       # Datastore space excluded from provisionable space in GB

$dsexcluded = @("DELL002_LUN_12")      # Datastore excluded by provisioning es. --> $dsexcluded = @("DELL002_LUN_12", "DELL002_LUN_04")

### LINKS

#  https://developer.vmware.com/home

#  https://docs.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-arrays?view=powershell-7.2#arrays-of-objects

#  https://vdc-repo.vmware.com/vmwb-repository/dcr-public/cdbbd51c-4824-4a1b-ad43-45df55a76a76/8cb3ed93-cac2-46aa-b329-db5a096af5bc/doc/GUID-60396B03-9589-4E40-8D36-383638653C5C.html

[Array]$VMList = @()

[array]$NetAdapterType = @('Unknown', 'e1000', 'e1000e', 'Flexible', 'Vmxnet', 'EnhancedVmxnet', 'Vmxnet3')

    $header = @("vmname", "domain", "vlan", "vmlocation", "template", "datacenter", "cluster")    

    Import-Csv $fileName -Header $header -Delimiter "`," | select -skip 1 | Foreach-Object {

    foreach ($row in $fileName) {
        # UNSET Variables
        $vmname = $null
        $domain = $null
        write-host "primo dominio"
        $domain
        $vlan = $null
        $vmlocation = $null
        $template = $null
        $datacenter = $null
        $cluster = $null
      
        #  ASSIGN Values to Variables

        $vmname = "$($_.vmname)"
        $domain = "$($_.domain)"
        write-host "secondo dominio"
        $domain
        $vlan = "$($_.vlan)"
        $vmlocation = "$($_.vmlocation)"
        $template = "$($_.template)"
        $datacenter = "$($_.datacenter)"
        $cluster = "$($_.cluster)"

        if (!$vmname) { 
            $objRand = new-object random
            $vmname = $DEFvmname + $objRand.next(100,9999)
        }
            elseif (!$vlan) {$vlan = $DEFvlan}
            elseif (!$vmlocation) {$vlan = $DEFvmlocation}
            elseif (!$template) {$template = $DEFtemplate}
            elseif (!$datacenter) {$datacenter = $DEFdatacenter}
            elseif (!$cluster) {$cluster = $DEFcluster}

        # The Name my be exists in the list

           if ( -not ($VMList -match $vmname )) {
                $VMList += @([pscustomobject]@{
                                vmname=$vmname
                                domain=$domain
                                vlan=$vlan
                                vmlocation=$vmlocation
                                template=$template
                                cluster=$cluster
                                }
                            )
            }
        }
    }

function GetDatastoreSpace {

    [Array]$DSList = @()

    $datastores = Get-Datastore -ErrorAction SilentlyContinue

    Foreach ($datastore in $datastores) {

    if ( -not ($datastore -in $dsexcluded) -and (-not ($datastore.name -match "DSMIL1" )) ) {

                ## Provisionable Space
                $dspspace = [Math]::Round($datastore.FreeSpaceGB - $RetSpace, 2)

                $DSList += @([pscustomobject]@{
                                datastore=$datastore
                                name = $datastore.Name
                                dspspace=$dspspace
                                }
                        )
            }
    }

    Return [array]$DSList
}

function GetMostCapabilityDatastore() {

    [array]$DSList = @(GetDatastoreSpace | where {$_})

    $max = 0
    $DSList | Foreach-Object { 
        if ($max -le $_.dspspace){

            $max = $_.dspspace
            $RetVal = $_
        } 
        
    }
    Return $RetVal
}

function WaitForTools {
[CmdletBinding()]
Param([Parameter(Mandatory=$true,ValueFromPipeline=$True, Position=0)][VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] $VM
)

   function RefreshExtensionData {
        Return $VMExtensionData = Get-VM -Name $VM | Get-VMToolsStatus
    }

 
    RefreshExtensionData

    $PowerStatus = Get-VM -Name $VM

    if ( $PowerStatus -eq "PoweredOn") {
        
        if ($VMExtensionData.ToolsStatus -eq "toolsNotRunning") {
            
            do {
                # Wait 5 seconds
                $Wait = 5

                Start-Sleep -s $Wait
                # Check the Max Time to sleep
                $MaxTimeToSleep = $MaxTimeToSleep + $wait

                #Write-Host "$wait, $MaxTimeToSleep"

                RefreshExtensionData
                Write-Host "Waiting for starting VMWare Tools on $VM" -ForegroundColor Yellow -BackgroundColor Black
            }
       
            until( ($VMExtensionData.ToolsStatus -eq "toolsOk") -or ( $MaxTimeToSleep -ge 60) ) {
                
            }

        }
    }
}

function Get-VMToolsStatus {
[CmdletBinding()]
Param([Parameter(Mandatory=$true,ValueFromPipeline=$True, Position=0)][VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] $VM,
$VMObj
)

    $VMObj = $VM.ExtensionData.Guest

    Return $VMObj
}

function SetVideoCard {
param([Parameter(Mandatory=$true,ValueFromPipeline=$True, Position=0)][VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] $VM,
      [Parameter(Mandatory=$false)][bool]$Autodetect=$true,
      [Parameter(Mandatory=$false)][int32]$MemoryMB
)
    $spec = New-Object VMware.Vim.VirtualMachineConfigSpec
    $Config = New-Object VMware.Vim.VirtualDeviceConfigSpec

    Get-VM -name $VM  | Foreach { $VideoAdapter = $_.ExtensionData.Config.Hardware.Device | Where {$_.GetType().Name -eq "VirtualMachineVideoCard"}
               
        $Config.device = $VideoAdapter
        
        if ( $Config.device.useAutoDetect -ne $Autodetect ) {

            if ($MemoryMB) {
                $Config.device.videoRamSizeInKB = $MemoryMB * 1KB
            }

            if ($AutoDetect) {
                $Config.device.useAutoDetect = $true
            }
            else
            {
                $Config.device.useAutoDetect = $false
            }

                
            $Config.operation = "edit"

            $spec.deviceChange += $Config

            $VMView = $_ | Get-View

            Write-Host "Setting Video Display for $VM"

            $VMView.ReconfigVM($spec)
        }

    }        
}

function SetNetworkCardType {
[CmdletBinding()]
Param( [Parameter(Mandatory=$true,ValueFromPipeline=$True, Position=0)][VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] $VM,
      [Parameter(Mandatory=$false)][VMware.VimAutomation.ViCore.Types.V1.VirtualDevice.VirtualNetworkAdapterType]$NetAdapterType='Vmxnet3',
      [Parameter(Mandatory=$true)][String] $vlan,
      [Parameter(Mandatory=$false)]$WOL=$false #WakeOnLan
    )
          # Unknown, e1000, e1000e, Flexible, Vmxnet, EnhancedVmxnet, Vmxnet3, SriovEthernetCard, Vmxnet3Vrdma

    if ( ($VM | Get-NetworkAdapter -Name "Network adapter 1" | where { $_.Type -ne $NetAdapterType }) ) {

        $VM | Get-NetworkAdapter -Name "Network adapter 1" | Set-NetworkAdapter -Type $NetAdapterType -NetworkName $vlan -StartConnected $True -Confirm:$false
        Write-Host "$VM - Setting Network Adapter Type to $NetAdapterType"
                
    }
                
}


function StartAndGo {
[CmdletBinding()]
Param([Parameter(Mandatory=$true,ValueFromPipeline=$True, Position=0)][VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] $VM
)
    $PowerStatus = Get-VM -Name $VM
    
    if ($PowerStatus.PowerState -eq "PoweredOff") {
        
        Write-Host "Start $VM and GO"
        [bool]$RetBool = Start-VM $VM -Confirm:$false
    }            
   
   Return $RetBool    
}

function StartAndWait {
[CmdletBinding()]
Param([Parameter(Mandatory=$true,ValueFromPipeline=$True, Position=0)][VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] $VM
)
    function RefreshExtensionData {
        $RetExtensionData = Get-VM -Name $VM | Get-VMToolsStatus
        Return $RetExtensionData
    }

    $VMExtensionData = RefreshExtensionData

    $PowerStatus = Get-VM -Name $VM
    
     if ($PowerStatus.PowerState -eq "PoweredOff") {
     
        
        Write-Host "Powering  On $VM"

        Start-VM $VM -Confirm:$false
                
        Write-Host "Please wait while $VM is started" -ForegroundColor Yellow -BackgroundColor Black
            
        do {
            # Wait 5 seconds
            $Wait = 5

            Start-Sleep -s $Wait
            # Check the Max Time to sleep
            $MaxTimeToSleep = $MaxTimeToSleep + $wait

            #Write-Host "$wait, $MaxTimeToSleep"
            $VMExtensionData = RefreshExtensionData
            Write-Host "Please wait while $VM is started" -ForegroundColor Yellow -BackgroundColor Black
        }
       
        until ( ($VMExtensionData.ToolsStatus -eq "toolsOk") -or ($MaxTimeToSleep -ge 120) ) {
        }
    }
}

function ShutdownVM {
[CmdletBinding()]
Param([Parameter(Mandatory=$true,ValueFromPipeline=$True, Position=0)][VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] $VM
)

    function RefreshPowerStatus {
        $RetPowerStatus = Get-VM -Name $VM
        Return $RetPowerStatus 
    }
    
    $PowerStatus = RefreshPowerStatus

    if ($PowerStatus.PowerState -eq "PoweredOn") {
        
        Write-Host "Powering  Off $VM"

        Shutdown-VMGuest $VM -Confirm:$false

        Write-Host "Please wait while $VM is stopped" -ForegroundColor Yellow -BackgroundColor Black
            
        do {
            # Wait 5 seconds
            $Wait = 5

            Start-Sleep -s $Wait
            # Check the Max Time to sleep
            $MaxTimeToSleep = $MaxTimeToSleep + $wait

            #Write-Host "$wait, $MaxTimeToSleep"
            # Check the power status
            $PowerStatus = RefreshPowerStatus
            ##  $VM.PowerState
            Write-Host "Please wait while $VM is stopped" -ForegroundColor Yellow -BackgroundColor Black
        }
            
        until (($PowerStatus.PowerState -eq "PoweredOff") -or ($MaxTimeToSleep -ge 120)) {
    
        }
    } 
}

function RestartVM {
[CmdletBinding()]
Param([Parameter(Mandatory=$true,ValueFromPipeline=$True, Position=0)][VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] $VM
)

    function RefreshExtensionData {
        $RetExtensionDate = Get-VM -Name $VM | Get-VMToolsStatus
        Return $RetExtensionDate
    }

    $VMExtensionData = RefreshExtensionData

    $PowerStatus = Get-VM -Name $VM

    if ($PowerStatus.PowerState -eq "PoweredOn") {
        
        Write-Host "Restarting $VM"

        Restart-VMGuest $VM -Confirm:$false

        Write-Host "Please wait while $VM is restarted" -ForegroundColor Yellow -BackgroundColor Black
            
        do {
            # Wait 5 seconds
            $Wait = 5

            Start-Sleep -s $Wait

            # Check the Max Time to sleep
            $MaxTimeToSleep = $MaxTimeToSleep + $wait

            #Write-Host "$wait, $MaxTimeToSleep"

            $VMExtensionData = RefreshExtensionData

            Write-Host "Please wait while $VM is restarted" -ForegroundColor Yellow -BackgroundColor Black
        }
            
        until ( ($PowerStatus.PowerState -eq "PoweredOn") -and (($VMExtensionData.ToolsStatus -eq "toolsOk") -or ($MaxTimeToSleep -ge 120)) ) {
    
        }
    } 
}

## https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.vsphere-lifecycle-manager.doc/GUID-12649CBB-F69A-4199-8957-B4C0170B4E9A.html

function GetVMToolsInstalled {
[CmdletBinding()]
Param([Parameter(Mandatory=$true,ValueFromPipeline=$True, Position=0)][VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] $VM
)
    $RetBool = $true

    $PowerStatus = Get-VM -Name $VM
    $VMExtensionData = Get-VM -Name $VM | Get-VMToolsStatus

    if ( $PowerStatus.PowerState -eq "PoweredOn") {

        ### Se non sono installati o sono obsoleti False
        if (($VMExtensionData.ToolsStatus -eq "toolsNotInstalled") -or ($VMExtensionData.ToolsVersionStatus -ne "guestToolsCurrent")) {
            
            $RetBool = $False
        }
    }

    Return $RetBool
}

function ToolsUpgrade {
[CmdletBinding()]
Param([Parameter(Mandatory=$true,ValueFromPipeline=$True, Position=0)][VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] $VM
    )

    Update-Tools -VM $VM -NoReboot | Wait-Tools

}

#https://docs.vmware.com/en/VMware-Tools/11.3.0/com.vmware.vsphere.vmwaretools.doc/GUID-E45C572D-6448-410F-BFA2-F729F2CDA8AC.html

function ToolsInstall {
[CmdletBinding()]
Param([Parameter(Mandatory=$true,ValueFromPipeline=$True, Position=0)][VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] $VM
    )

    Mount-Tools -VM $VM
    Invoke-VMScript -VM $VM -ScriptText {'D:\setup64.exe /s /v" /qb addlocal=all remove=hgfs,VSS,AppDefense,NetworkIntrospection"'} -ScriptType Powershell -GuestUser $GuestUser -GuestPassword $GuestUserPassword
    Dismount-Tools -VM $VM

}
            

function SetVlan {
[CmdletBinding()]
Param([Parameter(Mandatory=$true,ValueFromPipeline=$True, Position=0)][VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] $VM,
      [Parameter(Mandatory=$true)]$vlan
    )

    if ( Get-VM | where { ($_ | Get-NetworkAdapter | where ({($_.Name -eq "Network adapter 1") -and ($_.NetworkName -ne $vlan) })) } ) {
        
                Get-NetworkAdapter -VM $VM | where {$_.Name -eq "Network adapter 1"} | Set-NetworkAdapter -NetworkName $vlan -WakeOnLan $False -Confirm:$false
    }
}

## https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/rename-computer?view=powershell-7.2

function SetComputerName {
[CmdletBinding()]
Param([Parameter(Mandatory=$true,ValueFromPipeline=$True, Position=0)][VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] $VM,
      [Parameter(Mandatory=$true)][String]$ComputerName
    )
    
    $ScriptText = "Rename-Computer -NewName $($ComputerName)"
    $ScriptObj = Invoke-VMScript -VM $VM -ScriptText $ScriptText -ScriptType Powershell -GuestUser $GuestUser -GuestPassword $GuestUserPassword
    
    $ScriptObj.ScriptOutput
    $ScriptObj.ExitCode
}

## https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/dd349804(v=ws.10)#BKMK_4
## https://docs.microsoft.com/en-us/powershell/scripting/learn/deep-dives/add-credentials-to-powershell-functions?view=powershell-7.2

function JoinToDomain {
[CmdletBinding()]
Param([Parameter(Mandatory=$true,ValueFromPipeline=$True, Position=0)][VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] $VM,
      [Parameter(Mandatory=$true)][String]$Domain,
      [Parameter(Mandatory=$true)][String]$DomainUser,
      [Parameter(Mandatory=$true)][String]$DomainPassword
    )

    $User = "$DomainUser@$Domain"

    $SecPasswd = ConvertTo-SecureString $DomainPassword -AsPlainText -Force
    $Credential = $User,($DomainPassword | ConvertTo-SecureString -AsPlainText -Force)

    $ScriptText = "Add-computer -DomainName $($Domain) -Credential $($Credential)"

    Write-Host "Invoke-VMScript -VM $VM -ScriptText $ScriptText -ScriptType Powershell -GuestUser "$GuestUser" -GuestPassword $GuestUserPassword"

    $ScriptObj = Invoke-VMScript -VM $VM -ScriptText $ScriptText -ScriptType Powershell -GuestUser $VM\$GuestUser -GuestPassword $GuestUserPassword
    
    Write-Host $ScriptObj.ScriptOutput
    Write-Host $ScriptObj.ExitCode
}

function DoBulkVM {

    $User = "$DomainUser@$Domain"

    $StartingTime = $(get-date -f hh:mm:ss)

    $SecPasswd = ConvertTo-SecureString $DomainPassword -AsPlainText -Force
    $Credential = New-Object System.Management.Automation.PSCredential ($User, $SecPasswd) 

    write-host "++++++++++++++++++++++++++++++++++++++++++"
    write-host "++++++++++++++++++++++++++++++++++++++++++"
    write-host "Inserire il Vcenter sul quale iniziare il deploy delle VM - digitare il numero corrispondente e premere invio"  -ForegroundColor Red -BackgroundColor Yellow
    write-host "." -ForegroundColor Red -BackgroundColor Yellow
    write-host "1 -> vcenter11.vcserver.vmdomain.lan" -ForegroundColor Red -BackgroundColor Yellow
    write-host "2 -> vcenter10.vcserver.vmdomain.lan" -ForegroundColor Red -BackgroundColor Yellow
    write-host "3 -> vcenter13.vcserver.vmdomain.lan" -ForegroundColor Red -BackgroundColor Yellow
    write-host "4 -> vcenter14.vcserver.vmdomain.lan" -ForegroundColor Red -BackgroundColor Yellow

    $vcenter = read-host

    switch ($vcenter)
    {
    1 {$vcenterserver = "vcenter11.vcserver.vmdomain.lan"}
    2 {$vcenterserver = "vcenter10.vcserver.vmdomain.lan"}
    3 {$vcenterserver = "vcenter13.vcserver.vmdomain.lan"}
    4 {$vcenterserver = "vcenter14.vcserver.vmdomain.lan"}
    default{"No Match Found"}
    }


    Connect-VIServer -Server $vcenterserver -User $viUser -Password $viPassword

    for($i=0; $i -lt $VMList.Length; $i++)
    {
    
        $VMexists = Get-VM -name $VMList[$i].vmname -ErrorAction SilentlyContinue
                
        $ComputerADexist = $null
                $VMList[$i].Domain

        $User = "$DomainUser@$Domain"
        $SecPasswd = ConvertTo-SecureString $DomainPassword -AsPlainText -Force
        $creds = New-Object System.Management.Automation.PSCredential -ArgumentList ($user, $SecPasswd)
        $ComputerADexist = get-adcomputer $VMList[$i].vmname -server $VMList[$i].Domain -Credential $($creds)
        #write-host "computer exist - $ComputerADexist"
        #write-host "vmexist $VMexists"
           
        if (!$VMexists -and !$ComputerADexist) {

            $retobject= GetMostCapabilityDatastore

            try {
                $OSCS = New-OSCustomizationSpec -OSType Windows -ChangeSid -Domain $VMList[$i].Domain -OrgName "Covisian" -DomainCredentials $Credential -NamingScheme fixed -TimeZone "100" -NamingPrefix $VMList[$i].vmname -FullName $GuestUser -AdminPassword $GuestUserPassword
                $VM = New-VM -Name $VMList[$i].vmname -Location $VMList[$i].vmlocation -Template $VMList[$i].template -ResourcePool $VMList[$i].cluster -Datastore $retobject.Datastore -DiskStorageFormat EagerZeroedThick -OSCustomizationSpec $OSCS
                Write-Host "$VM on $retobject.Name has been created "
            #    StartAndGo -VM $VM

                ## SETTING NETWORK CARD
                Write-host "SetNetworkCardType on $VM"
                SetNetworkCardType -VM $VM -NetAdapterType 'Vmxnet3' -vlan $VMList[$i].vlan
        
                ## SETTING VIDEO CARD
                Write-host "SetVideoCard on $VM"
                SetVideoCard -VM $VM -Autodetect $True

                ## SETTING VLAN
                Write-host "SetVlan $VMList[$i].vlan on $VM"
                SetVlan -VM $VM -vlan $VMList[$i].vlan
                StartAndGo -VM $VM
            }
            catch 
            {


            }

            $EndingTime = $(get-date -f hh:mm:ss)
        } 
    }

    Write-host "Started: " + $StartingTime + " Ended: + $EndingTime"
    Disconnect-VIServer -Server $vcenterserver -Confirm:$false
}

### https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/sysprep-command-line-options?view=windows-11

### DO BULKING PROCESS
### MAIN ####
DoBulkVM

Considerazioni Finali

Lo script appena mostrato è stato concepito per il deploy di VMs Windows, ma può essere utilizzato come “suggerimento” per la costruzione di altri script per Sistemi Operativi differenti oppure per sistemi VMWare strutturati in modo differente.

    Preferenze Privacy

    Quando visiti il nostro sito web, possono essere memorizzate alcune informazioni, di servizi specifici, tramite il tuo browser, di solito sotto forma di cookie. Qui puoi modificare le tue preferenze sulla privacy. Il blocco di alcuni cookie può influire sulla tua esperienza sul nostro sito Web e sui servizi che offriamo.

    Questo sito web utilizza cookie, principalmente di terze parti. Personalizza le preferenze sulla privacy e/o acconsenti all'utilizzo dei cookie.