Powercli Delete Orphaned Edge Transport Nodes

I made a little mistake on my Lab Environment. There fore it was required to clean up my last unremoveable edge server.

Sow i made a little powercli script

RemoveOrphanedEdge.ps1

# https://kb.vmware.com/s/article/892835
# https://virtuallyjason.blogspot.com/2020/11/using-nsx-t-api.html

$nsxfqdn = Read-Host “Give the IP of the FQDN from your NSX Server”
if (!($creds)){

$creds = Get-Credential -Message "NSX-T Administrative Credentials:"

}
$base64Creds = [Convert]::toBase64String([System.Text.Encoding]::UTF8.GetBytes(“$($creds.username):$($creds.GetNetworkCredential().password)”))
$header = @{Authorization = “Basic $base64Creds”}
$uri = “https://$nsxserver”

# Check API Connection

invoke-webrequest -uri “$uri/api/v1/spec/openapi/nsx_api.json” -headers $header -SkipCertificateCheck

# Clean Stale Entries

invoke-webrequest -uri “$uri/api/v1/transport-nodes?action=clean_stale_entries” -headers $header -Method ‘POST’ -SkipCertificateCheck

Holodeck Toolkit Overview

Holodeck Toolkit 1.3 Overview

The VMware Cloud Foundation (VCF) Holodeck Toolkit is designed to provide a scalable, repeatable way to deploy nested Cloud Foundation hands-on environments directly on VMware ESXi hosts. These environments are ideal for multi-team hands on exercises exploring the capabilities of utilitizing VCF to deliver a Customer Managed VMware Cloud.

Graphical user interface, application

Description automatically generated

Delivering labs in a nested environment solves several challenges with delivering hands-on for a  product like VCF, including:  

  • Reduced hardware requirements: When operating in a physical environment, VCF requires four vSAN Ready Nodes for the management domain, and additional hosts for adding clusters or workload domains. In a nested environment, the same four to eight hosts are easily virtualized to run on a single ESXi host.   
  • Self-contained services: The Holodeck Toolkit configuration provides common infrastructure services, such as NTP, DNS, AD, Certificate Services and DHCP within the environment, removing the need to rely on datacenter provided services during testing.  Each environment needs a single external IP.
  • Isolated networking. The Holodeck Toolkit configuration removes the need for VLAN and BGP connections in the customer network early in the testing phase.  
  • Isolation between environments. Each Holodeck deployment is completely self-contained. This avoids conflicts with existing network configurations and allows for the deployment of multiple nested environments on same hardware or datacenter with no concerns for overlap. 
  • Multiple VCF deployments on a single VMware ESXi host with sufficient capacity. A typical VCF Standard Architecture deployment of four node management domain and four node VI workload domain, plus add on such as VMware vRealize Automation requires approximately 20 CPU cores, 512GB memory and 2.5TB disk.  
  • Automation and repeatability. The deployment of nested VCF environments is almost completely hands-off, and easily repeatable using configuration files.  A typical deployment takes less than 3 hours, with less than 15 min keyboard time.

Nested Environment Overview 

The “VLC Holodeck Standard Main 1.3” configuration is a nested VMware Cloud Foundation configuration used as the baseline for several Private Cloud operation and consumption lab exercises created by the Cloud Foundation Technical Marketing team. The Holodeck standard “VLC-Holo-Site-1” is the primary configuration deployed. The optional VLC-Holo-Site-2 can be deployed at any time later within a Pod.  VLC-Holo-Site-1 configuration matches the lab configuration in the VCF Hands-On Lab HOL-2246 and the nested configuration in the VCF Experience program run on the VMware Lab Platform. 

Each Pod on a Holodeck deployment runs an identical nested configuration. A pod can be deployed with a standalone VLC-Holo-Site-1 configuration, or with both VLC-Holo-Site-1 and VLC-Holo-Site-2 configurations active. Separation of the pods and between sites within a pod is handled at the VMware vSphere Standard Switch (VSS) level.  Each Holodeck pod connects to a unique VSS and Port Group per site.    A VMware vSphere Port Group is configured on each VSS and configured as a VLAN trunk.  

  • Components on the port group to use VLAN tagging to isolate communications between nested VLANs. This removes the need to have physical VLANs plumbed to the ESXi host to support nested labs.  
  • When the Holo-Site-2 configuration is deployed it uses a second VSS and Port Group for isolation from Holo-Site-1  

The VLC Holodeck configuration customizes the VCF Cloud Builder Virtual Machine to provide several support services within the pod to remove the requirement for specific customer side services. A Cloud Builder VM is deployed per Site to provide the following within the pod: 

  • DNS (local to Site1 and Site2 within the pod, acts as forwarder) 
  • NTP (local to Site1 and Site2 within the pod) 
  • DHCP (local to Site1 and Site2 within the pod) 
  • L3 TOR for vMotion, vSAN, Management, Host TEP and Edge TEP networks within each site 
  • BGP peer from VLC Tier 0 NSX Application Virtual Network (AVN) Edge (Provides connectivity into NSX overlay networks from the lab console)

