Hyper-V

Deploying StorSimple On-Premises Virtual Array (OVA) via GUI tools


The StorSimple model 1200 OVA (On-Premises Virtual Array) is available as VHD/VHDX or VMDK file to be deployed on local Hyper-V or VMWare hypervisor.

Note that the StorSimple OVA model 1200 is incompatible with the StorSimple 8k series physical and virtual devices (8100, 8600, 8010, 8020). This means we cannot recover volumes from 8k device to a 1200 OVA device or vice versa.

1. Deploy ‘Virtual Device Series’ StorSimple Manager:

You cannot deploy an OVA under your ‘Physical Device Series’ StorSimple Manager service. To deploy a ‘Virtual Device Series’ StorSimple Manager follow these steps in the classic portal:

ova01

Uncheck the box at the bottom to create a Storage Account.

Note that OVA is available on the following Azure regions as of 20 October 2016:

  • Australia East
  • Australia Southeast
  • Brazil South
  • East Asia
  • Southeast Asia
  • East US
  • West US
  • Japan East
  • Japan West
  • North Europe
  • West Europe

Enter a name for your StorSimple Manager service.

2. Create a Storage Account

I prefer to manually create a Storage Account instead of having one created automatically, to be able to give it a name that makes sense for the deployment, and becomes easy to identify and recognize later on.

ova04

Make sure the Storage Account is in the same Azure region as the StorSimple Manager service.

3. Download the OVA image file

Under the new StorSimple Manager service/devices/create virtual device:

ova02

You’ll see a page like:

ova03

Click the link under item #1 that corresponds to your hypervisor to download the OVA file. Copy the Registration Key at the bottom. It will be used later in step x to register the OVA with the StorSimple Manager service.

Extract the .ZIP file

ova05

4. Provision a VM for the OVA:

I’m using Hyper-V on Server 2012 R2 in this example. Minimum VM specs: 4 cores, 8 GB of RAM, 500 GB disk space for drive c: (system disk).

ova06

Gen 2 is supported and recommended when using VHDX image on Server 2012 R2

ova07

According to Microsoft, dynamic memory is not supported 😦ova08

Connect to the Hyper-V switch of your choice. Use the downloaded disk:

ova09

Click Next and Finish. Go back the VM settings/Processor, and select to use 4 cores:

ova10

Add a second disk to the VM under the SCSI controller. Set it as 500 GB dynamically expanding disk.

ova11

Start the VM and login to it. This takes several minutes. The default user is StorSimpleAdmin and the default password is Password1. Login and change the password (8 character minimum). The OVA image has a Core version of Server 2012 R2, and if DHCP server is available it picks up an IP address:

ova12

An extremely limited set of commands is available:

ova13

However, Microsoft has made the support mode available without the need for a decryption tool:

ova25

This exposes the entire PowerShell capabilities for admins to manage the device.

ova26

This is really a good decision on Microsoft’s part. The current local web interface has many idiosyncrasies that can be frustrating for a device admin. Having the option to manage the device via PowerShell goes a long way towards faster device adoption and customer satisfaction in my opinion and experience.

Although not required, I recommend using a static MAC address for the OVA VM. To do so shut down the VM from Hyper-V Manager, then under settings\network\advanced, select static MAC:

ova14

Start the VM.

5. Configure the OVA via the local web interface

Browse to the OVA IP address, and bypass the local certificate warning in the browser. Login with the new password you created in the prior step.

ova15

Under configuration/network settings, I recommend using a static IPv4 address

ova18

Notes:

  • By default, the OVA will attempt to get IP address if there’s DHCP server in the environment.
  • To view/change the IP address configuration in the local web interface, if you try to change the DNS server IP it will error out. A work around is to change it back to DHCP, apply, browse to the DHCP IP, login, change it back to static IP and make all the needed changes in one step. In other words, you must change IP address and DNS server address in one step or it fails to accept the changes’
  • There’s no way to remove IPv6 information in the local web interface

Browse to the new IP address to continue. For this post I’m using the device as an iSCSI SAN. I settled on leaving the device in ‘workgroup’:

ova19

Note:

I was unable to join an on-premises AD domain:

ova17

and entered credentials as:

ova21

But got the error message “Domain does not exist”!!??

ova20

I attempted to use the NetBIOS names (sam1 domain and sam1\administrator user) but got the same error.

I verified connectivity between the DC and the OVA, running these commands on the DC:

ova22

I also verified that the DC is responding to DNS queries. I ran the following command from a 3rd computer:

ova23


I skipped Proxy settings, since I’m not using a proxy to get to the Internet in this environment.

Interestingly enough, Time Server settings accepted the local DC with no problem:

ova24

Finally, I registered the device with the StorSimple Manager Service by entering the Service Registration Key. This was my first device on this StorSimple Manager Service, so I recorded the Service Data Encryption Key received upon successful registration.

Notes:

  • If this is not the first device to be registered with this StorSimple Manager service, you’ll need the Service Data Encryption Key as well to be able to register the device
  • You must have 3 green check marks at the Network, Device, and Time settings to be able to register the device under Cloud setting

ova27

6. Complete OVA configuration in Azure

In the classic portal (24 October 2016), click on your StorSimple Manager Service/Devices link and you should see the newly registered OVA

ova27

Click on that and click Complete Device Configuration

ova28

In the next screen, select a Storage Account. I recommend checking the box to Enable Cloud Storage Encryption, and entering a 32 character seed for at-rest encryption of data blocks that the device sends to the Azure Storage Account:

ova29

StorSimple Manager Services completes the following tasks:

ova30

 


Running Powershell script functions


Many of the scripts I write contain reusable code as functions. For example, the Merge-VMDisks.PS1 script contains Merge-VMDisks function. To use these functions, you must load them first into memory in the current Powershell session. Running the PS1 file will do just that; load the function in memory. It will NOT run the function.

Powershell stores a list of the currently available functions in the function: drive. To see available drives type:

Get-PSDrive

You will get a result similar to:

Function1To explore the contents of a PS drive, we can use the Get-Item cmdlet like:

Get-Item -Path function:

You will get a result similar to:

Function2In this example, to use the Merge-VMDisks function we need to load it into memory first in the current PS session by running the PS1 file:

E:\Install\Scripts\Merge-VMDisks.ps1
Get-Item -Path function:

Now running the Get-Item cmdlet shows 3 new functions loaded – that we got form the Merge-VMDisks.ps1 script:

Function3

Now that we have the function in memory, we can use it by invoking the function as we do any PS cmdlet. For example:

Merge-VMDisks -VMName ‘MyVM’

 

 

 


Powershell Script to move VHD(x) from one Hyper-V VM to another


This script will detach a VHD(x) disk from one Hyper-V VM and attach it to another. If the guest OS is Windows 2012 or above, this is safe to do directly (obviously not with system\boot partition). Older guest Windows OS’s will blue-screen if a disk is yanked without off-lining it first in the guest OS. The script can be downloaded from the Microsoft Script Center Repository.

For example:

Move-VHD -SourceVM vHost22 -TargetVM v-2012R2-G2a -VHDX ‘vHost01d(Web)-D.vhdx’ -Verbose

Will detach the VHDx disk ‘vHost01d(Web)-D.vhdx’ from vHost22 VM and attach it to v-2012R2-G2a VM

RegexSafe5

 This script uses the RegexSafe Powershell function described here.


Function/tool to return Regex-safe version of input string


Some of Powershell comparison operators use Regular Expressions, such as -match, -notmatch, and -replace operators. This poses a problem when trying to match against a string that contains Regex metacharacters. This function tools solves this issue by accepting an input string as input and returning a Regex-safe version of the same string where every Regex metacharacter in the input string is escaped.

The script can be downloaded from the Microsoft Script Center Repository. To use this function download it, unblock the file, and run it to load the function.

Example:

Imagine you wish to make a PS script to detach a VHD(X) disk from one Hyper-V VM and attach it to another. The script may start like this:

# Input:
$SourceVM = ‘v-2012R2-G2a’
$TargetVM = ‘vHost22’
$VHDX = ‘vHost01d(Web)-D.vhdx’

This next section will show current attached disks:

“Before:”
Get-VMHardDiskDrive -VMName $SourceVM
Get-VMHardDiskDrive -VMName $TargetVM

RegexSafe2

At this point, if we try to identify the disk that needs to be detached from one VM and attached to another using the input data:

Get-VMHardDiskDrive -VMName $SourceVM | Where { $_.Path -match $VHDX }

This cmdlet returns no matches. This is because the string we’re comparing to ‘vHost01d(Web)-D.vhdx’ contains 3 Regex metacharacters, namely ‘().’

This issue can be remedied by the use of this RegexSafe function:

