Archive

Archive for the ‘Powershell’ Category

VMware vSphere community (free) health check options

October 14th, 2015 No comments

I recently did a presentation at the South West VMUG on VMware vSphere community (free) health check options. In my presentation I covered some of the options available out there at the moment such as:

  • vCheck (vSphere plugins)
  • vGhetto health check script
  • Miscellaneous PowerCLI / PowerShell options
Starting off the session in style - Intro in mspaint, running under Windows 3.1

Starting off the session in style – Intro in mspaint, running under Windows 3.1

 

The second half of my presentation I dived into a live PowerCLI and PowerShell demo where I demonstrated some PowerCLI basics to get any kind of information out of your vSphere environment using some of the core cmdlets. I demonstrated use of the core PowerCLI cmdlets used for retrieving VM, Host and Datastore information, how to use the pipeline in PowerShell, and taking a look at all properties on any PS object using the Get-Member cmdlet on the pipeline.

After covering these basics, I took a blank vCheck plugin template, and showed how easy it is to create your own custom plugins for vCheck should you find that the existing plugins don’t cover everything you need.

I’ve got a link to download the slides for the presentation below, and hopefully I’ll be able to find a recording of the PowerCLI / PowerShell live demo I did to attach to this post as a follow up.

 

 

If you’re based in the South West of the UK, be sure to check out and attend the next SW VMUG meeting!

vmw_vmug_logo

Octopus Deploy Endpoint auto configuration on Azure VM deployment

January 28th, 2015 No comments

I’ve been working on a very cool project that involves the use of Microsoft Azure, TeamCity and Octopus Deploy.

I have created an Azure PowerShell script that deploys VMs into an Azure Subscription (Web machines that run IIS) as a part of a single Azure Cloud Service with load balancing enabled. As such, the endpoint ports that I create for Octopus tentacle communication need to differ for each machine on the public interface.

I wanted to fully automate things from end-to-end, so I wrote a very small console application that uses the Octopus Client library NuGet package in order to be able to communicate with your Octopus Deploy server via the HTTP API.

Octopus Endpoint Configurator on GitHub

The OctopusConfigurator console application should be run in your Azure VM once it is deployed, with 4 x parameters to specify when run.

It will then establish communication with your Octopus Deploy server, and register a new Tentacle endpoint using the details you pass it. The standard port number that gets assigned (10933) will then be replaced if necessary with the correct endpoint port number for that particular VM instance in your cloud service. For example, I usually start the first VM in my cloud service off on 10933, then increment the port number by 1 for every extra VM in the cloud service. As the deployments happen, the console application registers each new machine’s tentacle using the incremented port number back with the Octopus master server.

Once the Azure VM deployment is complete, I tell the VMs in the cloud service to restart with a bit of Azure PowerShell and once this is done, your Octopus environment page should show all newly deployed tentacles as online for your environment. Here is an example of an Invoke-Command scriptblock that I execute remotely on my Azure VMs as soon as they have completed initial deployment. What I do is tell the VM deployment script to wait for Windows boot, so once ready, the WinRM details are fetched for the VM using the Get-AzureWinRMUri cmdlet for Azure, which allows me to use the Invoke-Command to run the below script inside the guest VM.

 

Invoke-Command -ConnectionUri $connectionString -Credential $creds -ArgumentList $vmname,$externalDNSName,$creds,$InstallTentacleFunction,$OctopusExternalPort,$OctopusEnvironmentName -ScriptBlock {
	
	$webServerName = $args[0]
    $DNSPassthrough = $args[1]
    $passedCredentials = $args[2]
    $scriptFunction = $args[3]
    $OctoPort = $args[4]
    $OctopusEnvironmentName = $args[5]
		
	function DownloadFileUrl($url, $destinationPath, $fileNameToSave)
	{
	    $fullPath = "$destinationPath\$fileNameToSave"

	    if (Test-Path -Path $destinationPath)
	    {
	        Invoke-WebRequest $url -OutFile $fullPath
	    }
	    else
	    {
	        mkdir $destinationPath
	        Invoke-WebRequest $url -OutFile $fullPath
	    }

	    Write-Host "Full path is: $fullPath"
	    return [string]$fullPath
	}
	
	# Download the Octopus Endpoint Configurator to C:\Temp
	[string]$ConfiguratorPath = DownloadFileUrl "https://dl.dropboxusercontent.com/u/xxxxxxx/Apps/OctopusConfigurator.zip" "C:\Temp" "OctopusConfigurator.zip"
	
	Write-Host "Unzipping OctopusConfigurator.zip" -ForegroundColor Green
    cd C:\Temp
    $shell_app=new-object -com shell.application
    $filename = "OctopusConfigurator.zip"
    $zip_file = $shell_app.namespace((Get-Location).Path + "\$filename")
    $destination = $shell_app.namespace((Get-Location).Path)
    $destination.Copyhere($zip_file.items())
	
    cd C:\Temp

    if (Test-Path -Path .\OctopusConfigurator.exe)
    {
        & .\OctopusConfigurator.exe http://theoctopusurl.domain API-XXXXXXXXXXXXXXXXXXXXXX $webServerName $OctoPort
        Write-Host "Reconfigured Octopus Machine URI to correct port number" -ForegroundColor Green
    }
    else
    {
        Write-Host "OctopusConfigurator not found!" -ForegroundColor Red
        Exit
    }
}