The figure below shows a logical view of the VLC-Holo-Site-1 configuration within a Holodeck Pod. The Site-1 configuration uses DNS domain vcf.sddc.lab.

 Figure 1: Holodeck Nested Diagram

The Holodeck package also provides a preconfigured Photon OS VM, called “Holo-Router”, that functions as a virtualized router for the base environment. This VM allows for connecting the nested environment to the external world. The Holo-Router is configured to forward any Microsoft Remote Desktop (RDP) traffic to the nested jump host, known as the Holo-Console, which is deployed within the pod.

The user interface to the nested VCF environment is via a Windows Server 2019 “Holo-Console” virtual machine. Holo-Console provides a place to manage the internal nested environment like a system administrators desktop in a datacenter. Holo-Console is used to run the VLC package to deploy the nested VCF instance inside the pod. Holo-Console VM’s are deployed from a custom-built ISO that configures the following 

  • Microsoft Windows Server 2019 Desktop Experience with: 
  • Active directory domain “vcf.holo.lab” 
  • DNS Forwarder to Cloud Builder  
  • Certificate Server, Web Enrollment and VMware certificate template 
  • RDP enabled 
  • IP, Subnet, Gateway, DNS and VLAN configured for deployment as Holo-Console  
  • Firewall and IE Enhanced security disabled  
  • SDDC Commander custom desktop deployed 
  • Additional software packages deployed and configured 
  • Google Chrome with Holodeck bookmarks 
  • VMware Tools 
  • VMware PowerCLI 
  • VMware PowerVCF 
  • VMware Power Validated Solutions 
  • PuTTY SSH client 
  • VMware OVFtool 
  • Additional software packages copied to Holo-Console for later use 
  • VMware Cloud Foundation 4.5 Cloud Builder OVA to C:\CloudBuilder 
  • VCF Lab Constructor 4.5.1 with dual site Holodeck configuration
    • VLC-Holo-Site-1 
    • VLC-Holo-Site-2 
  • VMware vRealize Automation 8.10 Easy Installer

The figure below shows the virtual machines running on the physical ESXi host to deliver a Holodeck Pod called “Holo-A”. Notice an instance of Holo-Console, Holo-Router, Cloud Builder and four nested ESXi hosts.  They all communicate over the VLC-A-PG Port Group   

Figure 2: Holodeck Nested Hosts

Adding a second site adds an additional instance of Cloud Builder and additional nested ESXi hosts. VLC-Holo-Site-2 connects to the second internal leg of the Holo-Router on VLAN 20. Network access from the Holo-Console to VLC-Holo-Site-2 is via Holo-Router.

The figure below shows a logical view of the VLC-Holo-Site-2 configuration within a Holodeck Pod. The Site-2 configuration uses DNS domain vcf2.sddc.lab

 Figure 3: Holodeck Site-2 Diagram

Accessing the Holodeck Environment

User access to the Holodeck pod is via the Holo-Console.  Access to Holo-Console is available via two paths:

VLC Holodeck Deployment Prerequisites 

  • ESXi Host Sizing   
  • Good (One pod): Single ESXi host with 16 cores, 384gb memory and 2TB SSD/NVME 
  • Better (Two pod): Single ESXi host with 32 cores, 768gb memory and 4TB SSD/NVME 
  • Best (Four or more pods):  Single ESXi host with 64+ cores, 2.0TB memory and 10TB SSD/NVME 
  • ESXi Host Configuration: 
  • vSphere 7.0U3 
  • Virtual switch and port group configured with uplinks to customer network/internet  
  • Supports stand alone, non vCenter Server managed host and single host cluster managed by a vCenter server instance 
  • Multi host clusters are NOT supported
  • Holo-Build host 
  • Windows 2019 host or VM with local access to ESXI hosts used for Holodeck + internet access to download software. (This package has been tested on Microsoft Windows Server 2019 only) 
  • 200GB free disk space 
  • Valid login to https://customerconnect.vmware.com  
  • Entitlement to VCF 4.5 Enterprise for 8 hosts minimum (16 hosts if planning to test Cloud Foundation Multi region with NSX Federation) 
  • License keys for the following VCF 4.5 components
    • VMware Cloud Foundation
    • VMware NSX-T Data Center Enterprise
    • VMware vSAN Enterprise 
    • VMware vSphere Enterprise Plus 
    • VMware vCenter Server (one license)
    • VMware vRealize Suite Advanced or Enterprise
    • Note: This product has been renamed VMware Aria Suite
  • External/Customer networks required
    • ESXi host management IP (one per host) 
    • Holo-Router address per pod

Ultimate Cross vCenter Script

Last year i attend the Dutch VMUG (NLVMUG) i followed session from

Michael Wilmsen that was: Migrate your datacenter without downtime.

I must also move al lot of VM’s from different datacenters to other datacenters.
I use the script from Michael Wilmsen to move the VM’s. But along the way I counter some problems with this script. So I begon tweaking and tweaking and tweaking this script to create for me the ultimate Cross vCenter PowerCLI Script.