Get-VMHardDiskDrive -VMName $SourceVM | Where { $_.Path -match (RegexSafe $VHDX) }

RegexSafe3

The full script to move a VHD(x) disk from one VM to another can be found here.


Get-VMMetering script to collect and reset VM Metering data, report to CSV


This script can be downloaded from the Microsoft Script Center Repository. It can be set as a scheduled task on one of the Hyper-V hosts in the environment, not all of them.

Set the schedule of the scheduled task to run as often as you’d like to have the VM metering data collected and reset.

Edit the top 3 lines to match your environment details:

  • $CSV = “d:\sandbox\MeteringReports”
    • Edit this line to enter the path to the folder to save CSV files. This can be a UNC path like “\\server\share\folder”
  • $HVHosts = @(“Host1″,”Host2”)
    • Edit this line to list Hyper-V hosts in your environment
  • $Sort = “AvgCPU”
    • Edit this line to change the report sort order. Options include: AvgCPU, AvgRAM, MaxRAM, MinRAM, TotalDisk, NetworkInbound, NetworkOutbound, VMName, ComputerName

Report data and output will look like:

Metering1


Powershell script to merge Hyper-V Virtual Machine disks


In some situations you might find a VM disk to be part of a series of differencing disks. Take this example:

Merge4

If this was the result of VM Checkpoints, the fix would be easy: simply delete the checkpoints which merges the disks. But his is not the case. Hyper-V Manager shows no checkpoints:

Merge9

Powershell confirms (notice no output):

Merge10

This script shuts down the VM and merges its disks. It uses the Get-ParentPath function.

This script can be downloaded from the Microsoft Script Center Repository.

To use this script, download it, run it as administrator, then use the function.

To see help:

Merge11

For example:
Merge-VMDisks -VMName ‘MyVM’
Merge1
This may take some time depending on disk sizes and underlying storage system speed.
Merge3
The script leaves a log file shows the same steps on the console.
This is the picture after the merge is done:
Merge5
Merge6
If the script is run on a VM that has no disks to be merged, no changes are made:
Merge8
The script prompts for confirmation before shutting down the VM:
Merge7
This can be bypassed by using the -Confirm parameter as shown above.
Script help output looks like:
NAME
    Merge-VMDisks
    
SYNOPSIS
    Function to merge VM disks
    
SYNTAX
    Merge-VMDisks [-VMName]  [[-LogFile] ] [-WhatIf] [-Confirm] []
    
DESCRIPTION
    Function/script to merge VM disks. The script will power down the VM in the process.

PARAMETERS
    -VMName 
        Name of the VM whose VHD(x) disks are to be merged
        
        Required?                    true
        Position?                    1
        Default value                
        Accept pipeline input?       true (ByValue, ByPropertyName)
        Accept wildcard characters?  false
        
    -LogFile 
        Name and path of the file where the script will log its steps and progress
        
        Required?                    false
        Position?                    2
        Default value                ".\Merge-VMDisks_$(Get-Date -format yyyyMMdd_hhmmsstt).txt"
        Accept pipeline input?       false
        Accept wildcard characters?  false
        
    -WhatIf []
        
        Required?                    false
        Position?                    named
        Default value                
        Accept pipeline input?       false
        Accept wildcard characters?  false
        
    -Confirm []
        
        Required?                    false
        Position?                    named
        Default value                
        Accept pipeline input?       false
        Accept wildcard characters?  false
        
    
        This cmdlet supports the common parameters: Verbose, Debug,
        ErrorAction, ErrorVariable, WarningAction, WarningVariable,
        OutBuffer, PipelineVariable, and OutVariable. For more information, see 
        about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 
    
NOTES
    
        Function by Sam Boutros
        v1.0 - 11/01/2014
    
    -------------------------- EXAMPLE 1 --------------------------
    
    C:\PS>Merge-VMDisks -VMName 'v-2012R2-VBR1'
    
RELATED LINKS
    https://superwidgets.wordpress.com/category/powershell/


Powershell script to get parent disk/path tree of VHD(x) file


In some situations you might find a VM disk to be part of a series of differencing disks. Take this example:

PPath1

If this was the result of VM Checkpoints, the fix would be easy: simply delete the checkpoints which merges the disks. But his is not the case. Hyper-V Manager shows no checkpoints:

PPath2

Powershell confirms (notice no output):

PPath3

This script is the first step to a fix. It lists the disk parent tree. The script can be downloaded from the Microsoft Script Center Repository.

To use this script, download it, run it as administrator, then use the function. To see help:

PPath5

You will see output like:

NAME
 Get-ParentPath
 
SYNOPSIS
 Function to get parent disk/path tree of VHD(x) file
 
SYNTAX
 Get-ParentPath [-VHDPath] <String> [[-ComputerName] <String>] [-WhatIf] [-Confirm] 
[<CommonParameters>]
 
DESCRIPTION
 Function to get parent disk/path tree of VHD(x) file
 
PARAMETERS
 -VHDPath <String>
 Full path to the VHD(x) file.
 For example: 
"I:\VMs\v-2012R2-G2a\v-2012R2-G2a-C_55DB25B0-EFA9-415F-A5D1-738A62742B4E.avhdx"
 
 Required? true
 Position? 1
 Default value 
 Accept pipeline input? true (ByValue, ByPropertyName)
 Accept wildcard characters? false
 
 -ComputerName <String>
 Name of Hyper-V host where the VHD(x) file resides
 If absent, defaults to localhost
 
 Required? false
 Position? 2
 Default value .
 Accept pipeline input? false
 Accept wildcard characters? false
 
 -WhatIf [<SwitchParameter>]
 
 Required? false
 Position? named
 Default value 
 Accept pipeline input? false
 Accept wildcard characters? false
 
 -Confirm [<SwitchParameter>]
 
 Required? false
 Position? named
 Default value 
 Accept pipeline input? false
 Accept wildcard characters? false
 
 <CommonParameters>
 This cmdlet supports the common parameters: Verbose, Debug,
 ErrorAction, ErrorVariable, WarningAction, WarningVariable,
 OutBuffer, PipelineVariable, and OutVariable. For more information, see 
 about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 
 
INPUTS
 
OUTPUTS
 
NOTES
 Function by Sam Boutros
 v1.0 - 11/01/2014
 
 -------------------------- EXAMPLE 1 --------------------------
 
 Get-ParentPath -VHDPath 
"I:\VMs\v-2012R2-G2a\v-2012R2-G2a-C_55DB25B0-EFA9-415F-A5D1-738A62742B4E.avhdx" 
-ComputerName "xhost16"
 
 Retunrs an array of the disk path and all its parents paths
 
 -------------------------- EXAMPLE 2 --------------------------
 
 $VMName = "v-2012R2-G2a"
 $HVName = "xHost16"
 $VMDisks=Invoke-Command -ComputerName $HVName -ArgumentList $VMName -ScriptBlock { 
     Param($VMName)
     Get-VMHardDiskDrive -VMName $VMName
 }
 ($VMDisks.Path | Where { $_ -match ":" }) | % {
     Get-ParentPath -VHDPath $_ -ComputerName $HVName
 }
 
 Retunrs an array for each disk attached to the VM $VMName, containing the disk tree.

 Sample output:
 I:\VMs\v-2012R2-G2a\v-2012R2-G2a-C_55DB25B0-EFA9-415F-A5D1-738A62742B4E.avhdx
 I:\VMs\v-2012R2-G2a\v-2012R2-G2a-C_0020A6D3-0371-48E3-B67D-DE2ADF0BEDF1.avhdx
 I:\VMs\v-2012R2-G2a\v-2012R2-G2a-C_C2BA8DE5-8FE6-49AD-B12B-789853306524.avhdx
 I:\VMs\v-2012R2-G2a\v-2012R2-G2a-C_79E7AFEB-F867-4068-A3DA-6BF64F49E819.avhdx
 I:\VMs\v-2012R2-G2a\v-2012R2-G2a-C_232D8FD8-5855-4518-800C-2659385521FA.avhdx
 I:\VMs\v-2012R2-G2a\v-2012R2-G2a-C.VHDX
 I:\VMs\v-2012R2-G2a\v-2012R2-G2a-D_C492420D-011D-42F4-862A-A04A7222B7FC.avhdx
 I:\VMs\v-2012R2-G2a\v-2012R2-G2a-D_7B0A54C4-36E5-4229-9746-49566B0566AF.avhdx
 I:\VMs\v-2012R2-G2a\v-2012R2-G2a-D_460EDAAF-F30A-4744-8396-87449EAF1A8C.avhdx
 I:\VMs\v-2012R2-G2a\v-2012R2-G2a-D_9D3805B2-79F5-4E5F-865D-D69620E31B6A.avhdx
 I:\VMs\v-2012R2-G2a\v-2012R2-G2a-D_F37513BE-AD00-41FD-B24E-CBB3E0BDEFC4.avhdx
 I:\VMs\v-2012R2-G2a\v-2012R2-G2a-D.vhdx
 
