Tag: script

Judge at the Nutanix Coding Challenge

Nutanix just announced the PowerShell Coding Challenge for your Nutanix environment. The challenge will be to build a script which solves a real world problem in these use cases: Provisioning/orchestration, reporting, data protection, disaster recovery and runbook automation.

Do you have what it takes to write the best script for a Nutanix environment? Find out by participating in the inaugural Total Recode challenge. This global contest gives you a platform for showcasing your best talent. May the most creative, badass coding guru win!

Want to get more familiar with the Nutanix product and test your script? Check out the Nutanix Prism APIs and our recently announced Community Edition software.

Nutanix Coding Challenge Prizes

You can win great prices:

  • Best Overall
    DJ1 Inspire 1 Drone (Valued up
    to $4000) or $4000 cash prize
  • Most Impactful
    Home Lab ($2,500 value)
    or $2,500 cash prize
  • Most Creative
    $2000 cash prize

And I am proud the be a judge in this contest with other great minds:

 

Nutanix Coding Challenge Judges

If you want to know more or join the challenge, check out the Nutantix Coding Challenge: Total Recode website.



PowerShell

Get name of the PowerShell script file inside the script

When you create a PowerShell script you sometimes want to create some output for a log file for example. In many cases, it makes sense to use the script file name for the log file so you can easily see from which .ps1 the .log file was generated for example. To get the name of the PowerShell ps1. file you can use the following command from MyInvocation:

$MyInvocation.MyCommand

This will return the ps1. file object. To get only the name string you could use:

$MyInvocation.MyCommand.Name

To create a log file with the script file name you could use the following commands:

$path = Get-Location
$scriptName = $MyInvocation.MyCommand.Name
$scriptLog = "$path\$scriptName.log"


Sort Network Adapter via PowerShell

Sort Windows Network Adapter by PCI Slot via PowerShell

If you work with Windows, Windows Server or Hyper-V you know that before Windows Server 2012 Windows named the network adapters randomly. This was a huge deal if you were trying to automate deployment of servers with multiple network adapters. And of course Hyper-V Servers normally have multiple network adapters. In Windows Server 2012 Microsoft had some different ways how this was fixed. First there is CDN (Consistent Device Naming) which allows hardware vendors to integrate the names so the OS can pick them up and the second one being the possibility of Hyper-V Converged Fabric which is basically making our lives easier by having less network adapters.

Well a lot of vendors have not integrated CDN or you have some old servers without CDN support. Back in May 2012 before the release of Windows Server 2012 I wrote a little Windows PowerShell script to sort network adapters in Windows Server 2008 R2 and Hyper-V Server 2008 R2 by using WMI (Configure Hyper-V Host Network Adapters Like A Boss). Now for a Cisco UCS project I rewrote some parts of the script to use Windows PowerShell in for Windows Server 2012, Windows Server 2012 R2 and Hyper-V.

First lets have a look how you can get the PCI slot information for network adapters, luckily there is now a PowerShell cmdlet for this.

 
Get-NetAdapterHardwareInfo

Now lets see how you can sort network adapters via Windows PowerShell.

 
Get-NetAdapterHardwareInfo | Sort-Object Bus,Function

This will get you a output like this:

Sort Network Adapter via PowerShell

Lets do a little loop to automatically name them:

$prefix = "NIC"
$netAdapters = Get-NetAdapterHardwareInfo | Sort-Object Bus,Function
$i = 0
 
foreach ($netAdapter in $netAdapters){
 
$interface = $netadapter | Get-NetAdapter
$old = $interface.Name
$newName = $prefix + $i
$interface | Rename-NetAdapter -NewName $newName
$i++
Write-Host "Rename" $old "to:" $newName
 
}

So this names all the network adapters to NIC1, NIC2, NIC3,…

So lets do a PowerShell function for this:

# ---------------------------------------------------------------------------------------------- #
# Powershell Sort-NetworkAdapter $Rev: 748 $
# (c) 2014 Thomas Maurer. All rights reserved.
# created by Thomas Maurer
# www.thomasmaurer.ch
# last Update by $Author: tmaurer $ on $Date: 2014-01-04 14:07:36 +0100 $
# ---------------------------------------------------------------------------------------------- #
 