Coolfeatures:
– Info through Whattsapp (Default not enabled)
– Dryrun (Test Run)
– Logging
– Selection through GUI
– Multiple Nic support maximum of 4.
– Datastore en Host selection based on Free space en Free Memory
– Check of Destination Host or Datastore in Maintance
– Destination Store exist in Destination Cluster

MoveVM.ps1:
#Filename: MoveVM.ps1
#Author: M. Wilmsen / W. Vissers
#Source: http://virtual-hike.com/nlvmug-2018/
#Version: 2.0
#Date: 21-10-2018
#ChangeLog:
# V0.9 – M. Wilmsen First Version
# V1.0 – Fixed Multiple Nics to maximium of 4 nics
#      – Logfile name VM name
# V1.1 – Destination Cluster not the first Host
# V1.2 – Selected Destination host based on memory used
# V1.3 – Fixed folder location and VirtualPortGroup
# V1.4 – Fixed Datastore in Maintance
# V1.5 – Using Get-VICredentialStoreItem + Logpath Fixt
# V1.6 – Fixed Log in Hours in 24 uurs
# V1.7 – Fixed Using DatastoreCluster name based on Cluster name!
# V1.8 – Check if Destination has the same datastore
#          – Ask know for input
#          – VM selection with VMhost
#          – Fixed Ping Check
# v1.9 – Added Destination Store exist in Destination Cluster
# v2.0 – Fixed Destination Store exist in Destination Cluster
<#
.SYNOPSIS
Script to migrate a virtual machine
.DESCRIPTION
Script to migrate compute and storage from cluster to cluster. Log will be in current dir [VM]-[-timestamp].log

.EXAMPLE
MoveVM.ps1
#>
################################## INIT #################################################
#Set WebOperation timeout
# set-PowerCLIConfiguration -WebOperationTimeoutSeconds 3600
#Define Global variables
$location = “D:\xmovewhattsapp”
$LogPath = “.\”
$DataStoreClusterPrefix = “SAN-“
$SourceVC = Read-Host “Give Source vCenter”
$DestinationVC = Read-Host “Give Destination vCenter”
$DRSRecommendation = $true
$Dryrun = $false
$SendWhatsApp = $false
$WhatsAppNumbers = “0123456789”
$WhatsAppGroup = “Namehireyourwhattsgroup”
$instanceId = “23” #chang this line
$clientId = “demo@demo.nl” #change this line
$clientSecret = “Puthiersecretid” #change this line
################################## PASSWORD STORE ##############################################
#Username
# Check if credentials exist in credential store if not ask for credentials and put them in credential store

If ((Get-VICredentialStoreItem).host -notcontains $SourceVC) {New-VICredentialStoreItem -Host $SourceVC -User $env:USERNAME -Password ((get-credential).GetNetworkCredential().Password)}
If ((Get-VICredentialStoreItem).host -notcontains $DestinationVC) {New-VICredentialStoreItem -Host $DestinationVC -User $env:USERNAME -Password ((get-credential).GetNetworkCredential().Password)}

# Remove-VICredentialStoreItem * -Confirm:$false

################################## END INIT #################################################
################################## FUNCTIONS #################################################
#Define log function
Function LogWrite
{
    Param ([string]$logstring)
    #Add logtime to entry
    $LogTime = Get-Date -Format “MM-dd-yyyy_HH-mm-ss”
    $logstring = $LogTime + ” : ” + $logstring
    #Write logstring
    Add-content $LogFile -value $logstring
    Write-Host $logstring
}
#Define SendWhatsApp function
Function SendWhatsApp
{
   Param ([string] $message)
  
   if ( $SendWhatsApp ) {
     $LogTime = Get-Date -Format “MM-dd-yyyy_hh-mm-ss”
     $message = $logtime + ” : ” + $message
    
     foreach ( $number in $WhatsAppNumbers )
     {
        $jsonObj = @{‘group_admin’=$number;
                     ‘group_name’=$WhatsAppGroup;
                     ‘message’=$message;}
       Try {
         $res = Invoke-WebRequest -Uri “http://api.whatsmate.net/v2/whatsapp/group/message/$instanceId” `
                           -Method Post   `
                           -Headers @{“X-WM-CLIENT-ID”=$clientId; “X-WM-CLIENT-SECRET”=$clientSecret;} `
                           -Body (ConvertTo-Json $jsonObj)
         LogWrite “WhatsMate Status Code: ”  $res.StatusCode
         LogWrite $res.Content
       }
       Catch {
         $result = $_.Exception.Response.GetResponseStream()
         $reader = New-Object System.IO.StreamReader($result)
         $reader.BaseStream.Position = 0
         $reader.DiscardBufferedData()
         $responseBody = $reader.ReadToEnd();

        Write-host “Status Code: ” $_.Exception.Response.StatusCode
         Write-host $message
         }
     }
   }
}