RELATED LINKS
 https://superwidgets.wordpress.com/category/powershell/

Powershell script/function to expand system/boot disk on Windows XP/2003 VMs


In Windows 7 and Server 2008 virtual machines and above, expanding the boot/system disk is a simple matter of expanding it in the hypervisor, then expanding it in the guest OS in the Computer Management/Disk Management GUI. In Windows XP/Server 2003 guest VMs, expanding the boot/dystem disk is not available via native Windows tools.

This script leverages Server 2012 R2 hypervisor capabilities to expand boot/system disk on a guest VM running Windows XP/2003 OS. The script leaves a log file behind listing steps taken. The script can be downloaded from the Microsoft Script Center Repository.

To use it: Download the attached file, unblock it, adjust PS execution policy as needed, run the script to load the function in memory, then use this line to get detailed help and examples as shown below:

expand1

Note: The script will shutdown the VM during this process.

For example, if you down the VM, and expand the disk in Hyper-V Manager GUI:

Diskc10

In the VM, you cannot expand the boot/system partition with native Windows 2003/XP tools:

Diskc11

You can do that with this script. On the Hyper-V host where the VM is running, run:

Expand-C -VMName MyVM1 -Size 17GB -BackupPath "d:\save"

The script will

  • Backup the VHDX file before expanding it if the ‘BackupPath’ is used
  • Convert the file from VHD to VHDX format if it was a VHD file. In this case you’ll need to delete the old .vhd file manually.
    Diskc3
  • Down the VM (gracefully)
    Diskc7
  • Expand the VHDX file
  • Expand the partition
  • Re-attach the C: drive disk file to the VM
  • Start the VM Diskc8
  • Leave a log file listing the steps taken Diskc9

 

 


Windows 10 Technical Preview – Hyper-V Integration


After installing Windows 10 Technical Preview on Windows Server 2012 R2, I checked the integration service. In Hyper-V Manager on the 2012 R2 host, all looked normal:

Win10a29

Running the following Powershell command on the 2012 R2 Hyper-V server showed that the Windows 10 Technical Preview VM comes with Integration Service version 6.4.9841

Win10a28

 

This command shows more details:

Win10a30

Running this comparison between Integration services for the this Windows 10 VM and a Server 2012 R2 VM:

Compare-Object -ReferenceObject (Get-VMIntegrationService -VMName v-Win10a | select *) -DifferenceObject (Get-VMIntegrationService -VMName v-2012R2-G2a | select *)

showed no difference (This does not show or compare integration service version.)


Create simultaneous checkpoints of a group of related Virtual Machines


In some cases you may need to checkpoint a group of related VMs at exactly the time, such as a SharePoint farm, or a multi-tiered application. The process includes pausing, saving the VMs, creating checkpoints, restrating, and eventually restoring back to original state. Powershell can help automate the process:

1. Pause and Save:

# Input
$HVHost = “xHost16”
$VMs = “SSTest1″,”V-2012R2-Test1″,”v-2012R2-TW01”

# Pause and Save
Stop-VM -Name $VMs -Save
# Confirm
Get-VM -ComputerName $HVHost -Name $VMs | Select VMName,State,ComputerName | FT -AutoSize

SimulCheck1

2. Checkpoint:

# Checkpoint
Checkpoint-VM -ComputerName $HVHost -Name $VMs
# Confirm
Get-VMSnapshot -ComputerName $HVHost -VMName $VMs | Select VMName, Name, ComputerName | FT -AutoSize

SimulCheck2

3. Restart:

# Restart
Start-VM -ComputerName $HVHost -Name $VMs
# Confirm
Get-VM -ComputerName $HVHost -Name $VMs | Select VMName, State, ComputerName | FT -AutoSize

SimulCheck3

Eventually, when it’s time to restore the group of VMs to their original state:

4. Remove all checkpoints:

# Later on, to remove all checkpoints:
Remove-VMSnapshot -ComputerName $HVHost -VMName $VMs -IncludeAllChildSnapshots
# Confirm
Get-VMSnapshot -ComputerName $HVHost -VMName $VMs | Select VMName, Name, ComputerName | FT -AutoSize

< no output>..

SimulCheck4


Hyper-V Virtual Machine checkpoints


In Windows Server 2012 R2 a VM checkpoint in Hyper-V captures a point in time state of a virtual machine’s memory, CPU, system state, and disk contents.

Checkpoints were called VM Snapshots in Server 2012 but that was confusing because it was too close to VSS volume snapshots for example, and it was also known as Checkpoint in VMM.

When a checkpoint is invoked, a .avhd file is created for each of the VM’s .vhd(x) files, and the .vhd(x) files becomes read-only. All changes are then written to the .avhd files preserving the state of the .vhd(x) files at the point of creating the checkpoint. If the VM attempts to access a file, Hyper-V will look for it in the .avhd file first, if not found, it will look for the parent .vhd file. This causes a performance degradation particularly if a number of nested checkpoints are created like:

VSS6

In this example, The disk files can be observed in the VM folder:

VSS8

where all the files are read-only except the latest .avhd file at the bottom. Only one checkpoint .avhd file is read-write at any given point in time. Each checkpoint has 1 parent check point. In Powershell, we can run the cmdlet:

Get-VMSnapshot -VMName vHost17

to identify each checkpoint’s parent checkpoint:

VSS7

Removing a checkpoint merges its content (blocks) with its parent checkpoint. Checkpoints do not have to be removed in order. In this example, we can remove the 7:37:31 checkpoint using this Powershell cmdlet or from the Hyper-V Manager GUI:

Remove-VMSnapshot -VMName vHost17 -Name “vHost17 – (9/21/2014 – 7:37:31 PM)”

Hyper-V will merge the 7:37:31 checkpoint blocks with its parent RW checkpoint (7:37:43):

VSS9

VSS10

The entire tree of checkpoints can be deleted in one step by right clicking on the top checkpoint in Hyper-V Manager, and clicking ‘Delete Checkpoint Subtree’.

A checkpoint can be exported using the Export-VMSnapshot cmdlet. The resulting .vhd(x) file(s) can be used to create a clone of the original VM.

A checkpoint can be renamed in either Hyper-V Manager GUI or via Powershell cmdlet Rename-VMSnapshot.

A checkpoint can be applied (restored). This reverts the VM back to the point in time where the checkpoint was taken.

 

 


Setting up Veeam 8 Cloud Connect on Azure


High level summary:

  1. Provision Azure VM with sufficient CPU cores, memory, and disk space.
  2. Configure Azure Storage account, and disk space on the VM for use as a Backup Repository and Global Deduplication Cache.
  3. Configure an End Point to allow Cloud Connect tenants access to the VM
  4. Install Veeam Backup and Replication 8 on the VM with additional Cloud Connect License
  5. Configure Veeam on the VM to act as Cloud Connect Gateway, WAN Accelerator, and house a Backup Repository in Azure blob storage.
  6. On the tenant side, add and configure a Service Provider, setup and run a backup copy job using the Cloud Repository as backup target.

 1. Setup a Cloud Service:

VeeamCC02

In planning this deployment, select a region that’s geographically close to to your data center to have lowest latency.

2. Setup a Storage account:

VeeamCC04

Notes:

  • Storage account must be in the same region as the Cloud Service.
  • Geo-redundant replication will maintain 6 copies of the data in 2 geographically distant Azure data centers. This is the default, and can be changed later.
  • Locally redundant replication will maintain 3 copies of the data in a single Azure data center. This costs 1/2 as much as geo-redundant replication, and provides twice the bandwidth.
  • A Storage account has a 500TB maximum capacity.

3. Setup a Container under the Storage account:

Under Storage, select your Storage account, click the Containers link on top, then click Add at the bottom:

VeeamCC05b

Containers are similar to file system folders.

4. Create a virtual machine from Gallery using the Server 2012 R2 Data Center image:

VeeamCC03

Configure as Basic A2 size. This size has 2 CPU cores, 3.5GB of memory, and can have a maximum of 4x 1TB disks in addition to the 127 GB boot disk and a 60 GB temporary disk.

AzureMVsFor Azure VM pricing details see this link.

VeeamCC01Configure the VM to use the Cloud Service and Storage account we created earlier:

VeeamCC06b

5. Get the files needed to the new VM:

Once Azure is finished provisioning the new VM, click Connect at the bottom to connect to the new Azure VM via RDP. Enter the name and password used during the VM setup above.