Interacting with VMware vCO and the Rest API using PowerShell – getting a list of workflows

April 2nd, 2014 2 comments

Recently I needed to get a list of VMware vCO workflows from a remote server using PowerShell. A colleague of mine pointed me in the right direction by providing me with a URL to access the vCO Rest API on, as well as letting me know what I needed to send in order to authenticate.

To connect and retrieve content back in the PowerShell example below, we’ll need to:

  • Access the Rest API URL for Orchestrator using a web client object
  • Send basic authentication in the header of our request

Notes:

One thing I did notice is that when you use your web browser to test the URL, the result is returned to you as XML, however when I used a web client object in PowerShell, I got a result returned to me in JSON. The PowerShell script below is therefore tailored to interpret the result as JSON. This being so, you’ll need to make sure you are using PowerShell 3.0 or above, as the ConvertFrom-Json cmdlet is only available using PowerShell 3.0 and above.

When sending your authentication details with the web client object request, make sure your username/password combo are used in this format:

Authorization: Basic username:password

This means that your header you add to your web client option, should be added with the string as per the above, but with the username:password part encoded using base64. The script below takes this all into account, and all you need to do is provide your username and password for vCenter Orchestrator to the PowerShell function, it will handle the base64 encoding and passing of the values to the web client itself.

Anyway, enough of that, let us get onto the actual script itself. This is presented as a PowerShell function. Load it into your session (copy-paste) or add it to your PS profile for future use. Apologies for the formatting – Syntax Highlighter really messes with the formatting and nice clean indentation I normally have in my scripts!

Here is a direct download of the PowerShell script if the script paste below doesn’t work for you:

 

