PowerCLI: RE: Disallowing Multiple VM Console Sessions


Frank Denneman posted today about disallowing multiple VM console session in a high-secure virtual infrastructure design: http://frankdenneman.nl/2010/11/disallowing-multiple-vm-console-sessions

The first thing popped up in my mind was why not automate this setting with PowerCLI. So I created a function called Set-MaxMKSConnections:

Function Set-MaxMKSConnections{
param(
    [parameter(Mandatory = $true)]
    [string[]]$vmName,
    $Sessions
)
    $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec

       $extra = New-Object VMware.Vim.optionvalue
    $extra.Key="RemoteDisplay.maxConnections"
    $extra.Value="$Sessions"
    $vmConfigSpec.extraconfig += $extra

        $vm = Get-VM $vmName | Get-View
        $vm.ReconfigVM($vmConfigSpec)
}

You can run this function by copying the code into the PowerCLI window. To run it on a single VM, you can use the following line:

Set-MaxMKSConnections -vmName Thinapp -Sessions 1

To run it on all your VM’s, you can use the following foreach loop:

$vms = Get-VM
foreach($vm in $vms){
    Set-MaxMKSConnections -vmName $vm -Sessions 1
}

The configuration is changed even on Virtual Machines that are powered on (you need to restart the VM to activate the new setting):

image

If you want to raise the maxConnections value back to 2 or another value, you can change the –Sessions parameter with the correct value and run the script again.

Reconfigure DNS settings and add vSphere hosts to Windows DNS


I needed to change the DNS setup in our vSphere environment. Instead of doing this by hand on every host I decided to create a script. First I needed a script to add the A and PTR records to the Windows DNS servers. I remembered a post by the scripting guys so I took their function and added it to my script. The final step is to change de vSphere host DNS configuration. This one is easy with PowerCLI and a simle for loop.

Warning! If you are using vSphere 4.1 and the vSphere hosts are joined to a Windows domain. You are not able to change the DNS settings!

From the Hey Scripting Guy post I quote the following about the new-dnsrecord function:

I’ve written various scripts in the past to work with individual record types, and I’ve found that each class has slightly different syntax and requirements. This makes life awkward when you want to start automating this process, because you have to have a different script or function for each record type. I decided I wanted a universal script for creating records so that I could create multiple records at the same time from minimal information. The following script shows the function that I came up with to create A, PTR, MX, and CNAME records—these being the most common ones I have to deal with. We will be using the MicrosoftDNS_ResourceRecord class with varying inputs.

I have combined the new-dnsrecord function with some PowerCLI code to accomplish my goal of migrating the DNS settings of all the vSphere hosts and to add all the hosts to the DNS servers. I did this task by running the following script:

Continue reading “Reconfigure DNS settings and add vSphere hosts to Windows DNS”

PowerCLI: Changing Advanced Configuration Settings for NFS


 go2.wordpress[1]  image_thumb[1] 

After reading Jase’s post http://www.jasemccarty.com/blog/?p=532 about setting the advanced configuration settings. I wanted to create a script and add it to the Community Powerpack (more info about the Powerpack here: http://www.virtu-al.net/2010/06/04/goodbye-virtu-al-hello-community/)

So I created two PowerCLI scripts to achieve this. You can see a short demo here:

 

This script will be added to the new version of the Powerpack.If you don’t want to wait until  the new version of the Community Powerpack comes online, you can use the following script to set the advanced settings on all of your ESX hosts:

param(
    [parameter(Mandatory = $true)]
    [string[]]$vCenter
)

Connect-VIServer $vCenter

$esxHosts = Get-VMHost | Sort Name
foreach($esx in $esxHosts){
    Write-Host "Updating TCP and NFS Advanced Configuration Settings on $esx"

    # Update TCP Settings
    if((Get-VMHostAdvancedConfiguration -VMHost $esx -Name Net.TcpipHeapSize).Values -ne "30"){
        Set-VMHostAdvancedConfiguration -VMHost $esx -Name Net.TcpipHeapSize -Value 30 -Confirm:$false
    }
    if((Get-VMHostAdvancedConfiguration -VMHost $esx -Name Net.TcpipHeapMax).Values -ne "120"){
        Set-VMHostAdvancedConfiguration -VMHost $esx -Name Net.TcpipHeapMax -Value 120 -Confirm:$false
    }

    # Update NFS Settings
    if((Get-VMHostAdvancedConfiguration -VMHost $esx -Name NFS.HeartbeatMaxFailures).Values -ne "10"){
        Set-VMHostAdvancedConfiguration -VMHost $esx -Name NFS.HeartbeatMaxFailures -Value 10 -Confirm:$false
    }
    if((Get-VMHostAdvancedConfiguration -VMHost $esx -Name NFS.HeartbeatFrequency).Values -ne "12"){
        Set-VMHostAdvancedConfiguration -VMHost $esx -Name NFS.HeartbeatFrequency -Value 12 -Confirm:$false
    }
    if((Get-VMHostAdvancedConfiguration -VMHost $esx -Name NFS.HeartbeatTimeout).Values -ne "5"){
        Set-VMHostAdvancedConfiguration -VMHost $esx -Name NFS.HeartbeatTimeout -Value 5 -Confirm:$false
    }
    if((Get-VMHostAdvancedConfiguration -VMHost $esx -Name NFS.MaxVolumes).Values -ne "64"){
        Set-VMHostAdvancedConfiguration -VMHost $esx -Name NFS.MaxVolumes -Value 64 -Confirm:$false
    }
}

 