I have prepared an Azure SMB share as shown in this post, and stored a number of files in it that we’ll need:

VeeamCC08

I will leverage that share and map a drive on the new Azure Veeam VM using this short script:

$Drive = net use * \\share01.file.core.windows.net\azureshare01 /u:share01 o73afb5eWZkhaaaatwHMus2wsxApQ==
if (-not (Test-Path -Path “c:\sandbox\Backup&Replication.8.0.0.592.BETA2.iso”)) {
    New-Item -Path “c:\Sandbox” -ItemType Directory -ErrorAction SilentlyContinue
    Copy-Item -Path “$($Drive[0].Split(“:”)[0].substring(6,1)):\Tools\Veeam 8 Beta 2\Backup&Replication.8.0.0.592.BETA2.iso” -Destination “c:\sandbox” -Force
}
Mount-DiskImage -ImagePath “c:\sandbox\Backup&Replication.8.0.0.592.BETA2.iso”

This maps a drive to the Azure share, copies the Veeam 8 iso to c:\sandbox on the VM, and mounts the iso:

VeeamCC07

These 2 drive mappings are not persistent (will not survive a VM reboot). This is OK since we only need them during setup.

6. Setup a persistent drive mapping to your Azure Storage account:

There’s a number of ways to make Azure storage available to the VM:

  • Attach a number of local VHD disks. The problem with this approach is that the maximum we can use is 16TB, and we’ll have to use an expensive A4 sized VM.
  • Attach a number of Azure File shares. There’s a number of issues with this approach:
    The shares are not persistent although we can use CMDKEY tool as a workaround.
    There’s a maximum of 5TB capacity per share, and a maximum of 1TB capacity per file.
  • Use a 3rd party tool such as Cloudberry Drive to make Azure block blob storage available to the Azure VM. This approach has the 500TB Storage account limit which is adequate for use with Veeam Cloud Connect. Microsoft suggests that the maximum NTFS volume size is between 16TB and 256TB on Server 2012 R2 depending on allocation unit size. Using this tool we get 128TB disk suggesting an allocation unit size of 32KB.

I’ve examined these 10 different tools and in my testing Cloudberry Drive provided the most functionality. To install it:


11/6/2014:

Veeam has released Veeam v8 today, so I can make this post public.

CloudBerry Drive has proved to be not a good fit for use with Veeam Cloud Connect because it caches files locally. For more details see this post. So, I recommend skipping CloudConnect installation and simply attach up to 16x 1TB drives to the Azure VM (may need to change VM size all the way up to Standard A4 to get the maximum of 16 disks), and set them up as a simple disk in the VM using Storage Spaces)


– Install C++ 2010 x64 Redistributable pre-requisite:

VeeamCC09

– Run CloudBerryDriveSetup, accept the defaults, and reboot. After reboot, run this command to mount the Veeam iso back:

Mount-DiskImage -ImagePath “c:\sandbox\Backup&Replication.8.0.0.592.BETA2.iso”

– In the Azure Management Portal, obtain your storage account access key (either one is fine):

VeeamCC11

– Back in the Azure VM, right-click on the Cloudberry icon in the system tray and select Options:

VeeamCC10

– Under the Storage Accounts tab, click Add, pick Azure Blob as your Storage Provider, enter your Azure Storage account name and key:

VeeamCC12

– Under the Mapped Drives tab, click Add, type-in a volume label, click the button next to Path, and pick a Container. This is the container we created in step 3 above:

VeeamCC13

– You can see the available volumes in Windows explorer or by running this command in Powershell:

Get-Volume | FT -AutoSize

VeeamCC14

7. Add VHD disks to the VM for the Veeam Global deduplication cache:

We will be setting up Veeam’s WAN Accelerator for Global Deduplication. This uses a folder for global deduplication cache. We’ll add VHD disks to the VM for that cache folder to have sufficient disk space and IOPS for the cache.

VeeamCC27

Highlight the Azure Veeam VM, click Attach at the bottom, and click Attach empty disk. Enter a name for the disk VHD file, and a size. The maximum size allowed is 1023 GB (as of September 2014). Repeat this process to add as many disks as allowed by your VM size. For example, an A1 VM can have a maximum of 2 disks, A2 max is 4, A3 max is 8, and A4 max is 16 disks.

In the Azure Veeam VM, I created a 2TB disk using Storage Spaces on the VM as shown:

VeeamCC28

This is setup as a simple disk for maximum disk space and IOPS, but it can be setup as mirrored disks as well.

8. Install Veeam prerequisites:

9. Install Veeam 8 Backup and Replication:

If you’re using a VM smaller than A2 with less than 2 CPU core, you’ll receive a warning during Veeam installation. This is safe to ignore.

Select to install the Veeam Powershell SDK

Accept the default installation location under c:\program files\Veeam\backup and replication

Click “Do not use defaults and configure product manually”

VeeamCC15

Change location of the Guest Catalog folder and vPower cache folder:

VeeamCC16

Veeam will automatically install SQL 2012 SP1 express on the VM:

VeeamCC18

10. Add an endpoint to the VM for TCP port 6180:

While Veeam is installing on the VM, let’s add an endpoint for Veeam Cloud Connect. In the Azure Management Portal, click on the VM, click Endpoints, and click Add at the bottom. Add a Stand Alone Endpoint:

VeeamCC17

Note that endpoint name follows the NetBIOS naming convention and cannot exceed 15 characters.

11. Veeam initial configuration:

Back in the VM, open Veeam Backup and Replication 8. Under Backup Infrastructure we need to see the Backup Repositories and WAN Accelerators nodes on the left:

VeeamCC21

However, these will be hidden in the GUI by design since we have not added any Hyper-V or VMWare server. To work around this issue we can run this SQL query to show the needed options in the GUI:

IF NOT EXISTS (SELECT * FROM [dbo].[Options] WHERE id = ’91BF2EB1-51AC-4C75-A472-22610288191D’)
BEGIN
INSERT INTO [dbo].[Options]
([id]
,[name]
,[value])
VALUES
(’91BF2EB1-51AC-4C75-A472-22610288191D’
,’WasViHostEverAdded’
,’True’)
END
ELSE
BEGIN
UPDATE [dbo].[Options] SET
[value] = ‘True’
WHERE
[id] = ’91BF2EB1-51AC-4C75-A472-22610288191D’

END
GO

IF NOT EXISTS (SELECT * FROM [dbo].[Options] WHERE id = ‘6B5FDC9C-6E1D-4533-B17C-5FECC304589F’)
BEGIN
INSERT INTO [dbo].[Options]
([id]
,[name]
,[value])
VALUES
(‘6B5FDC9C-6E1D-4533-B17C-5FECC304589F’
,’WasAnyHostEverAdded’
,’True’)
END
ELSE
BEGIN
UPDATE [dbo].[Options] SET
[value] = ‘True’
WHERE
[id] = ‘6B5FDC9C-6E1D-4533-B17C-5FECC304589F’
END
GO

Copy this query and in notepad save it as c:\sandbox\Show-UI.sql for example on the Azure Veeam VM. Then run this command:

SQLCMD.EXE -S localhost\VEEAMSQL2012 -d VeeamBackup -i c:\sandbox\Show-UI.sql -o c:\sandbox\Show-UI.log

Thanks to Veeam phenomenal support for the tip. Their quick response was very helpful.

12. Add a Backup Repository:

In Veeam Backup and Replication, click WAN Accelerators, then click Add WAN Accelerator:

VeeamCC23

Give it a name, select Shared Folder:

VeeamCC24

This is necessary as opposed to the first option for directly attached storage, because of the way CloudBerry presents the attached Azure blob storage.

Type in the Shared Folder name, enter credentials to access it. To get the share name you can run “net use” command to see its exact path.

VeeamCC25

Click Next:

VeeamCC26

Accept vPower NFS defaults, and finish.

13. Add a WAN Accelerator:

In Veeam Backup and Replication, click WAN Accelerators, then click Add WAN Accelerator:

VeeamCC22

Select the e: drive we created in step 7 above, enter the maximum amount of disk space available, and finish:

VeeamCC29

14. Add a certificate:

This is a one time setup. SSL certificate is needed for authentication and tunnel encryption.

Note: This step requires Veeam Cloud Connect license. Without it, the Cloud Connect Infrastructure will be hidden in the Veeam Backup and Replication 8 GUI.

VeeamCC31

For production I recommend using a certificate from a public Certificate Authority. For this exercise I will generate a self signed certificate. In Cloud Connect Infrastructure, click Manage Certificates:

VeeamCC32

Click Generate new certificate

VeeamCC33

Type in a friendly name

VeeamCC34

