Social

onsdag den 21. oktober 2015

Pinging with Powershell - Get a list of online servers

Just about every IT guy or girl on the planet has used ping countless of times. With Powershell those days are over: Meet Test-Connection. It works just as you would expect and similar to ping, the advantage being that you (by default) get an object of type "System.Management.ManagementObject#root\cimv2\Win32_PingStatus" back.

I wont go into details on how to use Test-Connection, there are plenty of ressources doing just that. But I recently discover a very cool way to use Test-Connection against a large number of servers. And as they say, A script is worth a thousand words:

function Check-Online
{
    param(
        $ComputerName
        )

    Begin
    {
        # put live servers into this list
        $Script:serverlist = @()
    }

    Process
    {
        If (Test-Connection -Count 1 -ComputerName  $_ -TimeToLive 5 -asJob | 
         Wait-Job |
         Receive-Job |
         ? { $_.StatusCode -eq 0 } )
        {
            $Script:serverlist += $_
        }
    }
    End
    {
        return $Script:serverlist
    }
}

# get computer names from hyper-v
$ComputerNames = Get-VM | Select-Object -ExpandProperty Name
# check which are online
$ComputerNames | Check-Online

Simply feed the Check-Online function a list of computernames (IPs should work just as well) and it will return a list of online servers within seconds.

I think credit for the original code goes to my Lumagate colleague Claus Nielsen who just happens to be a Powershell MVP.

Download script from Technet gallery.

fredag den 16. oktober 2015

Reattaching Drives on VMs Using Powershell (General access denied on vhdx)

I recently had some storage issues in the company lab which meant that after a lengthy CHKDSK that permission on all VHDX files was lost. The solution was luckily simple: Reattach each drive and the permission on the file was restored. Problem was then that there was more than 50 drives all in all. Solution then became, as it often is, do it with Powershell.

The script as follows (Download from Technet), formatted using https://tohtml.com/powershell/:

$States = ( [Microsoft.HyperV.PowerShell.VMState]::Off, 
            [Microsoft.HyperV.PowerShell.VMState]::OffCritical
          )

$VMs = Get-VM | ? {$_.State -in $States}
$DriveCount = ($VMs | Get-VMHardDiskDrive).Count
$Counter = 0