function Sort-NetworkAdapter {
<# .SYNOPSIS This sorts and renames network adpaters by PCI slot .DESCRIPTION This sorts and renames network adapters sorted by PCI slot .EXAMPLE Sort-NetworkAdapter -prefix vnic -StartingNumber 0 This renames als NICs to vnic0, vnic1, vnic2,... .EXAMPLE Sort-NetworkAdapter -prefix nic -StartingNumber 1 This renames als NICs to nic1, nic2, nic3,... .PARAMETER prefix The Prefix of the network adapter name .PARAMETER StartingNumber The Number of the first network adapter #>
[CmdletBinding(SupportsShouldProcess=$True,ConfirmImpact='Low')]
param
(
[Parameter(Mandatory=$True,
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True,
HelpMessage='Which prefix you want to use?')]
[ValidateLength(1,20)]
[string]$prefix,
 
[Parameter(Mandatory=$False,
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True,
HelpMessage='Which Starting Number you want to use?')]
[int]$startingNumber = 1
)
 
begin {
write-verbose "Get netadpaters and sort them"
$netAdapters = Get-NetAdapterHardwareInfo | Sort-Object Bus,Function
}
 
process {
 
write-verbose "Rename netadapters"
 
foreach ($netAdapter in $netAdapters){
 
$interface = $netadapter | Get-NetAdapter
$old = $interface.Name
$newName = $prefix + $startingNumber
#$interface | Rename-NetAdapter -NewName $newName
$startingNumber++
Write-Host "Rename" $old "to:" $newName
 
}
}
}

Now you can run this by using Sort-NetworkAdapter for exmaple:

Sort-NetworkAdapter -prefix NIC

or

Sort-NetworkAdapter -prefix NIC -StartingNumber 0

You can also get this script from the Microsoft Technet Gallery or Script Center.



Configure Hyper-V Host Network Adapters Like A Boss

Hyper-V R2 SP1

If you are working a lot with Hyper-V and Hyper-V Clustering you know that something that takes a lot of time is configure the Hyper-V Host Network Adapters. First because most of the time you have a lot of NICs build into your host for the different Hyper-V and Cluster networks and secondly Windows names the NICs in a random way and this makes it hard to find out which network card is the right one. Maybe your first NIC on your Hyper-V Host01 is called “Local Area Connection 2” and on your second Hyper-V Host with the same hardware configuration the “same” NIC is called “Local Area Connection 3”. One of the possibilities to find out which network card is the right one is to check the MAC address of the network adapter. But for this you still have to know which MAC address is on which network adapter port.

Another way to do it is to plug in the network cables one by one. So you can see which port is active and then you can rename the network adapter. Now some times this one is one of the only solutions, but it takes a lot of time to do this on every host. And if you build Clusters up to 16 Hosts you really don’t want to do that.

Now there is a solution, you can sort your NICs by PCI bus and PCI slot. Maarten Wijsman did a blog post how you can do this on the Hyper-V.nu blog. With this knowledge you can start to automate this very easy.

networkcable

I have created two Windows PowerShell scripts which make my life a lot easier.

First I configured the first Hyper-V host and renamed all the Network adapters. If you have a GUI server you could do that via GUI or if you have a Windows Server Core or Hyper-V Server you can do this via netsh.

netsh interface set interface "Local Area Connection 2" newname="Management"

If I have done that I use my  Windows PowerShell script called Get-NICInformation.ps1 to get the information about the network adapters.

get-nicinformation

This gives me a lot of information about the NICs in my first hosts. But the important part is the order of the NICs. In my example I know that the order is this:

  • Management
  • VMNet
  • CSV
  • LiveMigration
  • iSCSI01
  • iSCSI02

Since my other hosts have the same hardware they will have the same PCI Bus order.

# ---------------------------------------------------------------------------------------------- #
# Powershell Get-NICInformation $Rev: 748 $
# (c) 2011 Thomas Maurer. All rights reserved.
# created by Thomas Maurer
# www.thomasmaurer.ch
# www.itnetx.ch
# last Update by $Author: tmaurer $ on $Date: 2012-02-24 14:07:36 +0100 (Fr, 24 Feb 2012) $
# ---------------------------------------------------------------------------------------------- #
 
#region [INFO BLOCK]
# INFO
Write-Host " " -BackgroundColor Black -ForegroundColor White
Write-Host " PowerShell Get-NICInformation " -BackgroundColor Black -ForegroundColor White
Write-Host " " -BackgroundColor Black -ForegroundColor White
Write-Host " by Thomas Maurer " -BackgroundColor Black -ForegroundColor White
Write-Host " www.thomasmaurer.ch " -BackgroundColor Black -ForegroundColor White
Write-Host " " -BackgroundColor Black -ForegroundColor White
#endregion
 
$adapters = Get-WMIObject Win32_PNPSignedDriver | Where-Object { $_.DeviceClass -eq “NET” -and $_.HardWareID -like*PCI*} | Sort-Object location
 