Click “Copy to clipboard” and save this information. We will need the thumbprint when connecting from the client/tenant side. This is only needed because we’re using a self signed certificate. If we used a certificate issued by a public Certificate Authority we would not need that thumbprint.

15. Add Cloud Gateway:

This is also a one time step. Under Cloud Connect Infrastructure, click Add Cloud Gateway:

VeeamCC35

Pick a server,

VeeamCC46

Use the Public IP of the Azure VM and the default port 6180.

Select its NIC,

VeeamCC37

and Finish.

16. Add a user/tenant:

A user may represent a Cloud Connect client/tenant or a corporate site. It is associated with his/her own repository under the main repository, and a lease. The lease corresponds to a backup client/backup cloud provider agreement term.

Under Cloud Connect Infrastructure, click Add User

VeeamCC38

Enter a name, create a password, check Lease expires, and click Calendar to select a lease expiration date.

VeeamCC39

In the Resources tab, click Add, create a name for the user/client repository name, select a Backup Repository from the drop down menu, check to Enable WAN acceleration, and pick the WAN accelerator from its drop down menu.


From the client/corporate side, in Veeam Backup and Replication 8, under Backup Infrastructure, click the Service Providers node, and click Add a Service Provider:

VeeamCC40

Enter the IP address or DNS name of the Azure Veeam VM we created above, and click Next:

VeeamCC41

Since we used a self-signed certificate, we need to provide the thumbprint from step 14 above. Click Verify:

VeeamCC42

Notice that the certificate has been validated. The certificate will be used for both authentication and tunnel encryption. Click Add and add the user name and password created in step 16 above:

VeeamCC43

Click Next, and Finish.

Finally, create a new backup copy job using the Cloud Repository as a backup target:

Veeam8b


Powershell Function to get Hyper-V host networking configuration


This function generates a txt report on one or more Hyper-V hosts’ networking configuration. It’s a useful tool when troubleshooting issues that relate to VM live-migration, VM replication and similar issues. It can be downloaded from the Microsoft Script Center Repository.

To get help for the function type in:

help Get-HVNetworking -full

You will see output similar to:

 .Synopsis 
  Function to get Hyper-V host networking configuration 
  
 .Description 
  Function generates report in txt format 
  The function will skip computers that don't have Hyper-V role installed 
 
 .Parameter ComputerName 
  Name(s) of the Hyper-V host(s) to report on 
  
 .Parameter ReportFile 
  File name to save the resulting report to.  
  Example: "c:\reports\Hyper-V_Networking.txt" 
  If absent, the resulting report is saved to a text file in the current folder. 
 
 .Example 
  Get-HVNetworking -ComputerName "Host1" 
  This example reports on the Hyper-V host "Host1" 
 
 .Example 
  Get-HVNetworking "Host1","Host2","Host3" -Verbose 
  This example reports on the Hyper-V hosts "Host1","Host2","Host3" 
  and displays results to the screen as well. 
 
 .Example 
  Get-ADComputer -Filter * | Select name | foreach-Object { Get-HVNetworking $_.name ".\Domain-HVNetworkingReport.txt" -Verbose } 
  This example goes through all computers in the domain  
  and reports on the ones that have Hyper-V role installled  
  and saves all gathered data into a single report 
 
 .Link 
  http://superwidgets.wordpress.com/category/powershell/ 
  
 .Notes 
  Function by Sam Boutros 
  v1.0 - 08/29/2014 
  Possible future updates: 
    Select specific properties of interest instead of returning all properties 
    Return selected properties as a PSObject  
 

New ‘Get-SBIPInfo’ function added to SBTools module retrieves computer IPv4 and IPv6 information


SBTools module can be downloaded from the Microsoft Script Center Repository.

To install it, extract the .rar file, and run install-SBTools.ps1 in the folder where you extracted the .rar file.

The Get-SBIPInfo function will retrieve computer IP information for one or more computers.

Sample output:

get-sbipinfo1

NAME
Get-SBIPInfo

SYNOPSIS
Function to get computer IP information.

SYNTAX
Get-SBIPInfo [[-ComputerName] <String[]>] [-WhatIf] [-Confirm] [<CommonParameters>]

DESCRIPTION
Function to get computer IP information.
Function returns an object that has the following properties:
ComputerName, AdapterDescription, IPAddress, IPVersion, SubnetMask, CIDR, MAC, DefaultGateway, DNSServer

PARAMETERS
-ComputerName <String[]>
Name(s) of the computer(s) to be used to get their IP information.

Required? false
Position? 1
Default value $env:COMPUTERNAME
Accept pipeline input? true (ByValue, ByPropertyName)
Accept wildcard characters? false

-WhatIf [<SwitchParameter>]

Required? false
Position? named
Default value
Accept pipeline input? false
Accept wildcard characters? false

-Confirm [<SwitchParameter>]

Required? false
Position? named
Default value
Accept pipeline input? false
Accept wildcard characters? false

<CommonParameters>
This cmdlet supports the common parameters: Verbose, Debug,
ErrorAction, ErrorVariable, WarningAction, WarningVariable,
OutBuffer, PipelineVariable, and OutVariable. For more information, see
about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).

INPUTS
System.String[]

OUTPUTS
System.Object

NOTES
Function by Sam Boutros
V 1.0
08/12/2014

————————– EXAMPLE 1 ————————–

C:\PS>Get-SBIPInfo

This example retuns the current computer IP information

————————– EXAMPLE 2 ————————–

C:\PS>Get-SBIPInfo xhost11 | Out-GridView

This example displays IP information of computer xHost11

————————– EXAMPLE 3 ————————–

C:\PS>Get-Content .\computers.txt | Get-SBIPInfo

This example returns IP information of every computer listed in the computers.txt file

————————– EXAMPLE 4 ————————–

C:\PS>Get-SBIPInfo | Where-Object { $_.IPversion -eq 4 } | Select-Object { $_.IPAddress }

This example lists the IPv4 address(es) of the local computer


New ‘ Test-SBVHDIntegrity’ function added to SBTools module tests VM VHD(x) files’ integrity


SBTools module can be downloaded from the Microsoft Script Center Repository.

To install it, extract the .rar file, and run install-SBTools.ps1 in the folder where you extracted the .rar file.

The Test-SBVHDIntegrity function will test the drive files of a Hyper-V virtual machine and verify the specified file exists and that there are no problems with it.

This is a function by Jeff Hicks originally published here, modified by Sam Boutros 08/09/2014, added functionality to work on VMs from other than localhost.

NAME
Test-SBVHDIntegrity

SYNOPSIS
Test VHD files for integrity

SYNTAX
Test-SBVHDIntegrity [-VM] <Object[]> [-WhatIf] [-Confirm] [<CommonParameters>]

DESCRIPTION
Test the drive files for a Hyper-V virtual machine and verify the specified
file exists and that there are no problems with it.

PARAMETERS
-VM <Object[]>
VM object. Function will check integrity of input VM disk files.

Required? true
Position? 1
Default value
Accept pipeline input? true (ByValue, ByPropertyName)
Accept wildcard characters? false

-WhatIf [<SwitchParameter>]

Required? false
Position? named
Default value
Accept pipeline input? false
Accept wildcard characters? false

-Confirm [<SwitchParameter>]

Required? false
Position? named
Default value
Accept pipeline input? false
Accept wildcard characters? false

<CommonParameters>
This cmdlet supports the common parameters: Verbose, Debug,
ErrorAction, ErrorVariable, WarningAction, WarningVariable,
OutBuffer, PipelineVariable, and OutVariable. For more information, see
about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).

————————– EXAMPLE 1 ————————–

C:\PS>Get-VM | Test-SBVHDIntegrity | Out-Gridview

————————– EXAMPLE 2 ————————–

C:\PS>Get-VM -ComputerName xHost11,xHost12 | Test-SBVHDIntegrity | Out-Gridview

This example displays disk integrity results for each VM on the Hyper-V hosts xHost11 and xHost12

————————– EXAMPLE 3 ————————–

C:\PS>Get-VM -ComputerName (Get-Content .\computers.txt) | Test-SBVHDIntegrity | Out-Gridview

This example displays disk integrity results for each VM on the Hyper-V hosts listed n the .\computers.txt file

————————– EXAMPLE 4 ————————–

C:\PS>Get-VM | Test-SBVHDIntegrity | where {(-NOT $_.TestPath) -OR (-NOT $_.TestVHD)}

This examples displays disks that fail either the TestPath or TestVHD checks


SBTools module, adds function to get VM’s VHD file path


You may need to track the location of Hyper-V virtual machines’ VHD files. This may be important to identify the storage platform where a particular VM drive is located, which is in turn important in troubleshooting performance and disk IO issues.

To use this function, download SBTools.rar from the Microsoft Script Center Repository and run .\install-SBTools.ps1

