Checking for VM Snapshots in vCenter using Powershell

A small script to output snapshots per VM.

Connect-VIServer myserver.fqdn.com
Write "#####START#####"
$vms = $null
$vms = Get-VM
foreach ($vm in $vms) {
$snapshots =  Get-Snapshot -VM $vm
$i = 1
foreach ($snapshot in $snapshots) {
$i = $i + 1
if ($i -ge 2) {
$vm.name
$i
#$snapshot.Name
#$snapshotTable =  @($vm.Name) # | Sort-Object {$_.name}
#$snapshotTable
}
}
}
Write "#####DONE######"

You can also list snapshots based on a name containing any value using the following code:

Get-VM | Get-Snapshot | Where-Object {$_. -contains "searchString"}

Checking partition alignment in vCenter using Powershell

A quick PowerCLI and Powershell script to check the partition alignment of Windows guests in a specific VM cluster under VMWare.

More information in the importance of partition alignment on hosts using storage arrays can be found at the following links:

NetApp – Best Practices for File System Alignment in Virtual Environments
Aligning your VMs virtual hard disks
Current Status, An Update, and a Look to the Future of Alignment

Good luck!

Connect-VIServer  myserver.fqdn.com
$Cluster = (Read-Host "Enter cluster name")

$myCol = @()
$vms = Get-Cluster $Cluster | get-vm | where {$_.PowerState -eq "PoweredOn" -and `
$_.Guest.OSFullName -match "Microsoft Windows*" } | Sort Name 

foreach($vm in $vms){
try {
$wmi = get-wmiobject -class "Win32_DiskPartition" `
-namespace "root\CIMV2" -ComputerName $vm            
	foreach ($objItem in $wmi){
        $Details = "" | Select-Object VMName, Partition, StartingOffset ,Status
		if ($objItem.StartingOffset) {
		$Details.StartingOffset = $objItem.StartingOffset
		$objItem.StartingOffset = $objItem.StartingOffset / 4096
#				Write $objItem.StartingOffset.gettype().name
            if ($objItem.StartingOffset.gettype().name -eq "UInt64"){
                $Details.VMName = $objItem.SystemName
                   $Details.Partition = $objItem.Name
                $Details.Status = "Partition aligned"
            }
            else{
                $Details.VMName = $objItem.SystemName
                   $Details.Partition = $objItem.Name
                $Details.Status = "Partition NOT aligned"
            }
    $myCol += $Details
    }
	}
}
catch {
Write "Error... "; $Error[0]
}
$myCol 
}

How to add datastores to single host in vCenter using Powershell

Connect-VIServer myserver.fqdn.com 
$VMHost = (Read-Host "Please enter the name of your the ESX Host you wish to configure")

$shellObject = new-object -comobject wscript.shell 
$intAnswer = $shellObject.popup("Do you want to add the datastores?", 0,"Add datastores - remember you must have added the hosts on the storage",4) 
If ($intAnswer -eq 6) {
Write "Creating Datastores on $VMHost…" 
New-Datastore -Nfs -VMHost $VMHost -Name datastorename -Path /vol/volname -NfsHost 10.10.10.10
New-Datastore -Nfs -VMHost $VMHost -Name datastorename -Path /vol/volname -NfsHost 10.10.10.10
} else {
Write "Skipping Datastores on $VMHost…" 
} 

List all VMs with a memory limit set in vCenter using Powershell

This script lists all VMs with a memory limit set in Resource Manger in a given VMWare cluster.

Connect-VIServer myserver.fqdn.com 
Get-Cluster $Cluster | Get-VM | Get-VMResourceConfiguration | where {$_.MemLimitMB -ne "-1"}

If you want to clear all memory limits and set them to unlimited use the following code

Connect-VIServer myserver.fqdn.com 
Get-Cluster MyCluster | Get-VM | Get-VMResourceConfiguration | where {$_.MemLimitMB -ne "-1"} | Set-VMResourceConfiguration -MemLimitMB $null

The same can also be done for the CPU management using CpuLimitMhz attribute.

Repurposed PCs and Citrix Desktop Appliance

Citrix Desktop Appliance is a great hidden secret of Web Interface and can easily be used as an alternate approach to a thin client deployment.

The Desktop Appliance is a cut down version of a standard Web Interface site. Once logged on the site takes the user directly to their desktop, this can be a XenApp published desktop and XenDesktop VDA. When installing the Web Interface component to the XenDesktop Delivery Controller the Desktop Appliance site is automatically created.

To deploy the site to an existing instance of the Web Interface I followed this blog.

Create a Desktop Appliance Web Interface Site
The appliance mode site is actually an additional website that gets hosted alongside the standard Web Interface site. The appliance site is created by default when deploying Web Interface for XenDesktop and can be easily added for XenApp. Creating an appliance mode site will not have any impact on existing web interface sites (unless you overlap the URLs).

There is no option for creating or configuring an appliance mode site in the current version of the Citrix Web Interface Management Console. No worries, it’s very simple to do using the Citrix sitemgr tool and a good opportunity to get down and dirty with your web interface site config.

Creating the appliance site:

■Navigate to: c:\Program Files (x86)\Citrix\Web Interface\5.3.0.
■Run command:
sitemgr -c DACDest=1:/Citrix/DesktopAppliance,XMLService=XAServer:XmlSvcPort
■Confirm the site was created by accessing it at the newly created URL or by checking for the deployment of site files at c:\inetpub\wwwroot\citrix\DesktopAppliance.
Configuring a single domain login:
If all users accessing the appliance site will authenticate using the same domain, the domain field can be hidden to simplify and clean up the login.