foreach ($adapter in $adapters ) {
 
$adapterName = Get-WMIObject Win32_NetworkAdapter | Where-Object { $_.PNPDeviceID -eq $adapter.DeviceID }
$adapterConfiguration = Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object { $_.index -eq $adapterName.Index }
 
Write-Host ‘Adapter Name :’ $adapterName.NetConnectionID
Write-Host ‘PCI BUS :’ $adapter.Location
Write-Host ‘MAC Address :’ $adapterName.MACAddress
Write-Host ‘GUID :’ $adapterName.GUID
Write-Host ‘Adpater Index :’ $adapterName.Index
Write-Host ‘Hardwarename :’ $adapterName.Name
Write-Host ‘DHCP enabled :’ $adapterConfiguration.DHCPEnabled
Write-Host ‘IP Address :’ $adapterConfiguration.IPAddress
Write-Host ‘Subent :’ $adapterConfiguration.IPSubnet
Write-Host ‘Default Gateway :’ $adapterConfiguration.DefaultIPGateway
Write-Host
 
}

For the next step I go to my second host. There I have my other Windows PowerShell script (Set-IPAddressfromXML) and a XML file (networkconfig.xml).

dir

I edit the networkconfig.xml file with the correct network information. Important here are the id=”” parameters. They are showing the order of the NICs so with Get-NICInformation I can see the Management interface is the first one, so it gets id=”1″, VMNET is the second one it gets id=”2″ and so on. You also set the correct IP Address information for the second host. Most of the time you just have to change the last number.

You can also set non static IP Addresses (DHCP), in my case I did this for the VMNET adapter which will be used by the Hyper-V Virtual Switch and does not need a IP address.

networkconfigxml

<!--?xml version="1.0" encoding="utf-8"?-->

After you have done this, you can now simply run the Set-IPAddressfromXML script. This will use the Information from the networkconfig.xml file and will rename all network adapters and will set the correct IP addresses.

set-ipaddressfromxml

# ---------------------------------------------------------------------------------------------- #
# Powershell Set-IPAddressfromXML $Rev: 748 $
# (c) 2011 Thomas Maurer. All rights reserved.
# created by Thomas Maurer
# www.thomasmaurer.ch
# www.itnetx.ch
# last Update by $Author: tmaurer $ on $Date: 2012-02-24 14:07:36 +0100 (Fr, 24 Feb 2012) $
# ---------------------------------------------------------------------------------------------- #
 
#region [INFO BLOCK]
# INFO
Write-Host " " -BackgroundColor Black -ForegroundColor White
Write-Host " PowerShell Set-IPAddressfromXML " -BackgroundColor Black -ForegroundColor White
Write-Host " " -BackgroundColor Black -ForegroundColor White
Write-Host " done by Thomas Maurer " -BackgroundColor Black -ForegroundColor White
Write-Host " www.thomasmaurer.ch " -BackgroundColor Black -ForegroundColor White
Write-Host " " -BackgroundColor Black -ForegroundColor White
#endregion
 
#region [CONFIG BLOCK]
# Get XML Information
<pre lang="xml">$global:xmlData = Get-Content ".\networkconfig.xml"
# Set NIC number starting value
[int]$global:nicNumber = "1"
#endregion
 
#region [MAIN BLOCK]
#Get NIC list
$Adapters = Get-WMIObject Win32_PNPSignedDriver | where { $_.DeviceClass -eq “NET” -and $_.HardWareID -like*PCI*} | Sort-Object location
 
foreach ($Adapter in $Adapters ) {
# Get Adapter Info
$AdapterName = Get-WMIObject Win32_NetworkAdapter | where { $_.PNPDeviceID -eq $Adapter.DeviceID }
$nic = $xmlData.config.networkadapters.nic | Where-Object {$_.id -eq $nicNumber}
 
# Write NIC Info
Write-Host ‘Adapter Name :’ $AdapterName.NetConnectionID
Write-Host ‘PCI BUS :’ $Adapter.Location
Write-Host ‘MAC Address :’ $AdapterName.MACAddress
Write-Host ‘GUID :’ $AdapterName.GUID
Write-Host ‘New Name :’$nic.name
Write-Host
 
# Change NIC Name
Invoke-Expression ('netsh interface set interface `"' + $AdapterName.NetConnectionID + '`" newname=`"' + $nic.name + '`" | out-null')
Write-Host ('netsh interface set interface "' + $AdapterName.NetConnectionID + '" newname="' + $nic.name + '"') -BackgroundColor Green -ForegroundColor Black
 
# if true set IP Address
if ($nic.static -eq "true"){
Invoke-Expression ('netsh interface ipv4 set address `"' + $nic.name + '`" static ' + $nic.ip +' ' + $nic.subnet + ' ' + $nic.gateway + ' | out-null')
Write-Host ('netsh interface ipv4 set address "' + $nic.name + '" static ' + $nic.ip +' ' + $nic.subnet + ' ' + $nic.gateway) -BackgroundColor Green -ForegroundColor Black
}
else {
Write-Host "No IP set" -BackgroundColor Green -ForegroundColor Black
}
 
# Count +1 for next Adapter
$nicNumber++
}
#endregion

 