foreach($VM in $VMs)
{
    $Drives = $VM | Get-VMHardDiskDrive
    foreach($Drive in $Drives)
    {
        $Counter += 1
        # Some of these values (Path at least) disappear from the $Drive object when we remove it from the machine
        $ControllerNumber = $Drive.ControllerNumber
        $ControllerLocation = $Drive.ControllerLocation
        $Path = $Drive.Path
        $SupportPersistentReservations = $Drive.SupportPersistentReservations
        $ControllerType = $Drive.ControllerType

        Write-Progress  -Activity "Reattaching drives" `
                        -Status "Removing $Path from $($VM.Name)" `
                        -PercentComplete (100*$Counter/$DriveCount) 
        Remove-VMHardDiskDrive -VMHardDiskDrive $Drive
        
        if($SupportPersistentReservations)
        {
            # Shared vhdx
            Add-VMHardDiskDrive -VM $VM `
                                -ControllerNumber $ControllerNumber `
                                -ControllerLocation $ControllerLocation `
                                -Path $Path `
                                -ControllerType $ControllerType `
                                -SupportPersistentReservations
        }
        else
        {
                        Add-VMHardDiskDrive -VM $VM `
                                -ControllerNumber $ControllerNumber `
                                -ControllerLocation $ControllerLocation `
                                -Path $Path `
                                -ControllerType $ControllerType
        }
        
        Write-Progress  -Activity "Reattaching drives" `
                        -Status "Reattached $Path to $($VM.Name)" `
                        -PercentComplete (100*$Counter/$DriveCount)
    }
}

tirsdag den 6. oktober 2015

Creating Multiple Azure NICs Using Multiple Instances (ARM Template)

I have started playing around with ARM and Azure in general and wanted to get my feet wet with linked templates and multiple instances. My very gifted colleague Kristian Nese has already covered template linking just fine, but I have yet to find a simple example on how to use multiple instances (honestly, I didn't try that hard, I want to do it myself).

Anyways, I thought I would share what I have done so far. It is a good introduction to multiple instances in ARM templates, and also get to use a few of the template functions. I will not provide a full solution (strongly suggest you piece it together yourself for the learning experience), but rather snippets and explanations (to the best of my knowledge).

If you are new to ARM templates: go away. No, just kidding, but do come back when you have the basics covered. I attended this hands on lab recently and found the excercises was an excellent learning experience. The teacher suggested not to use Visual Studio as you miss out on learning some of the basics of ARM templates. Follow that advice and just use your prefered json-editor (Sublime Text 2).

We will jump right in. The following snippet creates multiple NICs in Azure based on a parameter namePrefixes which we use to prefix various resources.

"namePrefixes": {
      "type": "array",
      "defaultValue": [
        "dc",
        "sql",
        "scsm"
      ]
    }

The resource NICs are declared as follows

{
  "dependsOn": [
    "[concat('Microsoft.Resources/deployments/',  parameters('vnetName'))]",
    "[concat('Microsoft.Network/publicIPAddresses/', parameters('namePrefixes')[copyIndex()], '-', variables('pulicIPPostfix'))]"
  ],
  "name": "[concat(parameters('namePrefixes')[copyIndex()], '-', variables('nicPostfix'))]",
  "type": "Microsoft.Network/networkInterfaces",
  "location": "[resourceGroup().location]",
  "apiVersion": "2015-06-15",
  "copy": {
    "name": "nicCopy",
    "count": "[length(parameters('namePrefixes'))]"
  },
  "properties": {
    "ipConfigurations": [
      {
        "name": "[concat('ipconfig', copyIndex())]",
        "properties": {
          "privateIPAllocationMethod": "static",
          "privateIPAddress": "[concat(variables('addressPrefixSplit')[0], '.', variables('addressPrefixSplit')[1], '.', variables('addressPrefixSplit')[2], '.', add(copyIndex(), 4))]",
          "subnet": {
            "id": "[variables('subnetID')]"
          },
          "publicIPAddress": {
            "id": "[resourceId('Microsoft.Network/publicIPAddresses',concat(parameters('namePrefixes')[copyIndex()], '-', variables('pulicIPPostfix')))]"
          }
        }
      }
    ]
  }
}

First we need to indicate that the nics depend on a virtual network. Here I am using Microsoft.Resources/deployments because the virtual network has been deployed using a linked template. We also depend on some public ip addresses that we have created using multiple instances also.
The naming scheme is to iterate the namePrefixes array and postfix the variable nicPostfix (mine has the value "nic").
Now in order to provide static IP addresses we use the variable addressPrefixSplit which is defined as

"addressPrefixSplit": "[split(parameters('addressPrefix'), '.')]"


We simply split the addressPrefix parameter on '.', ex. 10.0.0.0/16 which is also used to create the virtual network. The IP address is then the first 3 octets of the addressPrefix and the 4th octet is the value of copyIndex() + 4 which would give us the addresses: 10.0.0.4, 10.0.0.5, and 10.0.0.6.

The public IP Address is a reference to the resource ID of public IP addresses created using the same approach:

{
      "apiVersion": "2015-06-15",
      "type": "Microsoft.Network/publicIPAddresses",
      "location": "[resourceGroup().location]",
      "name": "[concat(parameters('namePrefixes')[copyIndex()], '-', variables('pulicIPPostfix'))]",
      "copy": {
        "name": "pipCopy",
        "count": "[length(parameters('namePrefixes'))]"
      },
      "properties": {
        "publicIPAllocationMethod": "[variables('publicIPAllocationMethod')]"
      }
}

Now you are ready to deploy a billion trillion NICs with just a few lines of json (not counting the billion trillion lines of name prefixes :D)

Søg i denne blog