■Edit the file “c:\inetpub\wwwroot\citrix\DesktopAppliance\conf\webinterface.conf” as follows:
■Uncomment “DomainSelection” and set it to “”
■Uncomment “HideDomainField” and verify it is set to “On”
■Uncomment “LoginDomains” and set it to “”
■Uncomment “RestrictDomains” and verify it is set to “On”

To specify multiple XML servers you can use a semi-colon ; to separate the server entry’s.

How does this work with multiple desktops?
Well it’s quite simple the site connects the user directly to the first desktop in alphabetical order.

But I have multiple desktops and want to prioritise the desktop order?
Fear not, this can be achieved by editing the published desktop name.
desktop.jpg
Note: Not the display name that users see.

The next step of this and my real aim was to repurpose fat (old) PCs as thin clients. This approach saves on the upfront costs associated with a typical thin client rollout and additionally you get to take advantage of great HDX features such a HDX Media Stream or HDX Rich Graphics with RemoteFX. So I wanted a quick low touch approach that didn’t involve spending money, this somewhat limited the options and this is what I came up with.

A simple VB script combining a few different techniques. The things I wanted to consider:

  • Users should only logon once
  • The environment must be relatively locked down
  • The user experience should be seamless

So I combined a few scripts from around the web (Sources below) to come up with this:

'' Repurpose PC

''Create local user
strComputer = "localhost"
Set colAccounts = GetObject("WinNT://" & strComputer & "")
Set objUser = colAccounts.Create("user","Citrix")
objUser.SetPassword "MyPassword"
objUser.SetInfo

''
'Declarations'
''
Dim objShell
Dim RegLocAutoLogon
Dim keyDefaultDomainName
Dim valDefaultDomainName
Dim keyDefaultUserName
Dim valDefaultUserName
Dim keyDisableCAD
Dim valDisableCAD
Dim keyAutoAdminLogon
Dim valAutoAdminLogon
Dim keyForceAutoLogon
Dim valForceAutoLogon
Dim keyDefaultPassword
Dim valDefaultPassword
'''
'Define keys and values'
'''
RegLocAutoLogon = "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\"
keyDefaultDomainName = "DefaultDomainName"
valDefaultDomainName = ""
keyDefaultUserName = "DefaultUserName"
valDefaultUserName = "Citrix"
keyDisableCAD = "DisableCAD"
valDisableCAD = 1
keyAutoAdminLogon = "AutoAdminLogon"
valAutoAdminLogon = "1"
keyForceAutoLogon = "ForceAutoLogon"
valForceAutoLogon = "1"
keyDefaultPassword = "DefaultPassword"
valDefaultPassword = "MyPassword"
keyShell = "Shell"
keyShellValue = """C:\Program Files\Internet Explorer\iexplore.exe"" -k http://myhost.mydomain.com/citrix/desktopappliance"
Set objShell = CreateObject("WScript.Shell")

''Begin setting the autologon registry keys
objShell.RegWrite RegLocAutoLogon & keyDefaultDomainName, 1, "REG_SZ"
objShell.RegWrite RegLocAutoLogon & keyDefaultDomainName, valDefaultDomainName, "REG_SZ"
objShell.RegWrite RegLocAutoLogon & keyDefaultUserName, 1, "REG_SZ"
objShell.RegWrite RegLocAutoLogon & keyDefaultUserName, valDefaultUserName, "REG_SZ"
objShell.RegWrite RegLocAutoLogon & keyDisableCAD, 1, "REG_DWORD"
objShell.RegWrite RegLocAutoLogon & keyDisableCAD, valDisableCAD, "REG_DWORD"
objShell.RegWrite RegLocAutoLogon & keyAutoAdminLogon, 1, "REG_SZ"
objShell.RegWrite RegLocAutoLogon & keyAutoAdminLogon, valAutoAdminLogon, "REG_SZ"
objShell.RegWrite RegLocAutoLogon & keyForceAutoLogon, 1, "REG_SZ"
objShell.RegWrite RegLocAutoLogon & keyForceAutoLogon, valForceAutoLogon, "REG_SZ"
objShell.RegWrite RegLocAutoLogon & keyDefaultPassword, 1, "REG_SZ"
objShell.RegWrite RegLocAutoLogon & keyDefaultPassword, valDefaultPassword, "REG_SZ"

''Set the machine shell to be the desktop appliance
objShell.RegWrite RegLocAutoLogon & keyShell , keyShellValue , "REG_SZ"

''Give feedback to the admin
WScript.Echo "Done PC converted"

This code in a nut shell creates a local user, sets up auto logon for Windows using the newly created local user and then sets the Windows default shell to be an Internet Explorer kiosk mode window.
Things to keep in mind:

  • Admins have to hold shift before the logon process starts to override the auto logon
  • Admins have to run task manager to start explorer.exe as the shell in this example
  • Task manager is still available to users. This could be locked down by local machine policy, group policy or a product such as AppSense
  • The machine is still running Windows and as a result would still need to be patched and manage although hardening the install maybe appropriate

Despite some of the draw backs I still firmly believe this approach is a great on ramp to thin client deployment leveraging some of the HDX and web interface components within the Citrix product suite that often go unused.

Sources:

Citrix Blogs
Microsoft MSDN
Microsoft Technet
Tek-tips forum

Bulk add a VMNetwork to a ESX Cluster

A quick powershell script to add a new VM Network to an existing ESX Cluster.

Connect-VIServer vsphere.example.com 
$Cluster = (Read-Host "Enter cluster name")
$vSwitch = (Read-Host "Enter vSwitch to add the port group to")
$PortGroup = (Read-Host "Enter vmNetwork name")
$vLANPortGroup = (Read-Host "Enter vmNetwork vLAN number")
Get-Cluster $Cluster | Get-VMHost -State "Connected" | Get-VirtualSwitch -Name $vSwitch | New-VirtualPortGroup -Name $PortGroup -VLanId $vLANPortGroup