The difficulty in identifying where a VM drive resides physically lies in the fact that VM drives are referred to differently from the VM and its host’s prospectives. This module includes a function; Get-SBVHD that retrieves a VM’s drive VHD file path. For example, consider this VM:

SBTools01

It has a total of 7 disks: 3 attached to 2 different IDE controllers, and 4 attached to 2 different SCSI controllers.

From the Hyper-V host’s prospective the 7 disks look like:

From the host’s prospective
ControllerType ControllerNumber ControllerLocation
ide 0 0
ide 0 1
ide 1 1
scsi 0 0
scsi 0 1
scsi 0 2
scsi 1 0

However, from the guest virtual machine’s prospective the 7 disks are identified as:

From the Guest’s prospective
Controller DiskNumber
ide 0
ide 1
ide 2
scsi 3
scsi 4
scsi 5
scsi 6

The host can tell us the VHD path to the VM disk presented in SCSI controller 0 location 1 for example, but it’s unaware of what’s on the disk in terms of partitions, and volumes.

The guest can tell us the volumes on a particular partition and the partitions on a particular disk, but it’s unaware of the VHD file path that represents this disk.

To add another wrinkle, starting with a guest VM’s drive letter, a volume has no information on what partition it resides on. Also, a partition has no information on what disk it resides on.

For example:

(get-volume -DriveLetter d) | Select-Object *

returns output similar to:

HealthStatus : Healthy
DriveType : Fixed
DriveLetter : D
FileSystem : NTFS
FileSystemLabel :
ObjectId : \\?\Volume{6e7e57fb-e9c7-11e3-80bd-00155d65010c}\
Path : \\?\Volume{6e7e57fb-e9c7-11e3-80bd-00155d65010c}\
Size : 107372081152
SizeRemaining : 94993174528
PSComputerName :
CimClass : ROOT/Microsoft/Windows/Storage:MSFT_Volume
CimInstanceProperties : {DriveLetter, DriveType, FileSystem, FileSystemLabel…}
CimSystemProperties : Microsoft.Management.Infrastructure.CimSystemProperties

Nothing here tells me what partition this volume resides on.

Using WMI class directly does not provide the needed information:

(Get-WmiObject -Class Win32_Volume -Filter “DriveLetter = ‘d:'”) | Select-Object *

returns more information about the volume:

PSComputerName : CM01
__GENUS : 2
__CLASS : Win32_Volume
__SUPERCLASS : CIM_StorageVolume
__DYNASTY : CIM_ManagedSystemElement
__RELPATH : Win32_Volume.DeviceID=”\\\\?\\Volume{6e7e57fb-e9c7-11e3-80bd-00155d65010c}\\”
__PROPERTY_COUNT : 44
__DERIVATION : {CIM_StorageVolume, CIM_StorageExtent, CIM_LogicalDevice, CIM_LogicalElement…}
__SERVER : CM01
__NAMESPACE : root\cimv2
__PATH : \\CM01\root\cimv2:Win32_Volume.DeviceID=”\\\\?\\Volume{6e7e57fb-e9c7-11e3-80bd-00155d65010c}\\”
Access :
Automount : True
Availability :
BlockSize : 4096
BootVolume : False
Capacity : 107372081152
Caption : D:\
Compressed : False
ConfigManagerErrorCode :
ConfigManagerUserConfig :
CreationClassName :
Description :
DeviceID : \\?\Volume{6e7e57fb-e9c7-11e3-80bd-00155d65010c}\
DirtyBitSet : False
DriveLetter : D:
DriveType : 3
ErrorCleared :
ErrorDescription :
ErrorMethodology :
FileSystem : NTFS
FreeSpace : 94993149952
IndexingEnabled : True
InstallDate :
Label :
LastErrorCode :
MaximumFileNameLength : 255
Name : D:\
NumberOfBlocks :
PageFilePresent : False
PNPDeviceID :
PowerManagementCapabilities :
PowerManagementSupported :
Purpose :
QuotasEnabled : False
QuotasIncomplete : False
QuotasRebuilding : False
SerialNumber : 950910896
Status :
StatusInfo :
SupportsDiskQuotas : True
SupportsFileBasedCompression : True
SystemCreationClassName :
SystemName : CM01
SystemVolume : False
Scope : System.Management.ManagementScope
Path : \\CM01\root\cimv2:Win32_Volume.DeviceID=”\\\\?\\Volume{6e7e57fb-e9c7-11e3-80bd-00155d65010c}\\”
Options : System.Management.ObjectGetOptions
ClassPath : \\CM01\root\cimv2:Win32_Volume
Properties : {Access, Automount, Availability, BlockSize…}
SystemProperties : {__GENUS, __CLASS, __SUPERCLASS, __DYNASTY…}
Qualifiers : {dynamic, locale, provider}
Site :
Container :

but nothing about the partition on which this volume resides.

The Get-SBVHD function in this module identifies the VHD file path of a given drive on a given VM.

to see more details type in

help Get-SBVHD -Full

 


All about time


timeIn a post in the Powershell Q&A forum, Tim Warner wrote:

Who remembers systeminfo? I liked to use systeminfo | more on my Windows XP and Win 7 systems to get the boot datetime, but Microsoft appears to have stripped the property in Windows 8 and Windows Server 2012. At any rate, it’s not what I want. :)

What would you say is the most efficient way in Windows PowerShell v3 or later to get not the boot time but the elapsed uptime of the box in an eyeball-friendly format?

Ultimately, I’d like to add this function to my profile script so I see the info at-a-glance every time I start the console. I’d like to see output that is similar to the following:

Uptime: 8 days, 12 hours, 36 minutes

I thought sure that should be easy via querying WMI from Powershell. Then Dave Wyatt  added:

Windows 8 will throw you all off, though. By default, when you “Shut down” a Windows 8 computer, you’re actually going into a sleep / hibernate state, and waking up from that doesn’t reset the WMI LastBootUpTime value (but a reboot does; go figure.) You can figure out the last “boot” time on Windows 8 by searching the event log, though.

Which got me thinking, with Windows 8 / Server 2012 and above we may not be getting uptime by querying WMI, so I looked into different ways to get computer uptime and wrote this script which can be downloaded from the Microsoft Script Center Repository.

Script output looks like:

time2

This script shows different ways to get and display computer uptime.  The script saves output to a log file in the folder where it runs. Log file name can be modified by editing the $LogFile variable.

The script gets uptime from:

  1. The VM’s Hyper-V host if the computer is a virtual machine
  2. Systeminfo
  3. Net statistics
  4. Event Log
  5. Win32_OperatingSystem class
  6. Win32_PerfFormattedData_PerfOS_System class (pointed out by Vern Anderson)

8/1/2014 – V.10


Get-Busy.ps1 powershell script to create files on many PCs and collect metrics


This script uses Busy.ps1 which is a script that I posted earlier. This script can be downloaded from the Microsoft TechNet Gallery. To use this script you need to edit the 4 data entry lines on top:

GetBusy

  • $WorkFolder = “e:\support” # Folder on each VM where test files will be created
  • $MaxSpaceToUseOnDisk = 20GB # Maximum amount of disk space to be used on each VM’s $WorkFolder during testing
  • $VMPrefix = “V-2012R2-LAB” # We’ll use that to scope this script (only running VMs with name matching this Prefix will be processed)
  • $LocalAdmin = “administrator” # This is the local admin account on the VMs. You can also use a domain account here if you like.

The script requires 1 positional parameter to indicate whether you wish to start the testing on the VMs or stop it. For example to start:

.\get-busy.ps1 start

GS-017e40

 To end the testing, use:

 .\get-busy.ps1 stop

The script will reach out to the VMs being tested and stop the busy.ps1 script, collect the test results, and cleanup the $Workfolder on each VM.

The script generates 2 log files:

  • A general log file that contains the messages displayed on the screen about each action attempted.
  • A CSV file that contains the compiled test results from all the CSV files generated by each busy.ps1 script on each of the tested VMs

Here’s an example of the compiled CSV file Get-busy_20140714_071428PM.csv


Powershell script to live migrate all running VMs including storage from one host to another


Powershell Script to live migrate all running VMs; including storage; from one host to another. Enter the source and destination host names (or IPs) in lines 4 and 5. Enter the drive letters of the destination host where you wish to live migrate the source host VMs to in line 6.

Moveall2

You can download this script from the Microsoft TechNet Gallery.

The script live migrates the VMs:

Moveall1

It also leaves 2 files on the folder where it runs:

– A log file that shows different information about the source and destination hosts, and the VMs being migrated.

– A CSV file that shows one record per migrated VM listing the source path of each of its disks. This may be useful for failback..


Powershell script to setup NFS share on Server 2012 R2