function Get-VmSize($vm)
{
     #Initialize variables
     $VmDirs =@()
     $VmSize = 0
     $searchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
     $searchSpec.details = New-Object VMware.Vim.FileQueryFlags
     $searchSpec.details.fileSize = $TRUE
     Get-View -VIObject $vm | % {
         #Create an array with the vm’s directories
         $VmDirs += $_.Config.Files.VmPathName.split(“/”)[0]
         $VmDirs += $_.Config.Files.SnapshotDirectory.split(“/”)[0]
         $VmDirs += $_.Config.Files.SuspendDirectory.split(“/”)[0]
         $VmDirs += $_.Config.Files.LogDirectory.split(“/”)[0]
         #Add directories of the vm’s virtual disk files
         foreach ($disk in $_.Layout.Disk) {
             foreach ($diskfile in $disk.diskfile){
                 $VmDirs += $diskfile.split(“/”)[0]
             }
         }
         #Only take unique array items
         $VmDirs = $VmDirs | Sort | Get-Unique
         foreach ($dir in $VmDirs){
             $ds = Get-Datastore ($dir.split(“[“)[1]).split(“]”)[0]
             $dsb = Get-View (($ds | get-view).Browser)
             $taskMoRef  = $dsb.SearchDatastoreSubFolders_Task($dir,$searchSpec)
             $task = Get-View $taskMoRef
             while($task.Info.State -eq “running” -or $task.Info.State -eq “queued”){$task = Get-View $taskMoRef }
             foreach ($result in $task.Info.Result){
                 foreach ($file in $result.File){
                     $VmSize += $file.FileSize
                 }
             }
         }
     }
     return $VmSize
}
################################## END FUNCTIONS #################################################
#Login to vCenter servers
if (($global:DefaultVIServers).Name -notcontains $SourceVC -or $DestinationVC) {

#SourceVC
$ConnectVC = Connect-VIServer $SourceVC
$Message = “Connecting to ” + $ConnectVC  + ” as ” + $env:USERNAME
#Logwrite $Message
#DestionationVC
$ConnectVC = Connect-VIServer $DestinationVC
$Message = “Connecting ” + $ConnectVC + ” as ” + $env:USERNAME
#Logwrite $Message

# Disconnect-VIServer * -Confirm:$false

}
Set-Location $location

$cluster=Get-Cluster -Server $SourceVC  | Out-GridView -OutputMode Single -Title “Select Source Cluster”
$vmtomigrate =Get-Cluster $cluster -Server $SourceVC | Get-VM | Out-GridView -OutputMode Single -Title “Select VM”
$DestinationCluster = Get-Cluster -Server $DestinationVC | Out-GridView -OutputMode Single -Title “Select Destination Cluster”
$vmfolder=Get-folder -Server $DestinationVC | Out-GridView -OutputMode Single -Title “Select Folder”