You can start the script with the parameter –vCenter in my case this is vc01:

image

The script will generate the following output.

image

Note on the first ESX host I already changed the NFS.HeartbeatFrequency during the test of the cmdlets.

PowerCLI: Script to Schedule Memory and or vCPU up/downgrade


After creating the Restart-VMs.ps1 script, I also created a script to schedule vHardware changes. With this script, you’re able to upgrade or downgrade the amount of memory and or the amount of vCPU’s of a VM. Just lik the restart script, you can schedule this script and change the recommended parameters.

These are the parameters you need to supply to the script. The first two parameters are mandatory. When you supply all the parameters, you are able to add/remove Memory and add/remove vCPU’s.

-vCenter enter the vCenter server you want to connect to. It’s possible to connect to multiple vCenter servers.
-vmName enter the name of the VM you want
-MemoryMB enter the amount of memory you want to add or remove from the VM. Be sure you enter the amount in MB.
-MemoryOption Supply the option add or remove.
-CPUCount Enter the amount of vCPU’s you want to add or remove from the VM.
-CPUOption Supply the option add or remove.

This is how the script works.

  1. Connect to vCenter
  2. Shutdown the selected VM
  3. Add/remove memory and or vCPU’s
  4. Poweron the selected VM
  5. Disconnect vCenter

Now it’s time for an example. I have a VM called NAGIOS and needed to remove 512MB RAM and needed to add an extra vCPU. So I started the script with the following parameters:

.\Change-VM_Memory_CPU_Count.ps1 -vCenter vc01.ict-freak.local -vmName NAGIOS -MemoryMB 512 -MemoryOption Remove -CPUCount 1 -CPUOption Add

The VM is powered off and the memory is downgraded to 1024MB RAM and the total number of vCPU’s upgraded to 2.

image

You can download the script below.

Continue reading “PowerCLI: Script to Schedule Memory and or vCPU up/downgrade”

PowerCLI Schedule a restart job for one or multiple VM’s


I created the following script to schedule some restart jobs overnight. The goal for this script was to add some parameters so you don’t have to edit the script file itself to schedule it for another VM or a group of VM’s.

####################################################################
#
# Restart-VMs.ps1
# 
# -vCenter vCenter Server or Servers to connect to. 
# Example -vCenter "vc01","vc02"
# -vmName the VM or VMs to restart.
# Example -vmName "VM1" or -vmName "VM1","VM2"
# # Example: #.\Restart-VMs.ps1 -vCenter vc01.ict-freak.local -vmName "VM1","VM2" # # Version 1.0 May 2010 Arne Fokkema www.ict-freak.nl @afokkema # ##################################################################### param( [parameter(Mandatory = $true)] [string[]]$vCenter, [parameter(Mandatory = $true)] [string[]]$vmName ) $VIServer = Connect-VIServer $vCenter If ($VIServer.IsConnected -ne $true){ Write-Host "error connecting to $vCenter" -ForegroundColor Red exit } foreach($vm in $vmName){ Write-Host "Going to restart $vm" Restart-VMGuest -VM (Get-VM $vm) -Confirm:$false } Disconnect-VIServer -Confirm:$false

Let’s start to run the script from the PowerCLI console first:

image

I started the script without setting any of the parameters. Since these two parameters are necessary  to run the script, you will be asked to enter the parameters, before you can continue.

 

Now it’s time to schedule the script in Windows Server 2008. Just create a simple scheduled task with the following settings:

The first line below is the Program/script: setting. The second line is the Add arguments setting.

C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe

-PSConsoleFile "C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\vim.psc1" " &  "C:\Scripts\Restart-VMs.ps1" -vCenter vc01 -vmName "VM1","VM2"

image

When you are going to use this script, be absolutely sure you are allowed to restart the VM’s you scheduled.