The following script sets up NFS share on Server 2012 R2:

NFS1

# Script to setup NFS share on Server 2012 R2
# Sam Boutros – 7/7/2014
# References: http://technet.microsoft.com/en-us/library/jj603081.aspx,
# http://technet.microsoft.com/en-us/library/jj574143.aspx#BKMK_deploy
#
$NFSFolder = “d:\shares\NFS1” # Tye in the path to the folder to be shared via NFS
$NFSShare = “nfs1” # Type in the share name you wish to use
# End Data entry section
#
Import-Module ServerManager
Add-WindowsFeature FS-NFS-Service
Import-Module NFS
if (!(Test-Path $NFSFolder)) {New-Item -ItemType directory -Path $NFSFolder}
New-NfsShare -name $NFSShare -Path $NFSFolder
$ShareName = $env:COMPUTERNAME + “:/” + $NFSShare
Write-Output “NFS share has been created: $ShareName”

You can see the new share in Server Manager under File and Storage Services:

NFS7

The default NFS share properties are:

NFS2

NFS3

Under Share Permissions, I clicked Add, entered the IP address (or name) of the Linux host that needs to connect to this 2012 R2 NFS share, and selected the desired access (read/write):

NFS4

No changes to NTFS permissions:

NFS5

Finally, I enabled the following firewall rule to allow me to ping this server:NFS8

Next, I setup a Red Hat 6.5 VM to test with.  I picked v6.5 because

  1. It comes with the Hyper-V integration built in – no need for manual RTM installation,
  2. The Hyper-V integration server for 6.5 kernel allows for Host-based VSS backup – no need for guest agent inside the Linux machine. We get crash consistent backup (not application consistent backup), but that’s a big improvement from Hyper-V integration service for kernel version 6.4 and older,
  3. The Hyper-V integration service supports dynamic RAM. Again, with kernel versions 6.4 and older, we can only use static RAM with Linux guests

I downloaded the media ISO Boot and DVD files from Red Hat,

created VM with 2 DVDs so that I can mount both media during setup, followed the simple installation steps, rebooted

Next, I used the console (and later on Putty to SSH) to the new Red Hat machine, logged in as root,

NFS9

I ran the following commands:

ifconfig -a => show interfaces
ifconfig eth0 10.5.19.36 netmask 255.255.255.0 => to setup IP address and mask
ping 10.5.19.38 => confirm connection to NFS server (enabled ping rule in Windows firewall)
mount -t ext4 => to show partitions formatted with ext4 file system
mkdir /pub => to create local mount point directory /pub
mount 10.5.19.38:/nfs1 /pub (must have added 10.5.19.36/RW permission on NFS share on Server 2012)
cd /pub => to change directory to /pub
ls => to see files on remote NFS share
echo hello >test1.txt => to test creating a text file named test1

You might want to edit /etc/fstab and modify the following line to match your configuration. For example:

10.5.19.38:/nfs1 /pub nfs defaults 0 0

The files were visible also on the 2012 R2 server.

 


Powershell script to rename many computers and join them to AD domain


This script will go through all VMs on the current Hyper-V host, select those that match a given name pattern, rename them to match the VM Name (in Hyper-V), and join them to the domain.

CVM3

The script can be downloaded from the Microsoft TechNet Gallery.

The script leaves a log file in the folder where it runs that shows details of actions performed and their success/failure status.

In the V1.1 update, I added code to initialize and format VM disks..

The VMs can be created in bulk as shown in this post.

This script needs a running VM acting as DC and DHCP server as shown in this post.

 


Using Powershell to create many Hyper-V Virtual Machines on many LUNs asynchronously


In a prior post I put out a powershell script to create many Hyper-V virtual machines on multiple LUNs using the Create-VM.ps1 script. That script ran in a single thread creating one VM before moving on to the next. In another post I manually ran 8 scripts to achieve the goal of running multiple jobs at the same time. In this script I use Start-Job with ScriptBlock and -ArgumentList to run multiple jobs at the same time.

GS-015j

The script can be downloaded from the Microsoft TechNet Gallery.

Hardware:

Compute node (Hyper-V host): 2x Xeon E5-2430L CPUs at 2 GHz with 6 cores each (12 Logical processors each) and 15 MB L3 cache, 96 GB RAM, 2x 10Gbps NICs that are not RDMA capable, setup in a NIC team (Teaming mode: Switch Independent, Load balancing mode: Hyper-V Port). Storage is 4x LUNs from a 3-node Gridstore array. Each LUN is configured as IOPS 2+1 LUN. Each Gridstore storage node has  1x Xeon E5-2403 processor at 1.8GHz with 4 cores (no hyper-threading) and 10 MB L3 cache, 32GB DDR3 1333 MHz DIMM, 4x 3TB 7200 RPM SAS disks, a 550GB PCIe Flash card, and 2x 10Gbps NICs that are not RDMA capable, setup in a NIC team (Broadcom Smart Load Balancing and Failover = switch-independent, no LACP support needed on switch).

The script took 9 minutes and 45 seconds to create the 40 VMs. During that time the Hyper-V host resource monitor showed:

GS-015a

GS-015b

GridControl snap-in showed:

GS-015c

GS-015d

GS-015e

I cal also see script logs piling up during script execution:

GS-015f

I started the 40 VMs manually after the script finished:

GS-015g

This excel file is based on the script output summary CSV file.

GS-015h

GS-015i


Conclusion and important points to note:

  • Hyper-V performance summary: No CPU or memory bottleneck observed during the test.
  • Array performance summary:
    • Files copies: 40
    • File size: 8.93GB
    • Concurrent operations: 4 copy operations at the same time
    • Total vLUNs used: 4
    • Average file copy duration: 10.18 seconds
    • Average throughput: 902.86 MB/s (6 Gbps)
    • Using the formula IOPS = BytesPerSec / TransferSizeInBytes
      LUNs are formatted as 64 KB blocks
      Average IOPS = (902.86*1024)/64 = 14.45k IOPS
  • Although 20 Gbps aggregate bandwidth is available to each of the compute node and the 3 storage nodes, I have not been able to produce network traffic above 10 Gbps.
  • CPU on the storage nodes was around 90% during the copy. The storage nodes can benefit from additional processing capacity.

Setting up Hyper-V lab using Powershell


In this post I setup a Hyper-V lab to test VM performance on Gridstore enterprise storage array.

Hardware: Compute node (Hyper-V host): 2x Xeon E5-2430L CPUs at 2 GHz with 6 cores each (12 Logical processors) and 15 MB L3 cache, 96 GB RAM, 2x 10Gbps NICs that are not RDMA capable. Storage is 8x LUNs from a 6-node Gridstore array detailed in this post.

I have Hyper-V role installed on this server. Next I setup NIC team and a vSwitch using this script:

GS-vSwitch

# Script to create NIC team, vSwitch
# Sam Boutros
# 6/28/2014
#
$PhysicalNICs = “NIC1,NIC2” # Get these names from Get-NetAdapter command
$NICTeamName = “Team1”
$vSwitchName = “My_vSwitch” # Pick a name for your vSwitch
$ParentPartitionvNICName = “My_vNIC” # Pick a name for your PP vNIC
$VLAN = 19
# End Data Entry section
#
# Create NIC Team
New-NetLbfoTeam -Name $NICTeamName -TeamMembers $PhysicalNICs -LoadBalancingAlgorithm HyperVPort -TeamingMode SwitchIndependent
# Create vSwitch
New-VMSwitch -Name $vSwitchName -NetAdapterName $NICTeamName -AllowManagementOS $False -MinimumBandwidthMode Weight
Set-VMSwitch $vSwitchName -DefaultFlowMinimumBandwidthWeight 50
# Create vNIC on this new vSwitch for the parent partition (Hyper-V host OS)
Add-VMNetworkAdapter -ManagementOS -Name $ParentPartitionvNICName -SwitchName $vSwitchName
# Comment out the following line if you’re not using VLANs
Set-VMNetworkAdapterVlan -ManagementOS -VMNetworkAdapterName $ParentPartitionvNICName -Access -VlanId $VLAN

Using a previously sys-prepped server 2012 R2 VHDX file (golden image), I manually create a VM to be used as DC for new lab test domain and DHCP server.

Install Active Directory Domain Services, DNS server, and DHCP server roles.

Configure Active Directory: new forest, new domain, forest level and domain level: 2012 R2, reboot.

Authorize DHCP server:

GS-010b

Create, configure, and activate new DHCP scope:

GS-010c

GS-010d

I got/set the MAC addresses to be given out by my Hyper-V host:

GS-010e

I added an Allow Filter to ensure that this DHCP server gives out IPs to the VMs of this host only and not any other machine in VLAN 19:

GS-010f