#Main Script

    #Set $MigError to false befor migration
     $MigError = $false
     #Get VM variables
     $vm = get-vm $vmtomigrate
    
     #Define LogFile with time stamp
     $LogTime = Get-Date -Format “MM-dd-yyyy_hh-mm-ss”
    
     if([IO.Directory]::Exists($LogPath))
     {
     #Do Nothing!!
     }
     else
     {
     New-Item -ItemType directory -Path $LogPath
     }
     $LogFile = $LogPath+$VM+”-“+$LogTime+”.log”
    
     # LogWrite Gebruiker
    
     Logwrite $env:USERNAME

    # Get-VM Info   
    
     $VMHDDSize = Get-VmSize($vm)
     $VMHDDSize = [Math]::Round(($VMHDDSize / 1GB),2)

    Logwrite “Start Virtual Machine Move”
     #If WhatsApp make notice
     if ( $SendWhatsApp ) { LogWrite “Notifications will be send using WhatsApp to WhatsApp Group: $WhatsAppGroup” }
     #If DryRun make Notice
     if ( $Dryrun ) {
     Logwrite “Start move virtual machines $vm Disksize $VMHDDSize GB (DryRun)”
     SendWhatsApp “Start move virtual machines $vm Disksize $VMHDDSize GB(DryRun)”
     }
     else {
     Logwrite “Start move virtual machines $vm Disksize $VMHDDSize GB”
     SendWhatsApp “Start move virtual machines $vm Disksize $VMHDDSize GB”
     }
     $SourceCluster = get-vm $vm | Get-Cluster | select name
     $vmip = $vm  | Select @{N=”IP Address”;E={@($_.guest.IPAddress[0])}}
     $vmip = $vmip.”ip address”
     $VMHDDSize = Get-VmSize($vm)
     $VMHDDSize = [Math]::Round(($VMHDDSize / 1GB),2)
     $NetworkAdapter = Get-NetworkAdapter -VM $vm -Server $SourceVC
     $SourceVMPortGroup = Get-NetworkAdapter -vm $vm | Select NetworkName
     $switchname = $DestinationCluster
    

     $Datastore = Get-VM $vm | Get-DataStore -Server $sourceVC | Select @{N=”Name”;E={@($_.Name)}}
     $Datastore = $Datastore.Name
     $DatastoreExistinOthervCenter = Get-Cluster $DestinationCluster | Get-DataStore -Server $DestinationVC | ? {$_.Name -like “*$Datastore*”}

     if ($DatastoreExistinOthervCenter )
      {
      LogWrite  “Datastore exsist $DestinationCluster in  destination vCenter $DestinationVC “
      $destinationDatastore = $DatastoreExistinOthervCenter }
      Else
      {
      LogWrite  “Datastore does not exsist in $DestinationCluster destination vCenter $DestinationVC”
      # Select DataStore with the most free space and not in maintance
      $DatastoreCluster = “$DataStoreClusterPrefix”+”$DestinationCluster”
      $destinationDatastore = Get-DatastoreCluster $DatastoreCluster | Get-Datastore | Where {$_.State -ne “Maintenance”} | Sort-Object -Property FreeSpaceGB -Descending | Select-Object -First 1
      }

     $destinationDatastoreFreeSpace = $destinationDatastore | Select Name,@{N=”FreeSpace”;E={$_.ExtensionData.Summary.FreeSpace}}
      $destinationDatastoreFreeSpace = [Math]::Round(($destinationDatastoreFreeSpace.”FreeSpace” / 1GB),2)

    # Select the host with the less used memory
   
     $DestinationHost = Get-Cluster –Name $DestinationCluster –Server $DestinationVC | Get-VMhost -State Connected | Sort-Object -Property MemoryUsageGB | Select-Object -First 1
            
     # Change Here if you have a vm with multiple Network Cards (Remove the # for the multiple nics)
    
     if ($NetworkAdapter.Count-eq 1) {
         $DestinationVMPortgroup =@()
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic1”
      }
     elseif ($NetworkAdapter.Count-eq 2) {
         $DestinationVMPortgroup =@()
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic1”
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic2”
     }
     elseif ($NetworkAdapter.Count-eq 3) {
         $DestinationVMPortgroup =@()
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic1”
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic2”
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic3”
     }
     elseif ($NetworkAdapter.Count-eq 4) {
         $DestinationVMPortgroup =@()
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic1”
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic2”
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic3”
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic4”
     }

    LogWrite “Start move: $vm”
     Logwrite “VM IP: $vmip”
     Logwrite “VM Disk Used (GB): $VMHDDSize”
     Logwrite “VM Folder: $vmfolder”
     Logwrite “Source vCenter: $SourceVC”
     Logwrite “VM Source Cluster: $SourceCluster”
     Logwrite “Destination vCenter: $DestinationVC”
     Logwrite “VM Destination Cluster: $DestinationCluster”
     Logwrite “Destination host: $DestinationHost”
     LogWrite “VM Source PortGroup: $SourceVMPortGroup”
     LogWrite “VM Destination Portgroup: $DestinationVMPortgroup”
     Logwrite “VM Destination Datastore: $destinationDatastore”
     LogWrite “Destination Datastore FreeSpace GB: $destinationDatastoreFreeSpace “
     if ( $Dryrun ) {
       $FreespaceAfterMigration = $destinationDatastoreFreeSpace – $VMHDDSize
       if ( $FreespaceAfterMigration -lt 0 ) { Logwrite “ERROR: Datastore $destinationDatastore does not have sufficient freespace! Virtual Machine needs $VMHDDSize. Only $destinationDatastoreFreeSpace available.” }
       else { Logwrite “Virtual Machine will fit on datastore $destinationDatastore. Freespace after migration is: $FreespaceAfterMigration GB” }
     }
    #Test if VM responsed to ping
    if ($vmip -eq $null) {
     LogWrite “Virtual Machine ip address not known”
     Logwrite “No ping check will be performed after moving the Virtual Machine”
     }
    else {
         Test-Connection -comp $vmip -quiet
         LogWrite “Virtual Machine $vm response to ping before being moved. Virtual machine will be checked after being moved”
         $PingVM = $true
     }
      
     #if ( $VMHDDSize -eq
     if ( -NOT $Dryrun) {
       #Migrate VM to cluster
       LogWrite “Move $vm to vCenter $DestinationVC and datastore $DestinationDatastore”
       Try {
         $Result = Move-VM -VM $vm `
                            -Destination $DestinationHost `
                            -Datastore $DestinationDatastore `
                            -NetworkAdapter $NetworkAdapter `
                            -PortGroup $DestinationVMPortgroup `
                            -ErrorAction Stop
           }
       Catch {
         $ErrorMessage = $_.Exception.Message
         LogWrite “ERROR: Move of $vm to cluster $DestinationHost failed!!!”
         Logwrite “ERROR: Move Status Code:  $ErrorMessage”
         SendWhatsApp “ERROR: Move of $vm failed!!! $ErrorMessage”
         $MigError = $true   
       }
       #Migrate VM to folder
       LogWrite “Move $vm to vCenter $vmfolder”
       Try {
         $VMtemp = get-vm $vm
         $Result = Move-VM -VM $vmtemp -InventoryLocation $vmfolder -ErrorAction Stop
           }
       Catch {
         $ErrorMessage = $_.Exception.Message
         LogWrite “ERROR: Move of $vm to folder $vmfolder failed!!!”
         Logwrite “ERROR: Move Status Code:  $ErrorMessage”
         SendWhatsApp “ERROR: Move of $vm failed!!! $ErrorMessage”
         $MigError = $true   
         }
       }
    
     $MigError = $false
     #Test if VM is running on destination cluster
     if ( -NOT $MigError -AND -NOT $Dryrun ) {
       LogWrite “Check $vm is registered in $DestinationVC”
       try {
         $CheckVM = get-vm -name $vm -server $DestinationVC -ErrorAction Stop
 
         if ( $CheckVM ) {
           Logwrite “$vm registered in $DestinationVC”
         }
         else {
           Logwrite “ERROR: $vm not found in $DestinationVC”
         }
       }
       catch {
         $ErrorMessage = $_.Exception.Message
         Logwrite “ERROR: $vm not found in $DestinationVC”
         Logwrite “ERROR: $ErrorMessage”
         SendWhatsApp “ERROR move: $vm not found in $DestinationVC”
       }
     }
     #Test is VM response to ping, if $PingVM = $True
     if ($PingVM) {
       if (Test-Connection -comp $vmip -quiet) {
         LogWrite “Virtual Machine $vm response to ping after move”
         SendWhatsApp “Virtual Machine $vm response to ping after move”
       } 
     }
     sleep 1
     SendWhatsApp “Finished move action: $vm from $SourceVC to $DestinationVC”
     Logwrite “Finished move action: $vm from $SourceVC to $DestinationVC”

if ($DRSRecommendation)
  {
   Get-DrsRecommendation -Cluster $DestinationCluster -Server $DestinationVC | Apply-DrsRecommendation
   Logwrite “DRS Recommendatation applyed”
  }
Else
  {
  Logwrite “No DRS Recommendatation applyed”
  Write-Host “No DRS Recommendatation applyed”
  }  
 

#Disconnect from vCenter servers
Logwrite “Disconnect from vCenter servers $SourceVC $DestinationVC”
Disconnect-viserver $SourceVC -Confirm:$false
Disconnect-viserver $DestinationVC -Confirm:$false
Logwrite “Finished moving virtual machines, exiting…..”
SendWhatsApp “Finished moving virtual machines, exiting…..”

VMware vSphere PowerCLI 11.0

VMware vSphere PowerCLI 11.0 New Features

New features available on  VMware vSphere PowerCLI 11.0 is to support the new all updates and release of VMware products , find the below following has been features,

  • New Security module
  • vSphere 6.7 Update 1
  • NSX-T 2.3
  • Horizon View 7.6
  • vCloud Director 9.5
  • Host Profiles – new cmdlets for interacting with
  • New Storage Module updates
  • NSX-T in VMware Cloud on AWS
  • Cloud module multiplatform support
  • Get-ErrorReport cmdlet has been updated
  • PCloud module has been removed
  • HA module has been removed

Now we will go through above mentioned new features to find what functionality it bring to PowerCLI 11.0

What is PowerCLI 11.0 New Security Module

The new security module brings more powerful automation features to PowerCLI 11.0 available  new cmdlets include the following

  • Get-SecurityInfo
  • Get-VTpm
  • Get-VTpmCertificate
  • Get-VTpmCSR
  • New-VTpm
  • Remove-VTpm
  • Set-VTpm
  • Unlock-VM

Also New-VM cmdlet has enhanced functionality with the security module functionality and it includes parameters like KmsCluster, StoragePolicy, SkipHardDisks etc which can be used while creating new virtual machines with PowerCLI .In addition to that  Set-VM, Set-VMHost, Set-HardDisk, and New-HardDisk cmdlets are added.

Host Profile Additions

There are few additions to the VMware.VimAutomation.Core module that will make managing host profiles from PowerCLI

  • Get-VMHostProfileUserConfiguration
  • Set-VMHostProfileUserConfiguration
  • Get-VMHostProfileStorageDeviceConfiguration
  • Set-VMHostProfileStorageDeviceConfiguration
  • Get-VMHostProfileImageCacheConfiguration
  • Set-VMHostProfileImageCacheConfiguration
  • Get-VMHostProfileVmPortGroupConfiguration
  • Set-VMHostProfileVmPortGroupConfiguration

Storage Module Updates

These new Storage Module updates specifically for VMware vSAN , the updates has predefined time ranges when using Get-VsanStat. In addition  Get-VsanDisk has additional new properites that are returned including capacity, used percentage, and reserved percentage. Following are the  cmdlets have been added to automate vSAN

  • Get-VsanObject
  • Get-VsanComponent
  • Get-VsanEvacuationPlan – provides information regarding bringing a host into maintenance mode and the impact of the operation on the data, movement, etc

Additionally  following modules have been removed

  • PCloud module
  • HA module

Download now and start using

Update-module VMware.Powercli

Useful Links

HPE Oneview Powershell Clear Alerts

You need: https://github.com/HewlettPackard/POSH-HPOneView/wiki

################################################################
#
#Naam:              Oneview Clear Alarms
#Version:           0.1
#Author:            Ward Vissers
################################################################

 

# Adding PowerCLI core snapin, also check if powerCLI module is alsready added

if (!(get-module -name HPOneView.400 -erroraction silentlycontinue)) {
import-module HPOneView.400 | out-null
}

 

$oneviewserver = “oneview.wardvissers.nl”
Connect-HPOVMgmt -Hostname $oneviewserver
Get-HPOVAlert | Set-HPOVAlert -Cleared
Get-HPOVAlert -State Active | Set-HPOVAlert -Cleared

PowerCLI Move All VM’s to other Host

################### Config ##################################

$SourceVC = “vcenter.wardvissers.nl

################## PASSWORD STORE #########################

#Username

# Check if credentials exist in credential store if not ask for credentials and put them in credential store

 

If ((Get-VICredentialStoreItem).host -notcontains $SourceVC) {New-VICredentialStoreItem -Host $SourceVC -User $env:USERNAME -Password ((get-credential).GetNetworkCredential().Password)}

 

# Remove-VICredentialStoreItem * -Confirm:$false

 

#################### END INIT ####################################

 

#Login to vCenter servers

if (($global:DefaultVIServers).Name -notcontains $SourceVC) {

 

#SourceVC

$ConnectVC = Connect-VIServer $SourceVC

 

# Get-Cluster –Name $DestinationCluster –Server $DestinationVC | Get-VMhost -State Connected | Sort-Object -Property MemoryUsageGB | Select-Object -First 1

 

$ESXiHostSrc = “esx01.wardvissers.nl”

$ESXiHostDst = “esx02.wardvissers.nl”

$vmList = Get-VMHost $ESXiHostSrc | Get-VM

$vmList | move-vm -destination (get-vmhost $ESXiHostDst)

}

PowerCLI move Multiple VM’s to a VM Folder

$DestinationVC = “vcenter.wardvissers.nl”

Connect-VIServer $DestinationVC

#Optie 1

$vmfolder = “Applicatie Servers”

$tempvms = Get-VM | where {$_.Folder -match ‘vm’}

foreach ($tempvm in $tempvms){

$DestinationHost = Get-VM $tempvm | Get-VMhost

Move-VM -VM $tempvm -InventoryLocation $vmfolder -Destination $DestinationHost -ErrorAction Stop

}

#Optie 2

# Get-VM | where {$_.Folder -match ‘vm’} | Move-VM -InventoryLocation “Diverse Applicatie Servers”

Deploy Multi VM’s based on Windows Template

I love powershell. I created a little script to deploy multi VM based on a Windows Template throug CSV file.

It’s create a computer account at the specfified ou. He greates also a Domain Local Group for management. (It used in the customization not specified here)

TempVMlist.csv

server,cpu,memory,DestinationCluster,OSCustomizationSpec,VMtemplate,adgroup

WARDTEST01,2,8,CLUSTER01,W2012R2_Demo,TPL_W2012R2_STD,ServerAdmin

MultiVM.ps1

#Filename: MultiVM.ps1

#Author: W. Vissers

#Source:

#Version: 1.1

#Date: 08-05-2018

#ChangeLog:

# V1.0 – Module Active Directory

#      – Module VMware PowerCli

#      – Active Directory Computer Account, Group

#      – Host Selected from Cluster with Least Memory

#      – Storage selection based on volume with most free space

# V1.1 – Added Harddisk 1&2

#      – Changed porte group other vlan

#

<#

.SYNOPSIS

Script to create a virtual machine from template

.DESCRIPTION

Script to create a virtual machine from template

.EXAMPLE

MultiVM.ps1

#>

################################## INIT #################################################

# LoadModule Active Directory

if (!(Get-Module “activedirectory”)) {Import-module activedirectory}

Else {Write-Host “Module Active Directory is al ready loaded”}

# LoadModule VMware PowerCLI

# if (!(Get-Module “VMware.PowerCLI”)) {

#    Find-Module VMware.PowerCLI

#    Install-Module -Name VMware.PowerCLI -Scope CurrentUser

#}

#Else

# {

# Write-Host “Module PowerCLI is al ready loaded”

# }

#Config

$ouservers=”OU=Servers,DC=wardvissers.nl,DC=nl”

$ougroup=”OU=GroepObjecten,DC=wardvissers,DC=nl”

$folder=”Applicatie Servers”

$DestinationVC =”vcenter01.wardvissers.nl

#Username

if (!$username ) { $username = Read-Host “Give vCenter username ‘wardvissers\admin'”}

#Password

if ( -NOT $Password ) {

$PasswordSec = Read-Host “Give vCenter password” -AsSecureString

$Password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($PasswordSec))

}

#Connect vCenter

$ConnectVC = Connect-VIServer $DestinationVC -Username $Username -Password $Password -AllLinked

$AllVMs = @()

$AllVMs = Import-Csv “D:\TempVMlist.csv”

foreach ($vm in $AllVMs) {

#Haal De Gegevens op

$server=$($vm.server)

$memory=$($vm.memory)

$cpu=$($vm.cpu)

$DestinationCluster=$($vm.DestinationCluster)

$OSSpec=”$($vm.OSCustomizationSpec)”

$VMtemplate=$($vm.VMtemplate)

$group=$($vm.adgroup)

$harddisk1=$($vm.harddisk1)

$harddisk2=$($vm.harddisk2)

Write-Host “$server heeft $memory GB memory en $cpu cpu(‘s)”

if ($server.length -gt 15) {

Write-Output “Hostname cannot contain more than 15 characters.”

$server = Read-Host “Re-enter hostname for host $server”}

Else

{

Write-Host “Server is umc server”

#Maak AD Groep aan en Computer Account

New-ADComputer -Name $server -Path $ouservers -Enabled $true

New-ADGroup -Name “DLG.$server” -SamAccountName “DLG.$server” -GroupCategory Security -GroupScope DomainLocal -DisplayName “DLG.$server” -Path $ougroup

Add-ADGroupMember -Identity “DLG.$server” -Members $group

}

# Rol server uit van Template

# Select the host with the less used memory

$DestinationHost = Get-Cluster –Name $DestinationCluster –Server $DestinationVC | Get-VMhost -State Connected | Sort-Object -Property MemoryUsageGB | Select-Object -First1

# Select DataStore with the most free space and not in maintance

$destinationDatastore = Get-Cluster $DestinationCluster | Get-Datastore | Where {$_.State -ne “Maintenance”} | Sort-Object -Property FreeSpaceGB -Descending | Select-Object -First 1

# Finally, I deploy my VM with the New-VM cmdlet using my template and OS specs. I place the VM on the ESXi host and store the VM on the datastore.

New-VM -Name $server -Template $VMTemplate -OSCustomizationSpec $OSSpec -VMHost $DestinationHOST -Datastore $DestinationDatastore -Location $folder

Get-VM $server | Set-VM -NumCpu $cpu -MemoryGB $memory -Confirm:$false

if ($harddisk1 -gt 60){Get-HardDisk -vm $server | Where {$_.Name -eq “Hard disk 1”} | Set-HardDisk -CapacityGB $harddisk1 -Confirm:$false}

if ($harddisk2 -gt 20) {Get-HardDisk -vm $server | Where {$_.Name -eq “Hard disk 2”} | Set-HardDisk -CapacityGB $harddisk2 -Confirm:$false}

Get-VM $server | Start-VM -Confirm:$false

Get-VM $Server | Get-NetworkAdapter | Set-NetworkAdapter -Connected $true -Confirm:$false

}

VMware PowerCLI 10.0.0

The release of VMware PowerCLI 10.0.0 was another big one for us. As a result, PowerCLI is now available on Linux, MacOS, and Windows! As part of every major release, there’s a large number of asks for the PowerCLI poster and today we’re releasing it!

The poster features a bit of a layout refresh which conforms to a more standardized poster sizing guideline, but still features all of our cmdlets, some basic examples, and links to helpful resources.

PowerCLI Poster

New Release: PowerCLI Poster

RVtools 3.10 Released

Version 3.10 (February, 2018)
– Upgraded RVTools solution to Visual Studio 2017
– Upgraded RVTools to .Net Framework version 4.6.1
– Upgraded Log4net to version 2.0.8, Waffle.AD to version 1.8.3
and NPOI to version 2.3.0
– Connection error when TLSv1.0 and TLSv1.1 are disabled and only TLSv1.2 is
enabled is solved by using .Net Framework 4.6.1
– vInfo tab page new columns: The latency-sensitivity setting of the virtual
machine, Change Block Tracking (CBT) and disk.EnableUUID values
– vDisk tab page new columns: SCSI label, unit number and sharedBus
– vHost tab page new columns: Assigned License(s), ATS heartbeat, ATS locking
values. 0 = disabled 1 = enabled, Host Power Policy shortname, CPU Power
Management current policy and CPU power hardware support
– When Export to xlsx is executed a metadata worksheet with version number of
RVTools and date time stamp is added to the output xlsx file
– All columns in the RVTools export xlsx file(s) now have a filter
– When export to csv newline characters are replaced by spaces
– When started from cli and login fails an error message and login box was
displayed. Now RVTools will exit with exit code -1, without showing the error
message and login form.
– Added an example PowerShell script with which you can merge RVTools export
xlsx files
– Added a example PowerShell script to start Export all to xlsx for multiple vCenters
– vDatastore tab page: For NFS datastores the address column is now filled with
remote host and path info
– vDatastore tab page new columns: Datastore Cluster Name, Cluster capacity and
Cluster free space
– The upper limit on the Health check for number of VMs on a datastore is now
9999
– vHealth tab page: new column “message type” which can be used as a filter in
Excel
– vHealth tab page: hbrdisk.RDID files are no longer reported as possible zombie
files
– vHealth tab page: low disk space messages no also show the free space in MB.
– All tab pages: Refresh or auto-refresh will respect your sort order
– CLI export2xls parameters changed to export2xlsx (old parameter will still work)
– Bug Fix: invalid “Horizontal Alignment” value in xlsx style sheet.
– Bug Fix: Calculation of total snapshot size was not always correct
– Bug Fix: Child snapshot hierarchy was not always correct
– Default installation directory is changed to C:\Program Files
(x86)\RobWare\RVTools without the version number

Documentation

Download

Translate »