I can now copy the Set-IPAddressfromXML.ps1 and the networkconfig.xml to each Hyper-V hosts and edit the IP Addresses in the xml file, run the PowerShell file and I am done.

Lets recap:

  1. Rename the NICs of the first hosts
  2. Run the Get-NICInformation.ps1 on the first host and check the NIC order
  3. Edit the networkconfig.xml on the second hosts with the right order of the NICs
  4. Run the Set-IPAddressfromXML.ps1
  5. Do this for all Hyper-V Hosts.

I hope this will make life easier :)

You can download the Scripts from my Skydrive

Some other things:

  • I have tested this with Windows Server 2008 R2, Hyper-V Server R2, Windows Server 8 beta, Hyper-V Server 8 beta
  • It works for both because it’s not done with PowerShell v3, maybe I will update it to get it even better.
  • I do not support this script, and you are running it on your own risk.


Run Remote Powershell Commands on multiple standalone Computers

Powershell Header

With this little Powershell Script you can run Powershell Commands on multiple Remotehosts even if those are not in an Active Directory.

# Config
$Servers = @("Server01", Server02)
$Cred = Get-Credential # Add Credentials for all Servers (Domain or non-Domain)
 
# Run Command (for example Get-Service | Where-Object {$_.Name -eq "BITS"}
foreach ($Server in $Servers) {
	Invoke-Command -ComputerName $Server -Credential $Cred {Get-Service | Where-Object {$_.Name -eq "BITS"}}
}

Important:

You have to enable Powershell Remoting on the Remotehost with Enable-PSRemoting



Powershell: Send Tweet

Powershell Header

For some reason your Powershell script should send a Tweet. With this function Powershell will send a message to Twitter.

function Send-Tweet($Message)
{
#Twitter Login
$Twitter_UserName = "yourname"
$Twitter_Password = "yourpassword"
$Twitter_URL = "https://twitter.com/statuses/update.xml?status="

$Twitter_Request = [System.Net.WebRequest]::Create($Twitter_URL + $Message)
$Twitter_Request.credentials= New-Object System.Net.NetworkCredential($Twitter_UserName,$Twitter_Password)
$Twitter_Request.method= "POST"
$Twitter_Request.contentType = "application/x-www-form-urlencoded"
$Twitter_Request.GetResponse().statusCode # return the status code of the request
}

You can now call this function and add a message

Send-Tweet "This is my first Tweet from Powershell"

Twitter

If you need a interactive script you can simply use this (seen by Bhargav’s IT Playground)

function Send-Tweet($Message,$UserName){
if($Message-eq$null){$Message=Read-Host"Enter your tweet"}
if($Username-eq$null){$Username=read-host"Enter your twitter username"}
if($Password-eq$null)
{
$Password=read-host-assecurestring"Enter your twitter password"
$marshal=[Runtime.InteropServices.Marshal]
$Password=$marshal::PtrToStringAuto($marshal::SecureStringToBSTR($Password))
}
$url="https://twitter.com/statuses/update.xml?status=$Message"
$request=[System.Net.WebRequest]::Create($url)
$request.credentials=New-Object System.Net.NetworkCredential($UserName,$Password)
$request.method="POST"
$request.contentType ="application/x-www-form-urlencoded"
$request.GetResponse().statusCode # return the status code of the request}



Powershell: Invoke-Expression

Powershell Header

Using the Invoke-Expression Cmdlet:

The Invoke-Expression cmdlet provides one way to run a script from within Windows PowerShell.

Invoke-Expression c:\scripts\test.ps1

or

& c:\scripts\test.ps1

And you also can run a function in your Powershell Script by a variable. This is something really important when you work with dynamic scripts:

Invoke-Expression -command ($Function_Name)

you even can send dynamic parameters to this function:

Invoke-Expression -command ($Function_Name + ' $Function_Parameters')