Function Get-VcoWorkflow() 
{

<#
.SYNOPSIS
Fetches vCO Workflow information and details from a vCenter Orchestrator server

.DESCRIPTION
Fetches vCO Workflow information and details from a vCenter Orchestrator server

.PARAMETER Username
Username for the vCO server

.PARAMETER Password
Password for the vCO server

.PARAMETER Server
The vCO server hostname or IP address

.PARAMETER PortNumber
The port to connect on

.EXAMPLE
PS F:\> Get-VcoWorkflow -Username Sean -Password mypassword -Server 192.168.60.172 -PortNumber 8281

.LINK

http://www.shogan.co.uk

.NOTES
Created by: Sean Duffy
Date: 30/03/2014
#>

[CmdletBinding()]
param(
[Parameter(Position=0,Mandatory=$true,HelpMessage="Specify your vCO username.",
ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
[String]
$Username,

[Parameter(Position=1,Mandatory=$true,HelpMessage="Specify your vCO password.",
ValueFromPipeline=$false,ValueFromPipelineByPropertyName=$true)]
[String]
$Password,

[Parameter(Position=2,Mandatory=$true,HelpMessage="Specify your vCO Server or hostname.",
ValueFromPipeline=$false,ValueFromPipelineByPropertyName=$true)]
[String]
$Server,

[Parameter(Position=2,Mandatory=$true,HelpMessage="Specify your vCO Port.",
ValueFromPipeline=$false,ValueFromPipelineByPropertyName=$true)]
[ValidateRange(0,65535)] 
[Int]
$PortNumber
)

process 
{
$Report = @() | Out-Null

# Craft our URL and encoded details note we escape the colons with a backtick.
$vCoURL = "https`://$Server`:$PortNumber/vco/api/workflows"
$UserPassCombined = "$Username`:$Password"
$EncodedUsernamePassword = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($UserPassCombined))
$Header = "Authorization: Basic $EncodedUsernamePassword"

# Ignore SSL warning
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

# Create our web client object, and add header for basic authentication with our encoded details
$wc = New-Object System.Net.WebClient;
$wc.Headers.Add($Header)

# Download the JSON response from the Restful API, and convert it to an object from JSON.
$jsonResult = $wc.downloadString($vCoURL)
$jsonObject = $jsonResult | ConvertFrom-Json

# Create a blank Report object array
$Report = @()

# Iterate over the results and transform the key/value pair like formatting to a proper table.
# Note I use a hashtable to populate a new PSObject with properties, using values found in the original JSON result
foreach ($link in $jsonObject.link)
{
	$kvps = $link.attributes
	$HashTable = @{}
	$kvps | foreach { $HashTable[$_.name] = $_.value } # foreach item in the link object, populate the hashtable
	$NewPSObject = New-Object PSObject -Property $HashTable # Create a new PSObject and populate the properties/values using our hashtable

	# Add our populated object to our Report array
	$Report += $NewPSObject
}

return $Report

}
}

I hope that this script comes in handy, and gives you an idea as to how you can retrieve and convert data from vCO and its RESTful API for use in PowerShell 🙂

Results example after running the Function:
get-vcoworkflow-results

 

Three PowerCLI scripts for information gathering – VMs, Hosts, etc

February 11th, 2014 6 comments

 

I was on a vSphere upgrade review engagement recently, and part of this involved checking hardware and existing vSphere VI was compatible with the targeted upgrade.

To help myself along, I created a few PowerCLI scripts to help with information gathering to CSV for the VI parts – such as Host Versions, build numbers, VMware tools and hardware versions, etc… These scripts were built to run once-off, simply either by copy/pasting them into your PowerCLI console, or by running them from the PowerCLI console directly.

They can easily be adapted to collect other information relating to VMs or hosts. To run, just launch PowerCLI, connect to the VC in question (using Connect-VIServer) and then copy/paste these into the console. The output will be saved to CSV in the directory you were in. Just make sure you unblock the zip file once downloaded if you execute them directly from PowerCLI, otherwise the copy/paste option mentioned above will work fine too.

There are three scripts bundled in the zip file:

  • Gather all hosts under the connected vCenter server and output Host name, Model and Bios version results to PowerCLI window and CSV
  • Gather all hosts under the connected vCenter server and output Host name, Version and Build version results to PowerCLI window and CSV
  • Gather all hosts under the specified DC and output VM name and hardware version results to PowerCLI window and CSV

Short and simple scripts, but hopefully they will come in handy to some. As mentioned above, these can easily be extended to fetch other information about items in your environment. Just take a look at the way existing info is fetched, and adapt from there. Also remember that using | gm (get-member) on objects in PowerShell is your friend – you can discover all the properties and methods on PowerShell objects by using this, and use those to enhance your reports/outputs in your scripts.

 

Issue using the Count method to count objects with PowerShell 2.0

November 7th, 2012 No comments

 

I came across a small issue with a little helper script I wrote to count vSphere objects using PowerCLI this morning. It’s been a couple of a weeks since I last did a blog post – things have been very busy, so I have not been able to commit much time over the last few weeks to blogging. As such, I thought I would do a quick post around this small issue I came across earlier. It has more than likely been covered off elsewhere, but will be a good reference point to come back to if I ever forget!

 

So to the issue I saw. Essentially, if an object count is 1 or less, then the object is returned as the object type itself. For example, where only one Distributed Virtual Switch exists in a vSphere environment, and we use the cmdlet, Get-VirtualSwitch -Distributed, a single object is returned of BaseType “VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl“.

 

However, if we had more than one dvSwitch, then we would get a BaseType of “System.Array” returned.

 

We are able to use the Count() method on an array with PowerShell version 2.0, but are not able to use the Count() method on a single object. The work around I found here (when using PowerShell 2.0) is to cast the object type specifically as an array.

So in the case of our dvSwitch example above, originally we would have done:

@dvSwitchCount = (Get-VirtualSwitch -Distributed).Count

 

To cast this as an array, and therefore having an accurate count of the objects, whether there are no members, one member, or more, we would use:

@dvSwitchCount = @(Get-VirtualSwitch -Distributed).Count

 

Note the addition of the “@” sign – used to cast the variable as an array.

Jonathan Medd also kindly pointed out that this is fixed with PowerShell 3.0 – have a read of the new features to see the addition that allows .Count to be used on any type of object over here.

Get Virtual Machine Inventory from a Hyper-V Failover Cluster using PowerShell

July 10th, 2012 4 comments

A colleague was asking around for a PowerShell script that would fetch some inventory data for VMs on a Hyper-V cluster the other day. Not knowing too much about Hyper-V and having only ever briefly looked at what was out there in terms of PowerShell cmdlets for managing Hyper-V, I decided to dive in tonight after I got home.

 

Here is a function that will fetch Inventory data for all VMs in a specified Failover Cluster. This is what it fetches:

  • VM Name
  • VM CPU Count
  • VM CPU Socket Count
  • VM Memory configuration
  • VM State (Up or Down)
  • Cluster Name the VM resides on
  • Hyper-V Host name the VM resides on
  • Network Virtual Switch Name
  • NIC Mac Address
  • Total VHD file size in MB
  • Total VHD Count

 

Being a function, you can pipe in the name of the cluster you want, for example Get-Cluster | Get-HyperVInventory. Or you could do Get-HyperVInventory -ClusterName “ExampleClusterName”. You could also send it to an HTML Report by piping it to “ConvertTo-HTML | Out-File example.html”

Download here, or copy it out from the script block below:
Download Get-HyperVInventory PowerShell Script (3800)
 

# Requires: Imported HyperV PowerShell module (http://pshyperv.codeplex.com/releases/view/62842)
# Requires: Import-Module FailoverClusters
# Requires: Running PowerShell as Administrator in order to properly import the above modules

function Get-HyperVInventory {
<#
.SYNOPSIS
Fetches Hyper-V VM Inventory from a specified Hyper-V Failover cluster

.DESCRIPTION
Fetches Hyper-V VM Inventory from a specified Hyper-V Failover cluster

.PARAMETER ClusterName
The Name of the Hyper-V Failover Cluster to inspect

.EXAMPLE
PS F:\> Get-HyperVInventory -ClusterName "dev-cluster1"

.EXAMPLE
PS F:\> Get-Cluster | Get-HyperVInventory

.LINK
http://www.shogan.co.uk

.NOTES
Created by: Sean Duffy
Date: 09/07/2012
#>

[CmdletBinding()]
param(
[Parameter(Position=0,Mandatory=$true,HelpMessage="Name of the Cluster to fetch inventory from",
ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
[System.String]
$ClusterName
)

process {

$Report = @()

$Cluster = Get-Cluster -Name $ClusterName
$HVHosts = $Cluster | Get-ClusterNode

foreach ($HVHost in $HVHosts) {
$VMs = Get-VM -Server $HVHost
foreach ($VM in $VMs) {
[long]$TotalVHDSize = 0
$VHDCount = 0
$VMName = $VM.VMElementName
$VMMemory = $VM | Get-VMMemory
$CPUCount = $VM | Get-VMCPUCount
$NetSwitch = $VM | Get-VMNIC
$NetMacAdd = $VM | Get-VMNIC
# VM Disk Info
$VHDDisks = $VM | Get-VMDisk | Where { $_.DiskName -like "Hard Disk Image" }
foreach ($disk in $VHDDisks) {
$VHDInfo = Get-VHDInfo -VHDPaths $disk.DiskImage
$TotalVHDSize = $TotalVHDSize + $VHDInfo.FileSize
$VHDCount += 1
}
$TotalVHDSize = $TotalVHDSize/1024/1024
$row = New-Object -Type PSObject -Property @{
Cluster = $Cluster.Name
VMName = $VMName
VMMemory = $VMMemory.VirtualQuantity
CPUCount = $CPUCount.VirtualQuantity
CPUSocketCount = $CPUCount.SocketCount
NetSwitch = $NetSwitch.SwitchName
NetMACAdd = $NetMacAdd.Address
HostName = $HVHost.Name
VMState = $HVHost.State
TotalVMDiskSizeMB = $TotalVHDSize
TotalVMDiskCount = $VHDCount
} ## end New-Object
$Report += $row
}
}
return $Report

}
}

 

Example use cases – load the function into your PowerShell session, or place it in your $profile for easy access in future, and run the following:

# Example 1
Get-HyperVInventory -ClusterName "mycluster1"
# Example 2
Get-Cluster | Get-HyperVInventory
# Example 3
Get-HyperVInventory -ClusterName "mycluster1" | ConvertTo-HTML | Out-File C:\Report.html

 

The function includes help text and examples, so you can also issue the normal “Get-Help Get-HyperVInventory” or “Get-Help Get-HyperVInventory -Examples”. It is by no means perfect and could do with some improvements, for example if there is more than one Virtual Switch Network associated with a VM these would be listed in a row multiple times for each. Feel free to suggest any improvements or changes in the comments.