Now we’re ready to spin some VMs!

See this post for a script to create many VMs in bulk.

And this post for renaming them and joining them to the domain.


Using Powershell to create many Hyper-V Virtual Machines in parallel on Gridstore array


In a prior post I put out a powershell script to create many Hyper-V virtual machines on multiple LUNs using the Create-VM.ps1 script. That script ran in a single thread creating one VM before moving on to the next. In this test of the Gridstore array I ran 8 scripts at the same time in parallel.

GS-013a

# Script to create 8 test VMs on a specific LUN on current HyperV Host at a fixed point in time.
# Uses Create-VM.ps1 from https://superwidgets.wordpress.com/category/powershell/
# Sam Boutros – 7/1/2014
#
$GoTime = 40 # minute
$VMPrefix = “V-2012R2-LABk”
$VMrootPath = “k:\VMs”
$NumberofVMs = 8 # Per target LUN
#
# Common variables
$VMG = 2
$VMMemoryType = “Dynamic”
$VMStartupRAM = 1GB
$VMminRAM = 512MB
$VMmaxRAM = 1GB
$vSwitch = “Gridstore_vSwitch”
$VMCores = 2
$VLAN = 19
$AdditionalDisksTotal = 2
$AdditionalDisksSize = 1TB
$GoldenImageDiskPath = “E:\Golden\V-2012R2-3-C.VHDX”
$CSV = (Get-Location).path + “\IOPS_” + (Get-Date -format yyyyMMdd_hhmmsstt) + “.csv”
#
Write-Output “Waiting to start at the $GoTime minute”
do {start-sleep 1} until ((Get-Date).Minute -eq $GoTime) # Wait until GoTime
For ($j=1; $j -lt $NumberofVMs+1; $j++) {
$VMName = $VMPrefix + $j
$VMFolder = $VMRootPath + “\” + $VMName
.\Create-VM.ps1 -VMName $VMName -VMFolder $VMFolder -VMG $VMG -VMMemoryType $VMMemoryType -VMStartupRAM $VMStartupRAM -VMminRAM $VMminRAM -VMmaxRAM $VMmaxRAM -vSwitch $vSwitch -VMCores $VMCores -VLAN $VLAN -AdditionalDisksTotal $AdditionalDisksTotal -AdditionalDisksSize $AdditionalDisksSize -GoldenImageDiskPath $GoldenImageDiskPath -CSV $CSV
Start-VM -Name $VMName
}

The other 7 scripts were identical, except for the last letter of the $VMPrefix and the drive letter of the $VMRootPath.

The line do {start-sleep 1} until ((Get-Date).Minute -eq $GoTime) ensures that all 8 scripts kick off within 1 second of each other, essentially starting at the same time.

GS-013b

GS-013c

The Hyper-V host was clearly stressed:

GS-013d

GS-013e

GS-013f

The GridControl snap-in showed CPU utilization on the Gridstore storage nodes was holding around 60%:

GS-013g

Write process on the storage nodes hits all 6 nodes:

GS-013h

Read requests hit 4 storage nodes:

GS-013i

Here’s a copy of the metrics summary script output.

One of the 8 scripts had an error:

GS-013j

GS-013k

The error was that the script tried to create VM too fast. The interesting thing here is the magenta error message in this screen shot. It’s from an error handling code in the Create-VM.ps1 script. The script log file Create-VM_V-2012R2-LABk2_20140701_034214PM.txt showed:

2014.07.01 03:42:14 PM: Starting with paramters:
2014.07.01 03:42:14 PM:
2014.07.01 03:42:14 PM: VMName: V-2012R2-LABk2
2014.07.01 03:42:14 PM: VMFolder: k:\VMs\V-2012R2-LABk2
2014.07.01 03:42:14 PM: vSwitch: Gridstore_vSwitch
2014.07.01 03:42:14 PM: GoldenImageDiskPath: E:\Golden\V-2012R2-3-C.VHDX
2014.07.01 03:42:14 PM: VMG: 2
2014.07.01 03:42:14 PM: VMMemoryType: Dynamic
2014.07.01 03:42:14 PM: VMStartupRAM: 1073741824 – VMStartupRAM (calculated):
2014.07.01 03:42:14 PM: VMminRAM: 536870912 – VMminRAM (calculated):
2014.07.01 03:42:14 PM: VMmaxRAM: 1073741824 – VMmaxRAM (calculated):
2014.07.01 03:42:14 PM: VMCores: 2 – VMCores (calculated):
2014.07.01 03:42:14 PM: VLAN: 19 – VLAN (Calculated):
2014.07.01 03:42:14 PM: AdditionalDisksTotal: 2 – AdditionalDisksTotal (calculated):
2014.07.01 03:42:14 PM: AdditionalDisksSize: 1099511627776 – AdditionalDisksSize (Calculated): 1099511627776
2014.07.01 03:42:14 PM: .
2014.07.01 03:42:14 PM: Creating VM with the following paramters:
2014.07.01 03:42:14 PM: VM Name: ‘V-2012R2-LABk2’
2014.07.01 03:42:14 PM: VM Folder: ‘k:\VMs\V-2012R2-LABk2’
2014.07.01 03:42:14 PM: VM Generation: ‘2’
2014.07.01 03:42:14 PM: VM Memory: Dynamic, Startup memory: 1,024 MB, Minimum memory: 512 MB, Maximum memory: 1,024 MB
2014.07.01 03:42:14 PM: vSwitch Name: ‘Gridstore_vSwitch’
2014.07.01 03:42:14 PM: VM CPU Cores: ‘2’
2014.07.01 03:42:14 PM: Copying disk image k:\VMs\V-2012R2-LABk2\V-2012R2-LABk2-C.VHDX from goldem image E:\Golden\V-2012R2-3-C.VHDX
2014.07.01 03:42:41 PM: Copy time = 0 : 27 : 762 (Minutes:Seconds:Milliseconds) – 00:00:26.7623983 Milliseconds
2014.07.01 03:42:41 PM: File k:\VMs\V-2012R2-LABk2\V-2012R2-LABk2-C.VHDX size: 9,148 MB (9592373248 bytes)
2014.07.01 03:42:41 PM: Throughput: 342 MB/s (341.822877660408 MB/s)
2014.07.01 03:42:41 PM: or: 2,735 Mbps (2734.58302128326 Mbps)
2014.07.01 03:43:32 PM:
2014.07.01 03:43:32 PM: Error: Failed to create VM ‘V-2012R2-LABk2’.. stopping
2014.07.01 03:43:32 PM: Error details: The operation cannot be performed while the virtual machine is in its current state.[The operation cannot be performed while the virtual machine is in its current state..count-1]

Windows event viewer search showed:

GS-013l

So it appears that this “k” script working to create 8 VMs on drive “K” sent New-VM request at 3:43:32 (line 303 of CreateVM.ps1). That request took 11 seconds to complete as shown in event ID 13002 above. In the mean time, the script’s subsequent error checking lines 304, 305 detected that the VM has not bean created and aborted execution as designed.

On another note, I’m sure there are better ways to run powershell commands or scripts in parallel. I’ve looked into The [RunspaceFactory] and [PowerShell] Accelerators while running powershell in Multithreaded Apartment (powerhsell.exe -mta). I’ve also tried Updated Type Accelerator functions for PowerShell 3.0 and 4.0. I have tried the Start-Job/Get-Job cmdlets with script blocks, but had hard time passing parameters to Create-VM.ps1 with $ScriptBlock and -ArgumentList. I’ve also looked into ForEach-Parallel powershell workflow command. I simply needed to get this testing done quickly and did not have time to find a better way to run tasks in parallel in powershell. I welcome any comments or suggestions on better ways to run powershell scripts in parallel.


Conclusion and important points to note:

  • This set of scripts ran tasks that attempted to create 64 VMs on 8 Gridstore vLUNs. It did so by running 8 scripts in parallel, each script attempted to create 8 VMs on a different vLUN. 55 VMs were created successfully. Script failures were tracked down to busy/overwhelmed physical host.
  • Similar to the last test, each of the 8 vLUNs is configured as an IOPS (2+1) LUN
  • Network bandwidth utilization was completely maxed out on the testing Hyper-V host (10 Gbps Ethernet) I will use NIC teams to provide 20 Gbps Ethernet bandwidth
  • Storage nodes’ CPU utilization was at around 60% in this test, which is not a bottleneck.
  • This test is essentially a disk copy test as well and not a Hyper-V virtual machine performance test.
  • Summary comparison between this and the last test:

GS-013m

The throughput values under Gbps and GB/Min. are meant to compare parallel versus serial execution testing and not as metrics for the storage array, because they include time to create and configure virtual machines in addition to time taken by disk operations.