Release: PowerCLI Update Manager cmdlets


image

Just saw the news on Twitter. The PowerCLI Update Manager cmdlets are back!

Quote from the PowerCLI blog:

Cmdlet Name

Cmdlet Description

Attach-Baseline

Attaches baselines to the specified Template, VirtualMachine, VMHost, Cluster, Datacenter, Folder, and VApp objects.
Attaching a baseline to a container object such as a folder or datacenter transitively attaches the baseline to all objects in the container.

Detach-Baseline

Detaches baselines from the specified inventory objects.

Download-Patch

Downloads new patches into the Update Manager patch repository from the enabled patch download sources.

Get-Baseline

Retrieves the baselines specified by the provided cmdlet

parameters.

Get-Compliance

Retrieve baseline compliance data for the specified object of type Template, VirtualMachine, VMHost, Cluster, Datacenter, Folder, and VApp.

Get-Patch

Retrieves all available patches or those specified by the provided cmdlet parameters.

Get-PatchBaseline

Retrieves all patch baselines or those specified by the provided cmdlet parameters.

New-PatchBaseline

Creates a new patch baseline. Patch baselines can be applied to either hosts or virtual machines. Depending on the patch criteria you select, patch baselines can be either dynamic or static (fixed).

Remediate-Inventory

Remediates an inventory object against the specified baselines.

Remove-Baseline

Deletes the specified baselines from their servers. Before the

removal, the baselines are detached from all entities they have been attached to.

Scan-Inventory

Scans inventory objects for baselines attached to them.

Set-PatchBaseline

Modifies the properties of a patch baseline. You can specify explicitly the patches you want to include in the baseline through the IncludePatch parameter.

Stage-Patch

Initializes staging of patches. Staging allows you to download

patches from the Update Manager server to the ESX/ESXi hosts, without applying the patches immediately.

 

Download and more information can be found here: http://communities.vmware.com/

Release Notes can be found here: http://communities.vmware.com/docs/DOC-12075

The online manual can be found here: http://www.vmware.com/

 

You need to install PowerCLI 4 update 1 before you install the Update Manager cmdlets

PowerCLI: Return Datastore name by Canonical name


When you are troubleshooting an ESX host, you can see a lot off warnings in the VMKERNEL log:

Jan 29 16:15:34 esx02.ict-freak.local vmkernel: 9:23:45:33.917 cpu1:4210)WARNING: NMP: nmp_DeviceAttemptFailover:
Retry world failover device “t10.9454450000000000000000001000000056900000D0000000” – issuing command 0x4100041f0c00

But which datastore belongs to the Canonical name mentioned in the VMKERNEL log??

The following script will return the Datastore name. Thanks @Lucd22 for the help!!

$esxhost = "esx1.ict-freak.local"
$id = "t10.9454450000000000000000001000000056900000D0000000"

foreach($ds in (Get-VMHost $esxhost | `
    Get-Datastore | where{$_.Type -eq "vmfs"} | Get-View)){

    $ds.Info.Vmfs.Extent | %{
         if($_.DiskName -eq $id){
            Write-Host $ds.Info.Name $_.DiskName
        }
    }
}

The output will look like this:

image

Ok, this is a nice script to have in you toolbox, but I hear you think,  how do I add it to the VESI?.

First you need to create a new folder, if you don’t use any other Powerpack.

image

Give the folder a name. I used the name Personal scripts:

image

The next step is to add a new script node:

image

The last step is to paste the following code into the new created script node:

if ($global:defaultviservers) {
    $id = Read-Host "Enter the Canonical Name (naa.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)"
    foreach($esx in (Get-VMHost)){
        foreach($ds in (Get-VMHost $esx | Get-Datastore | ` 
        where{$_.Type -eq "vmfs"} | Get-View)){
            $Details = "" |Select-Object DataStore
                $ds.Info.Vmfs.Extent | %{
                 if($_.DiskName -eq $id){
                    $Details.DataStore = $ds.Info.Name
                }
               }
        }
        $Details.PSTypeNames.Clear()
        $Details
    }
}
Else {
    [System.Windows.Forms.MessageBox]::Show('You must connect to one or more hosts before you can use this node. Please click on the ''Managed Hosts'' node of the VMware PowerPack, connect to one or more of the servers you have configured there, and then try again.','Connection not established',[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Information) | Out-Null
}

If you want to run this script, you have to connect to vCenter first. Open VMware – Managed Hosts:

image

Click on Add managed host… to add a server:

image

To connect to the new added vCenter server, press the connect under actions. To run the script click on the new create script node and enter a Canonical Name.

image

And the script will return the Datastore name:

image

Now you are able to convert the Canonical name to the Datastore Name.