• Shortcuts : 'n' next unread feed - 'p' previous unread feed • Styles : 1 2

» Publishers, Monetize your RSS feeds with FeedShow:  More infos  (Show/Hide Ads)


Date: Tuesday, 06 Nov 2012 22:54

You may have read my previous posts on remote administration and constrained delegation (Enabling Hyper-V Remote Management - Configuring Constrained Delegation For SMB and Highly Available SMB or Enabling Hyper-V Remote Management - Configuring Constrained Delegation For Non-Clustered Live Migration or Scripting Constrained Delegation Settings) one of biggest challenges people voice over constrained delegation is that it requires active directory administrator permissions.  In Windows Server 2012 the Active Directory team introduced resource-based Kerberos constrained delegation this feature provides several significant advantages over traditional constrained delegation.  Specifically it no longer requires a domain administrator to configure it and it works across domain/forest trusts removing the requirement that both servers reside in the same domain and it’s really easy to configure!

One thing to keep in mind you still have to configure the share permissions and file/folder permissions properly (see the Create SMB Share For Virtual Machines section of Enabling Hyper-V Remote Management - Configuring Constrained Delegation For SMB and Highly Available SMB).

Basic Configuration

In this example below we are just getting the active directory computer object for the fileserver and then setting the PrincipalsAllowedToDelegateToAccount with the active directory computer object of the Hyper-V server.  In the background this sets msDS-AllowedToActOnBehalfOfOtherIdentity property to an NT Security Descriptor for the Hyper-V server’s computer account.

Get-ADComputer -Filter {Name -Like "FileServer"}  | Set-ADComputer -PrincipalsAllowedToDelegateToAccount (Get-ADComputer -Filter {Name -Like "HyperVServer"})

Advanced Configuration

The function below does a much more complete job of adding the Hyper-V server to the File Server’s PrincipalsAllowedToDelegateToAccount, specifically it read’s in existing entries building an array of allowed servers.

function Add-PrincipalsAllowedToDelegateToAccount
{
    Param
    (
        [String]
        $FileServer,
        [String]
        $HyperVServer
    )

    $deligationPrinciples = @()
    $fsAD = Get-ADComputer -Filter {Name -Like $FileServer} `
        -Properties msDS-AllowedToActOnBehalfOfOtherIdentity

    foreach ($AllowedAccount in $fsAD."msDS-AllowedToActOnBehalfOfOtherIdentity".Access)
    {
        $samAccountName = $AllowedAccount.IdentityReference.Value
        $samAccountName = $samAccountName.Remove(0, ($samAccountName.IndexOf("\")+1))

        $deligationPrinciples+=Get-ADComputer -Filter {SamAccountName -Like $samAccountName}
    }

    $deligationPrinciples += Get-ADComputer -Identity $HyperVServer
    $fsAD | Set-ADComputer -PrincipalsAllowedToDelegateToAccount $deligationPrinciples
}

 

I hope this helps everyone, it sure has helped my team!

-taylorb

 

Author: "Taylor Brown [Microsoft Hyper-V]"
Comments Send by mail Print  Save  Delicious 
Date: Tuesday, 09 Oct 2012 17:00

imageWith the release of Windows Server 2012 we introduced a new virtual hard disk format known as VHDX.  This new format provided the foundation for a number of features and performance enhancements.  One such feature is the ability to independently expand differencing virtual hard disks without impacting the base or parent hard disk or any siblings.  From the UI you can simply select ‘Edit Disk…’ input the path of the virtual hard disk and select expand from the options provided.  Similarly you can utilize the new Resize-VHD cmdlet in PowerShell providing the path to the disk and the new size in bytes for example Resize-VHD -Path "C:\VHDs\Child.vhdx" -SizeBytes 80GB.

 

-taylorb

Author: "Taylor Brown [Microsoft Hyper-V]"
Comments Send by mail Print  Save  Delicious 
Date: Monday, 08 Oct 2012 17:17
image

One of the most commonly requested features from customers using dynamic memory was the ability to see within the guest what the maximum memory was configured for.  So with Windows Server 2012 Hyper-V servers and with Windows Server 2012 or Windows 8 guests we added the maximum memory to the task manager.

 

-taylorb

DM 

Author: "Taylor Brown [Microsoft Hyper-V]"
Comments Send by mail Print  Save  Delicious 
Date: Tuesday, 25 Sep 2012 20:14

imageA few times I’ve had people ask me about how they automate moving VM’s off of a cluster node based on some type of detected failure or performance issue.  In general my answer is to utilize System Center specifically Operations Manager – many customers I work with take this advice and leverage the management packs and broad insight that Operations Manager provides to create automatic Diagnostics and Recoveries tied to Monitors.  But for other customers this is to heavy handed or they

don’t have the resources to leverage Operations Manager.  So are they out of luck?  Not really – there are two commonly overlooked feature in Windows, the Task Scheduler and Performance Monitor.

imageWithin the Windows Task Scheduler you can create a task which is automatically executed every time an event is generated the task can then run a script.  For example you can create a task which is tied to the event that is logged when a network adapter that is connected to a virtual switch has it’s network cable disconnected, when that event is detected you can have a script that pauses the cluster node and migrates all of the VM’s off of it.  Similarly you can configure the Windows Performance Monitor to trigger a scheduled task when a performance threshold has been exceeded.  What actions these tasks take is completely up to your imagination and the how complex you want to make the scripts they execute.

The biggest draw back to this method vs using something like Operations Manager is that magic term ‘centralization’ i.e. these tasks have to be configured on each server and any changes have to be replicated to each server.  Additionally either the scripts have to be flexible enough work across varying server configurations (for example one NIC or two, teamed or not) or you have to configure the script/task individually for each server.  However going back to our original statement this is really an answer for environments where Operations Manger is too heavy thus limited number of servers.

I’m going to provide a few basic examples just to get you thinking and as a proof of concept.  Specifically I am going to focus on the disconnected network adapter and some overall performance metrics (CPU utilization, Disk throughput and Network throughput).  We’ll start with the disconnected network adapter.

Creating a Task Triggered By Events

image

Creating the task

  1. Start by opening the Task Scheduler and then create a new task
  2. Provide the task a name i.e. Disconnected NIC
  3. Select an account for the task to run under it will need to be an Administrator account for this example to work – I use a domain account that I provision to all my servers for this specific reason, and yes I change the password often and the account is significantly limited.
  4. Select “Run whether user is logged on or not”
  5. Select “Run with highest privileges”
image

Defining the triggers

We will define two triggers the first for event id 22 which represents the media being disconnected and a second for event id 24 which represents the underlying nic being disabled or otherwise failing.

  1. Select the triggers tab and click New
  2. Select “On an event” from the Begin the task list
  3. From the Log dropdown select System
  4. From the source dropdown Select “Hyper-V-VMSwitch
  5. In the Event ID field specify 22
  6. Repeat steps 1-5 specifying 24 as the event id for step 5.
image

Defining the actions

In this example there is just a single action – the action runs a PowerShell script.  You could have multiple actions for example one that runs a script to live migrate VMs and a second to send an e-mail or startup another host what ever you want.

  1. Select the actions tab and click New
  2. For the action “Start a program” should already be selected
  3. For the Program/script property specify “%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe” to initiate PowerShell
  4. For the Add arguments property specify the path to the script you want executed when this event occurs.  The script could be as simple as “Suspend-ClusterNode –Drain”.  There is a more in-depth example of a script below as well.
     

Creating a Performance Monitor Alert To Trigger a Task

 

image

Creating a Data Collector Set

  1. Start by opening Performance Monitor (perfmon)
  2. Expand the “Data Collector Sets”
  3. Right click on “User Defined” and select New->Data Collector Set
  4. Provide a name for the collector set
  5. Select “Create manually (Advanced)” and select Next
  6. Select “Performance Counter Alert” and select Finish
image

Creating a Data Collector

  1. Right click on the newly created Collector Set and select New->Data Collector
  2. Specify a name and select “Performance counter alert”
image

Defining the counters and thresholds

  1. Click Add
  2. Select the counter or counters you are interested in alerting on, in this example I am looking at CPU utilization, available memory and Avg. Disk Queue Length.  It’s worth noting that if multiple conditions are true the alert will only specify the first condition, you can get around this if required by defining multiple alerts.
  3. For each counter you specify provide an alert threshold, i.e. for CPU utilization I specified Idle time below 10% for Memory below 8096 Available MBs etc..
  4. Select Next and then Check the “Open properties for this data collector” and Finish
image

Defining the counter interval and task to run

  1. In the Data Collector Properties on the Alerts Tab you can specify the sample interval – do keep in mind the more often you query the counter the more CPU is required, 15 seconds seems like a good starting point.
  2. On the Alert Task tab specify a name you will use for a Task Manager task (we’ll create the task in a min)
  3. You can also specify and arguments you want passed to the task.
  4. When done click ok…
image

Creating the scheduled task

  1. Create a task using the same method as the event triggered tasks.  Ensure you name it appropriately based on the Alert Task name you provided when defining the performance alert.
  2. For the triggers you can leave that blank – the performance alert is the trigger.
  3. For the action they will look very similar to the event action however note that for the arguments in addition to the script I have specified ‘$(Arg0)’.  This is what passes the arguments from the performance alert to the script – also worth calling out since it took me a while to figure it out the single quotes are required…
  4. Another worthwhile tip, on the settings tab you may want to select Do not start a new instance for the If the task is already running option.  Otherwise it will start your script every 15 seconds (or what ever interval you specified)
  5. In terms of the script actions that’s up to you… For a basic test I just had it output the arguments to a file ($args | Out-File "C:\Scripts\PerformanceAlert.txt" –Append) which will give you some output like:
    \Hyper-V Hypervisor Logical Processor(_Total)\% Idle Time;< 95.000000;90.611417;9/25/2012 - 4:04:25 PM

    More Robust Disconnected NIC Script

    This is a more robust script for the disconnected host NIC – what the script does is identifies which NIC is disconnected and any VM’s that are impacted by that NIC being disconnected.  It then checks all of the other cluster nodes to see if there NIC is also disconnected before migrating only the effected VM’s.

    $NicDisconnectedLog = [String]::Empty
    $NicDisconnectedLog += "NIC Adapter Disconnection Detected - Attempting to Move VMs`n"

    $Event = Get-EventLog -LogName System -Source Microsoft-Windows-Hyper-V-VmSwitch `
        -InstanceId 24 -Newest 1

    $NicDisconnectedLog += ("Disconnected NIC Description: " + `
        $Event.ReplacementStrings[3] + "`n")

    $Switch = Get-VMSwitch -SwitchType External | Where-Object `
        {$_.NetAdapterInterfaceDescription -eq $Event.ReplacementStrings[3]}

    $NicDisconnectedLog += ("Associated Switch Name: " + $Switch.Name + "`n")

    $NicDisconnectedLog += ("Determining Available Cluster Nodes`n")
    $AvalableClusterNodes = @()
    foreach ($clusterNode in (Get-ClusterNode | Where-Object {$_.State -eq "Up"}))
    {
        $destSwitch = Get-VMSwitch -Name $Switch.Name -ComputerName $clusterNode.Name
        if ((Get-NetAdapter -InterfaceDescription $destSwitch.NetAdapterInterfaceDescription `
            -CimSession $clusterNode.Name).Status -eq "Up")
        {
            $AvalableClusterNodes+= $clusterNode
            $NicDisconnectedLog += ("Node: " + $clusterNode.Name + " is available.`n")
        }
        else
        {
            $NicDisconnectedLog += ("Node: " + $clusterNode.Name + `
                " also has a disconnected switch.`n")
        }
    }
    if ($AvalableClusterNodes.Count -eq 0)
    {
        $NicDisconnectedLog += ("No Available Cluster Nodes - Exiting`n")
    }
    else
    {

        $NicDisconnectedLog += ("Determining Effected VM's`n")
        $EffectedNics = Get-VMNetworkAdapter -VMName * | Where-Object `
            {$_.SwitchName -eq $Switch.Name}
        $VMsToMove = @()
        foreach ($Nic in $EffectedNics)
        {
            if (!$VMsToMove.Contains($Nic.VMId))
            {
                $NicDisconnectedLog += ("VM: " + $Nic.VMName + "ID:(" + `
                    $Nic.VMId + ")" +" is effected - preparing to move.`n")       

                $VMsToMove += $Nic.VMId
            }
        }

        $NicDisconnectedLog += ("Preparing to Move Effected VM's`n")
        for ($MoveCounter = $VMsToMove.Count; $MoveCounter -gt 0; $MoveCounter--)
        {
            $attemptCount = 0
       
            do {
                $destinationNode = $AvalableClusterNodes[(($MoveCounter+$attemptCount) `
                    % $AvalableClusterNodes.Count)]
                $NicDisconnectedLog += ("Moving VM with ID: " + $VMsToMove[($MoveCounter-1)] `
                    + " to node: " + $destinationNode.Name + "`n")               

                $result = Move-ClusterVirtualMachineRole -VMId $VMsToMove[($MoveCounter-1)] `
                    -Node $destinationNode.Name -MigrationType Live

                $attemptCount++
            }
            while (($result.OwnerNode -ne $destinationNode.Name) `
                -and ($attemptCount -lt $AvalableClusterNodes.Count))
        }
    }

    $NicDisconnectedLog | Out-File "C:\Scripts\NicLog.txt"

     

     

    -taylorb

    Author: "Taylor Brown [Microsoft Hyper-V]"
    Comments Send by mail Print  Save  Delicious 
    Date: Wednesday, 18 Jul 2012 17:50

    With all of the new PowerShell cmdlet’s in available for Hyper-V in Window's Server 2012 the one I personally had the hardest time with was Move-VMStorage.  The Move-VMStorage cmdlet is used to perform storage migrations for Hyper-V virtual machines i.e. moving a virtual hard disk from one drive to another or from one SMB share to another.  The tricky part about this cmdlet comes in when you want to move only a part of the VM’s storage (so only the VHDs or only a single VHD) – in that case you need to provide an array of hastables?  What goes in that hashtable?  How do you create it?  Here’s how.

     

    Overview

    There are effectively two way’s to call Move-VMStorage each with two minor variations (a VM object vs. a VM name).  The first one is pretty straight forward – you call Move-VMStorage with either a VM object or name and provide a Destination Storage Path, this will move all on the VM’s virtual hard disks, it’s configuration, any snapshots etc… You can see an example of that below.  The second method allows you to specify only parts of the VM to move – i.e. a specific virtual hard disk, in many cases this is very helpful if for example you want to balance IO load or increase redundancy or if your VM’s are configured with different storage paths upfront and you want to move one of those VHD’s.

    PS C:\> Get-Help Move-VMStorage

    NAME
        Move-VMStorage
       
    SYNTAX
        Move-VMStorage [-VMName] <string> [-DestinationStoragePath] <string> [-ComputerName <string[]>]
        [-ResourcePoolName <string>] [-RetainVhdCopiesOnSource] [-AllowUnverifiedPaths] [-AsJob]
        [-WhatIf] [-Confirm]  [<CommonParameters>]
       
        Move-VMStorage [-VMName] <string> [-ComputerName <string[]>] [-VirtualMachinePath <string>]
        [-SnapshotFilePath <string>] [-SmartPagingFilePath <string>] [-Vhds <hashtable[]>]
        [-ResourcePoolName <string>] [-RetainVhdCopiesOnSource] [-AllowUnverifiedPaths] [-AsJob]
        [-WhatIf] [-Confirm]  [<CommonParameters>]

       
        Move-VMStorage [-VM] <VirtualMachine> [-VirtualMachinePath <string>] [-SnapshotFilePath
        <string>] [-SmartPagingFilePath <string>]
    [-Vhds <hashtable[]>] [-ResourcePoolName <string>]
        [-RetainVhdCopiesOnSource] [-AllowUnverifiedPaths] [-AsJob] [-WhatIf] [-Confirm] 
        [<CommonParameters>]

       
        Move-VMStorage [-VM] <VirtualMachine> [-DestinationStoragePath] <string> [-ResourcePoolName
        <string>] [-RetainVhdCopiesOnSource] [-AllowUnverifiedPaths] [-AsJob] [-WhatIf] [-Confirm] 
        [<CommonParameters>]

    The Basic Storage Migration

    A basic migration operation where you want to migrate all of the VM’s storage is pretty straight forward – let’s look at an example with a VM that has three VHDs all located in the same folder as it’s configuration and the migrate them to another location.

    Storage Configuration Prior Migration

    PS C:\> (Get-VM Demo).ConfigurationLocation    
    V:\Share\VMs\Demo

    PS C:\> Get-VMHardDiskDrive -VMName Demo    

    VMName ControllerType ControllerNumber ControllerLocation DiskNumber Path
    ------ -------------- ---------------- ------------------ ---------- ----
    Demo IDE 0 0   V:\Share\VMs\Demo\OS.vhdx
    Demo SCSI 0 0   v:\Share\VMs\Demo\SCSIDisk1.vhdx
    Demo SCSI 0 1   v:\Share\VMs\Demo\SCSIDisk2.vhdx

    Migrating The VM’s Storage

    PS C:\> Move-VMStorage -VMName Demo -DestinationStoragePath T:\Share2\VMs\Demo

    Storage Configuration Post Migration

    PS C:\> (Get-VM Demo).ConfigurationLocation
    T:\Share2\VMs\Demo

    PS C:\> Get-VMHardDiskDrive -VMName Demo    

    VMName ControllerType ControllerNumber ControllerLocation DiskNumber Path
    ------ -------------- ---------------- ------------------ ---------- ----
    Demo IDE 0 0   T:\Share2\VMs\Demo\OS.vhdx
    Demo SCSI 0 0   T:\Share2\VMs\Demo\SCSIDisk1.vhdx
    Demo SCSI 0 1   T:\Share2\VMs\Demo\SCSIDisk2.vhdx

    Migrating a Single Virtual Hard Disk

    Migrating a single virtual hard disk is a slightly more involved operation – once you see how it’s done the process is pretty simple.  We’ll use the same VM as before but in this case we will only migrate the virtual hard disk attached to the SCSI controller at location 1.  The first operation thing we need to do is retrieve the path of the virtual hard disk as it is today and we will use the Get-VMHardDiskDrive cmdlet for this.  Then we need to create a hash table with two key value pairs, the first pair has a key name of “SourceFilePath” with a value of the location of the virtual disk, the second pair has a key name of “DestinationFilePath” and a value of the location where the virtual hard disk will be migrated to.  We then take that hashtable and put it into an array that is then passed to Move-VMStorage. 

    Here is the complete example:

    $vhdToMove = Get-VMHardDiskDrive -VMName Demo -ControllerLocation 1
    $vhdMoveMap = New-Object -TypeName System.Collections.Hashtable
    $vhdMoveMap.Add("SourceFilePath", $vhdToMove.Path)
    $vhdMoveMap.Add("DestinationFilePath", "T:\Share2\VMs\Demo\SCSIDisk2.vhdx")
    $vhds = @($vhdMoveMap)
    Move-VMStorage -VMName Demo -Vhds $vhds

    Migrating Multiple Virtual Hard Disks

    In similar fashion to the first single virtual hard disk migration we can move multiple disks at the same time by just adding more hashtable’s to the array.

    For example if we wanted to move two virtual hard disks:

    $vhdToMove = Get-VMHardDiskDrive -VMName Demo -ControllerLocation 0 -ControllerType SCSI
    $vhdMoveMap = New-Object -TypeName System.Collections.Hashtable
    $vhdMoveMap.Add("SourceFilePath", $vhdToMove.Path)
    $vhdMoveMap.Add("DestinationFilePath", "T:\Share2\VMs\Demo\SCSIDisk1.vhdx")
    $vhds = @($vhdMoveMap)

    $vhdToMove = Get-VMHardDiskDrive -VMName Demo -ControllerLocation 1 -ControllerType SCSI
    $vhdMoveMap = New-Object -TypeName System.Collections.Hashtable
    $vhdMoveMap.Add("SourceFilePath", $vhdToMove.Path)
    $vhdMoveMap.Add("DestinationFilePath", "S:\Share3\VMs\Demo\SCSIDisk2.vhdx")
    $vhds += @($vhdMoveMap)

    Move-VMStorage -VMName Demo -Vhds $vhds

    Or if we wanted to move all virtual hard disks for any VM starting with “D”:

    Get-VM -Name "D*" | % {
    $vhds = $null
        foreach ($VHD in (Get-VMHardDiskDrive -VM $_))
        {
            $vhdMap = New-Object -TypeName System.Collections.Hashtable
            $vhdMap.Add("SourceFilePath", $VHD.Path)
            $vhdMap.Add("DestinationFilePath", ($VHD.Path.Replace("V:\Share\VMs\", "T:\Share2\VMs\")))
            $vhds += @($vhdMap)
        }
        Move-VMStorage -VM $_ -Vhds $vhds
    }

     

    I hope this helps better explain the Move-VMStorage cmdlet…  Happy migrating.

    -taylorb

    Author: "Taylor Brown [Microsoft Hyper-V]"
    Comments Send by mail Print  Save  Delicious 
    Date: Thursday, 21 Jun 2012 21:35

    I hope everyone that attended TechEd had a great time – this was far and away the best TechEd I have personally attended.  I had promised all the scripts from my session and I decided to wait until the recording/slides where available and just do one big post so here it is…

    Session Recording

    http://channel9.msdn.com/Events/TechEd/NorthAmerica/2012/VIR301

     

     

    Scripts

    Keeping The PowerShell Window On Top

    I already posted this earlier at Scripts From TechEd 2012… Part 1 (Keeping PowerShell Window On Top) but here it is again…
    $signature = @’
    [DllImport("user32.dll")]
    public static extern bool SetWindowPos(
        IntPtr hWnd,
        IntPtr hWndInsertAfter,
        int X,
        int Y,
        int cx,
        int cy,
        uint uFlags);
    ‘@
    $type = Add-Type -MemberDefinition $signature -Name SetWindowPosition -Namespace SetWindowPos -Using System.Text -PassThru

    $handle = (Get-Process -id $Global:PID).MainWindowHandle
    $alwaysOnTop = New-Object -TypeName System.IntPtr -ArgumentList (-1)
    $type::SetWindowPos($handle, $alwaysOnTop, 0, 0, 0, 0, 0x0003)

     

    Configuring Virtual Fibre Channel

    $vm = (Get-ClusterGroup -Name "FibreChannelDemo" -Cluster "hv-teched-c" | Get-VM)
    $vm
    $adapterA = Add-VMFibreChannelHba -VM $vm -GenerateWwn -SanName "Virtual SAN - A" -Passthru
    $adapterA
    $adapterB = Add-VMFibreChannelHba -VM $vm -GenerateWwn -SanName "Virtual SAN - B" -Passthru
    Import-Module DataONTAP
    Connect-NaController -Name "#Name/IP Of NetApp SAN"
    $igroup = New-NaIgroup -Name "FibreChannelDemo" -Protocol fcp -Type hyper_v
    Add-NaIgroupInitiator -Igroup $igroup.Name -Initiator $adapterA.WorldWidePortNameSetA
    Add-NaIgroupInitiator -Igroup $igroup.Name -Initiator $adapterA.WorldWidePortNameSetB
    Add-NaIgroupInitiator -Igroup $igroup.Name -Initiator $adapterB.WorldWidePortNameSetA
    Add-NaIgroupInitiator -Igroup $igroup.Name -Initiator $adapterB.WorldWidePortNameSetB
    New-NaVol -Name "FibreChannelDemo" -Aggregate aggr1 -Size 100G -SpaceReserve "none"
    New-NaLun -Path "/vol/FibreChannelDemo/FibreChannelDemo" -Size 100G -Type hyper_v -Unreserved
    Add-NaLunMap -InitiatorGroup $igroup -Path "/vol/FibreChannelDemo/FibreChannelDemo"
    Start-vm -VM $vm

    Displaying SQL Transactions

    #Insert the PowerShell Function to Keep the Window On Top
    $sqlConn = new-object System.Data.SqlClient.SqlConnection -ArgumentList "Data Source=HV-TE-SQL-1\MSSQLSERVER2;Integrated Security=TRUE;Initial Catalog=Demo"
    $sqlConn.Open()
    $sqlCommand = new-object System.Data.SqlClient.SqlCommand -ArgumentList @("EXEC [dbo].[AddData];", $sqlConn)

    while ($true)
    {
        $startTime = [DateTime]::Now
        for ($counter = 0; $startTime.AddSeconds(1) -gt [DateTime]::Now; $counter++)
        {
            $sqlCommand.ExecuteReader().Close()
        }
        Clear-Host
        "Executing $counter Transactions Per Second" | write-host -NoNewline
    }

    Displaying VHD/VHDx Size On Disk

    #Insert the PowerShell Function to Keep the Window On Top
    function Write-VHDSize {
        $vhdSize = ((Get-ItemProperty -Path "m:\teched01_Trim_vhd\trim.vhd").Length/1GB)
        $vhdxSize = ((Get-ItemProperty -Path "N:\teched01_Trim_vhdx\trim.vhdx").Length/1GB)
        Clear-Host
        Write-Host "Current VHD and VHDx Size On Disk"
        [String]::Format("VHD Size:`t{0:F2}GB`nVHDx Size:`t{1:F2}GB", $vhdSize, $vhdxSize) | Write-Host -NoNewline
        Start-Sleep -Milliseconds 300
    }

    while ($true)
    {
        Write-VHDSize
    }

    Displaying the VHDx and SAN Space Used

    #Insert the PowerShell Function to Keep the Window On Top
    function WriteVHDVolSize ()
    {
        $vhdxSize = ((Get-Item -Path "O:\teched01-Trim-san\trim.vhdx").Length/1MB)
        $EqlVolumeSize = (Get-EqlVolume -VolumeName "teched01-Trim-san").AllocatedMB
        Clear-Host
        [String]::Format("VHDx Size:`t{0:F2}MB`nUsed SAN Space:`t{1:F2}MB", $vhdxSize, $EqlVolumeSize) | Write-Host -NoNewline
        Start-Sleep -Milliseconds 300
    }

    if (!(Get-Module EqlPSTools))
    {
        Import-Module "c:\Program Files\EqualLogic\bin\EqlPSTools.dll"
    }
    $Creds = new-object -typename System.Management.Automation.PSCredential -argumentlist "demo", (ConvertTo-SecureString -AsPlainText "#Password" -Force)
    Connect-EqlGroup -GroupAddress "#Name/IP Of EqualLogic SAN" -Credential $Creds

    while ($true)
    {
        WriteVHDVolSize
    }

    Initializing the Virtual Disk In The VM

    Write-Host "Initializing VHDx Disk..."

    $disk = Get-Disk | Where-Object {$_.OperationalStatus -eq "Offline"}
    $disk | Set-Disk -IsOffline:$false
    if ($disk -eq $null)
    {
        $disk = Get-Disk | Where-Object {$_.PartitionStyle -eq "RAW"}
    }
    $disk | Initialize-Disk -PartitionStyle GPT

    Write-Host "Creating X: Partition of 40GB on VHDx Disk..."
    New-Partition -DiskId $disk.UniqueId -Size 40GB -DriveLetter ([Char]"X") | Format-Volume -FileSystem NTFS -Confirm:$false
    Write-Host "Creating Y: Partition of 40GB on VHDx Disk..."
    New-Partition -DiskId $disk.UniqueId -Size 40GB -DriveLetter ([Char]"Y") | Format-Volume -FileSystem NTFS -Confirm:$false

    Start-Process E:

    Optimizing The Volume

    Optimize-Volume -DriveLetter X –ReTrim

    Full Script For UnMap/Trim Demo Of VHDx On SAN

    function Copy-File {
        param(
        [String]$Source,
        [String]$Destination
        )
        $sourceFile = [System.IO.File]::OpenRead($Source)
        $destinationFile = [System.IO.File]::OpenWrite($Destination)
        Write-Progress -ID 1 -Activity "Copying BigFile" -status "$Source -> $Destination" -PercentComplete 0
        try {
            [byte[]]$buffer = new-object byte[] 4096
            [int]$total = [int]$counter = 0
            do {
                $counter = $sourceFile.Read($buffer, 0, $buffer.Length)
                $destinationFile.Write($buffer, 0, $counter)
                $total += $counter
                if ($total % 1mb -eq 0) {
                    Write-Progress -ID 1 -Activity "Copying BigFile" -status "$Source -> $Destination" `
                       -PercentComplete ([int]($total/$sourceFile.Length* 100))
                }
            } while ($counter -gt 0)
        }
        finally {
            Write-Progress -ID 1 -Activity "Copying BigFile" -Completed:$true
            $sourceFile.Close()
            $destinationFile.Close()
        }
    }

    "Windows PowerShell" | Write-Host
    "Copyright (C) 2012 Microsoft Corporation. All rights reserved.`n" | Write-Host

    "PS C:\> Copy-File -From `"E:\MyBigFile.bin`" -To `"X:\MyBigFile.bin`"" | Write-Host -NoNewline
    Read-Host |Out-Null
    Copy-File -From "E:\MyBigFile.bin" -To "X:\MyBigFile.bin" | Write-Host -NoNewline
    Write-Host "Flushing File System Cache...`n"
    Set-Disk -Number 2 -IsOffline:$true
    Set-Disk -Number 2 -IsOffline:$false

    "PS C:\> Remove-Item `"X:\MyBigFile.bin`" -Force:`$true -Confirm:`$false" | Write-Host -NoNewline
    Read-Host |Out-Null
    Remove-Item "x:\MyBigFile.bin" -Force:$true -Confirm:$false

    "PS C:\> Optimize-Volume -DriveLetter X -ReTrim" | Write-Host -NoNewline
    Read-Host |Out-Null

    Optimize-Volume -DriveLetter X –ReTrim

    -taylorb

    Author: "Taylor Brown [Microsoft Hyper-V]"
    Comments Send by mail Print  Save  Delicious 
    Date: Tuesday, 12 Jun 2012 22:21

    I just finished my speaking session at TechEd 2012, once the recording is available I will post a link…  I’ve already had an overwhelming number of requests for the scripts that I used during the session.  I’m going to do a few posts over the next few days, as I can steal 10 min from all the TechEd activities.

     

    The first script and the one that every seemed the most interested in keeps a PowerShell Window on top i.e. the top most window.  The way I did it was a bit evil – well very non PowerShell but it works.  I use PInvoke…

     

    $signature = @’
    [DllImport("user32.dll")]
    public static extern bool SetWindowPos(
        IntPtr hWnd,
        IntPtr hWndInsertAfter,
        int X,
        int Y,
        int cx,
        int cy,
        uint uFlags);
    ‘@
     
    $type = Add-Type -MemberDefinition $signature -Name SetWindowPosition -Namespace SetWindowPos -Using System.Text -PassThru

    $handle = (Get-Process -id $Global:PID).MainWindowHandle
    $alwaysOnTop = New-Object -TypeName System.IntPtr -ArgumentList (-1)
    $type::SetWindowPos($handle, $alwaysOnTop, 0, 0, 0, 0, 0x0003)

     

    So there you go – look for more of the scripts latter tonight or tomorrow…

     

    -taylorb

    Author: "Taylor Brown [Microsoft Hyper-V]" Tags: "Powershell"
    Comments Send by mail Print  Save  Delicious 
    Date: Monday, 11 Jun 2012 12:35

    After a very long day of travel yesterday I am even happier to be at TechEd 2012 now.  This is going to be the most exciting TechEd that I can remember - there is so much stuff in Windows Server 2012 it's really unbelievable.

     

    In any case if you are at TechEd stop by and say hi or even better come by my session!

    VIR301 - Windows Server 2012 Hyper-V Storage

    Speaker(s): Taylor Brown, Senthil Rajaram

    Tuesday, June 12 at 1:30 PM - 2:45 PM  in S310A

    In this session, we cover the changes to the Windows Server 2012 Hyper-V storage stack. We dive into the enhancements around the new virtual disk format, integrating new storage industry innovations around offloaded data transfer and large sector disks, and detail the new storage options for Hyper-V including Storage spaces and SMB file storage. We present performance and scaling improvements and conclude the session with sample configurations, including both standalone and clustered options.  #TEVIR301

     

    Taylor Brown     
    Hyper-V Enterprise Deployment Team    
    taylorb@microsoft.com   
    http://blogs.msdn.com/taylorb

    WS08R2-HyperV_v_rgb

    Author: "Taylor Brown [Microsoft Hyper-V]"
    Comments Send by mail Print  Save  Delicious 
    Date: Monday, 07 May 2012 18:10

    I originally wrote this script for my own clusters to upgrade them from Windows Server 2008 R2 to Windows Server “8” Beta and since then I have shared it with a few others who also found it very helpful.  I had some designs on improving it but decided I would put those on hold until later.  The script is pretty straight forward it gathers all of the information about a VM from the source cluster and then does in import from the source cluster to the destination machine having Hyper-V copy all of the VHD and other configuration files.  The script takes advantage of a few new Hyper-V features in Window Server “8” Beta – specifically the ability to import directly from a VM configuration file as well as our new Hyper-V PowerShell cmdlet’s.  If you want more details on Compare-VM, Import-VM or any of the other cmdlet’s take a look at the TechNet documentation.

     

     

    Script Limitations and Assumptions

    All of these can be worked around – but many will be handled better in future releases (i.e. RC/RTM) thus I did not spend to much time scripting around them.

    • Must Be Run on a Windows Server “8” Beta Hyper-V Host
    • VM’s must be using CSV
    • VM’s VHD’s must all be on the same CSV and the same folder and must be located under the “Virtual Hard Disks” Folder
    • VM’s can not have snapshots (due to a bug in Windows Server “8” Beta)

     

     

     

    function Migrate-VMFromR2Cluster {
         param (
         [Parameter(Mandatory
    =$true,Position=0,HelpMessage="Name Of The VM To Be Migrated")]
         [
    String]
         $VmName,
         [Parameter(Mandatory
    =$true,Position=0,HelpMessage="Name Of The Source Cluster")]
         [
    String]
         $SourceCluster,
         [Parameter(Mandatory
    =$true,Position=0,HelpMessage="Path Where The VM Will Be Copied To On Local Machine")]
         [
    String]
         $TargetVMPath,
         [Parameter(Mandatory
    =$true,Position=0,HelpMessage="Name Of The Virtual Switch The VM Will Be Connected To")]
         [
    String]
         $TargetHyperVSwitchName
    )

    #Get all of the VM's settings on the source server, we have to do this prior to offlining the configuration file
    $SourceServer = ((Get-ClusterGroup $VmName -Cluster $SourceCluster).OwnerNode).Name
    $SourceVM = Get-WmiObject -Namespace "root\virtualization" -ComputerName $SourceServer -Class "Msvm_ComputerSystem" -Filter "ElementName = '$VmName'"
    $VmDataRoot = ($SourceVM.GetRelated("Msvm_VirtualSystemGlobalSettingData").ExternalDataRoot.ToLower()).Replace("c:\", "\\$SourceServer\c`$\")
    $VmConfigurationFile = ($VmDataRoot+ "\Virtual Machines\" + $SourceVM.Name + ".xml")
    $VhdSourcePath = ($VmDataRoot + "\Virtual Hard Disks")
    $Msvm_VirtualSystemSettingData = ($SourceVM.GetRelated("Msvm_VirtualSystemSettingData") | % {$_})
    $Msvm_SyntheticEthernetPortSettingDataCollection = $Msvm_VirtualSystemSettingData.GetRelated("Msvm_SyntheticEthernetPortSettingData")

    #Get all of the VLAN and networking configurations for the VM
    #
    - this is requried as in Windows 2008 and 2008 R2 we store the network settings in the switch configuration not with the VM
    #
    - in Windows Server "8" Beta there was a bug that this data was also not present in the export file
    $SwitchPortSettings = New-Object -TypeName System.Collections.Hashtable
    foreach ($Msvm_SyntheticEthernetPortSettingData in $Msvm_SyntheticEthernetPortSettingDataCollection)
    {
        
    $Msvm_SwitchPort = $Msvm_SyntheticEthernetPortSettingData | % {[WMI]($_.Connection| % {$_})}
         if ($Msvm_SwitchPort.__Path -ne $null)
         {
              $Msvm_VLANEndPoint = $Msvm_SwitchPort.GetRelated("Msvm_VLANEndPoint") | % {$_}
              $Msvm_VLANEndpointSettingData = $Msvm_VLANEndPoint.GetRelated("Msvm_VLANEndpointSettingData") | % {$_}
              $SwitchPortSettings.Add($Msvm_SyntheticEthernetPortSettingData.InstanceID, 
                
    @($Msvm_SwitchPort, $Msvm_VLANEndpointSettingData.AccessVLAN))
         }
    }

    #Offline the VM's configuration file so that we can open in for Import
    (Get-ClusterGroup $VmName -cluster $SourceCluster) | Get-ClusterResource | Stop-ClusterResource | Out-Host

    #Generate a VM compatability object which will be used to fixup all the network adapters
    #
    - note that copy is specified meaning the VHDs will be copied over the network
    $compare = Compare-VM -Copy -Path $VmConfigurationFile -VhdSourcePath $VhdSourcePath -VhdDestinationPath $TargetVMPath -VirtualMachinePath $TargetVMPath

    #Fixing network adapters and make sure they use correct VMSwitch and keep VLAN ID and mac spoofing settings
    Foreach ($NetworkAdapter in $Compare.vm.NetworkAdapters)
    {
         $NetworkAdapter | Connect-VMNetworkAdapter -SwitchName $TargetHyperVSwitchName
         $NicSetting = $SwitchPortSettings[$NetworkAdapter.Id]
         if ($NicSetting -ne $null)
         {
             $NetworkAdapter | Set-VMNetworkAdapterVlan -Access -VlanId $NicSetting[1]
             if ($NetworkAdapter[0].AllowMacSpoofing)
             {
                 $NetworkAdapter | Set-VMNetworkAdapter -MacAddressSpoofing On
             }
         }
    }
    Import-VM -CompatibilityReport $Compare
    Set-VM -Name $VmName -AutomaticStopAction ShutDown
    }

    Taylor Brown
    Hyper-V Enterprise Deployment Team
    taylorb@microsoft.com
    http://blogs.msdn.com/taylorb

    WS08R2-HyperV_v_rgb

    Author: "Taylor Brown [Microsoft Hyper-V]" Tags: "Hyper-V - Windows 8"
    Comments Send by mail Print  Save  Delicious 
    Date: Wednesday, 28 Mar 2012 00:37

    In my last post we talked about PowerShell Session Configurations  and specifically about the new RunAs functionality in PowerShell 3.0.  But there’s some other incredibly cool and powerful functionality within session configurations – Session Configuration Files.  You can see the full beta documentation on Session Configuration Files on TechNet but I am going to focus on a few specific features.

    ModulesToImport and VisibleCmdlets

    When you create a new PSSessionConfiguration file you can specify what modules to import and more specifically what cmdlets, aliases, types etc… will be visible to the user.  Using this functionality we can create PSSessions that will only allow specific users to do very specific actions such as starting or stopping a VM.  In the example below I create a configuration that will only allow users to use the Get-VM* cmdlet along with Start-VM and Stop-VM.
    New-PSSessionConfigurationFile -Path C:\psSessions\HyperVRemoteLimitedUser.pssc `
        -SessionType RestrictedRemoteServer `
        -LanguageMode RestrictedLanguage `
        -ModulesToImport Hyper-V `
        -VisibleCmdlets @("Get-VM*", "Start-VM", "Stop-VM") `

    Register-PSSessionConfiguration -Name "HyperVRemoteLimitedUser" `
                            -Path C:\psSessions\HyperVRemoteLimitedUser.pssc `
                            -SessionType DefaultRemoteShell -AccessMode Remote

    When a remote users connects to this session they will only be able to use cmdlet’s meting those specifications…
    PS C:\> $session = New-PSSession -ComputerName 37-4611K2615L -ConfigurationName HyperVRemoteLimitedUser
    PS C:\> Enter-PSSession $session
    [37-4611K2615L]: PS>get-vm
    Name  State CPUUsage(%) MemoryAssigned(M) MemoryDemand(M) MemoryStatus Uptime   Status             ReplicationState
    ----  ----- ----------- ----------------- --------------- ------------ ------   ------             ----------------
    Test  Off   0           0                 0                            00:00:00 Operating normally Disabled
    Test3 Off   0           0                 0                            00:00:00 Operating normally Disabled


    [37-4611K2615L]: PS>new-vm
    The term 'New-VM' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the
    spelling of the name, or if a path was included, verify that the path is correct and try again.
        + CategoryInfo          : ObjectNotFound: (New-VM:String) [], CommandNotFoundException
        + FullyQualifiedErrorId : CommandNotFoundException

    [37-4611K2615L]: PS>get-host
    The term 'Get-Host' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the
    spelling of the name, or if a path was included, verify that the path is correct and try again.
        + CategoryInfo          : ObjectNotFound: (Get-Host:String) [], CommandNotFoundException
        + FullyQualifiedErrorId : CommandNotFoundException

    [37-4611K2615L]: PS>Get-VMSwitch
    Name     SwitchType NetAdapterInterfaceDescription
    ----     ---------- ------------------------------
    External External   Microsoft Network Adapter Multiplexor Driver

    Creating Multiple Configurations For Different Users

    In my last post I provided a handy script New-SSDLForAdGroup to use with Register-PSSessionConfiguration.  Combining that with PSSessionConfigurationFiles – I’m going to create three different session types depending on the user.

    Function New-SSDLForADGroup
    {
    param(
        [String]$GroupName = [String]::Empty
        )
        try {
        #retreave the default SSDL as a base
        $defaultSSDL = (Get-Item WsMan:\localhost\service\rootSDDL).Value
        $isContainer = $false
        $isDS = $false
        $SecurityDescriptor = New-Object -TypeName `
            Security.AccessControl.CommonSecurityDescriptor `
            $isContainer, $isDS, $defaultSSDL

        #remove the default groups (Administrators and Interactive User)
        while($SecurityDescriptor.DiscretionaryAcl.Count -gt 0)
        {
            $ssdl = $SecurityDescriptor.DiscretionaryAcl[0]
            $SecurityDescriptor.DiscretionaryAcl.RemoveAccess(
                [System.Security.AccessControl.AccessControlType]::Allow,
                $ssdl.SecurityIdentifier,
                $ssdl.AccessMask,
                $ssdl.InheritanceFlags,
                $ssdl.PropagationFlags) | Out-Null
        }

        #get the SID for the specified Group and add it to the SSDL
        $AdminGroup = New-Object Security.Principal.NTAccount $GroupName
        $AdminGroupSid = $AdminGroup.Translate(`
            [Security.Principal.SecurityIdentifier]).Value

        $SecurityDescriptor.DiscretionaryAcl.AddAccess(
            [System.Security.AccessControl.AccessControlType]::Allow,
            $AdminGroupSid,
            268435456, #full control all operations
            [System.Security.AccessControl.InheritanceFlags]::None,
            [System.Security.AccessControl.PropagationFlags]::None) | Out-Null

        return $SecurityDescriptor.GetSddlForm("All")
        }
        catch [Exception] {
            Write-Error -Message "Failed To Generate SSDL (review inner exception):`n $_.Message" `
                -Exception $_.Exception
        }
    }

    $HyperVRemoteAdminRunAs = Get-Credential "hyper-v\HyperVRemoteCommands"

    #Limited Users
        $ssdlForSession = New-SSDLForADGroup -GroupName "hyper-v\LimitedUsers"
        New-PSSessionConfigurationFile -Path C:\psSessions\HyperVRemoteLimitedUser.pssc `
            -SessionType RestrictedRemoteServer `
            -LanguageMode RestrictedLanguage `
            -ModulesToImport Hyper-V `
            -VisibleCmdlets @("Get-VM*", "Start-VM", "Stop-VM") `

        Register-PSSessionConfiguration -Name "HyperVRemoteLimitedUser" `
            -Path C:\psSessions\HyperVRemoteLimitedUser.pssc `
            -SessionType DefaultRemoteShell -AccessMode Remote `
            -NoServiceRestart -Force `
            -SecurityDescriptorSddl $ssdlForSession `
            -RunAsCredential $HyperVRemoteAdminRunAs

    #PowerUsers
        #Only use the cmdlet's in the allowed modules
        $moduleList = @("Hyper-V")
        $cmdLets = $null
        foreach ($Module in $moduleList)
        {
            Import-Module $Module
            $Mod = Get-Module $Module
            $cmdLets += $Mod.ExportedCmdlets.Keys
        }

        $ssdlForSession = New-SSDLForADGroup -GroupName "hyper-v\hv-PowerUsers"
        New-PSSessionConfigurationFile -Path C:\psSessions\HyperVRemotePowerUser.pssc `
            -SessionType RestrictedRemoteServer `
            -LanguageMode RestrictedLanguage `
            -ModulesToImport $moduleList `
            -VisibleCmdlets ([Array]$cmdLets)
           
        Register-PSSessionConfiguration -Name "HyperVRemotePowerUser" `
            -Path C:\psSessions\HyperVRemotePowerUser.pssc `
            -SessionType DefaultRemoteShell -AccessMode Remote `
            -NoServiceRestart -Force `
            -SecurityDescriptorSddl $ssdlForSession `
            -RunAsCredential $HyperVRemoteAdminRunAs

    #ServerAdmins
        $ssdlForSession = New-SSDLForADGroup -GroupName "hyper-v\hv-admins"
        Register-PSSessionConfiguration -Name "HyperVServerAdmin" `
            -SessionType DefaultRemoteShell -AccessMode Remote `
            -NoServiceRestart -Force `
            -SecurityDescriptorSddl $ssdlForSession `
            -RunAsCredential $HyperVRemoteAdminRunAs

    Restart-Service -Name WinRM –Force

    Taylor Brown
    Hyper-V Enterprise Deployment Team
    taylorb@microsoft.com
    http://blogs.msdn.com/taylorb

    WS08R2-HyperV_v_rgb

    Author: "Taylor Brown [Microsoft Hyper-V]" Tags: "Hyper-V - Windows 8"
    Comments Send by mail Print  Save  Delicious 
    Date: Monday, 26 Mar 2012 23:09

    In response to my recent set of posts someone pointed me to a new PowerShell 3.0 feature of PowerShell sessions – RunAs… I had seen people use PowerShell session configurations in the past but I had never really seen a need to use them myself that is until now.  With the challenges of constrained delegation and some of the limitations of CredSSP the ability to define an account on your Hyper-V hosts for which all commands will run in the context of can be very powerful and that’s exactly what this provides.

    Basic Configuration

    GPOFor example let’s say I defined a new domain user “HyperVRemoteCommands” and I restrict the account as I would any other service account – no interactive login, no remote desktop login etc…  and I add it to the local Hyper-V Administrators group on my Windows 8 Hyper-V servers which will give that account permissions to all of Hyper-V (creating VM’s, deleting VM’s, creating switches etc…)  If I’m using SMB storage, which I am, I would also add that account to the security group that had permissions on my SMB storage.
    Now I’ve got a user that can do all of my Hyper-V administration but has no login rights – basically just like an SCVMM service account or a SQL account.  Here’s the cool part you can use the Register-PSSessionConfiguration cmdlet which with PowerShell 3.0 has a new parameter RunAsCredential to create a new WSMan session that will run as that user account.  Here’s an Example:
    Register-PSSessionConfiguration -Name HyperVRemoteAdmin -SessionType DefaultRemoteShell -AccessMode Remote -RunAsCredential (Get-Credential "hyper-v\HyperVRemoteCommands")

    Now from a remote machine we can connect to that session and execute commands just as we normally would – however they are being run in the context of the RunAs account.
    $session = New-PSSession -ComputerName 37-4611K2615L -ConfigurationName HyperVRemoteAdmin
    Invoke-Command -Session $session -ScriptBlock {New-VM –Name Demo -Path \\hv-w8-beta-smb\VirtualMachines\Demo}

    Advanced Security

    The question that remains is who has access to connect to this session and use these permissions?  By default access is same for the new session as the default WSMan instance – which is the local administrators group and interactive users, this can be overridden very easily with custom permissions.  If you specify the ShowSecurityDescriptorUI flag the cmdlet will prompt you for the credentials requires to this configuration.  There’s another parameter you can specify as well –SecurityDescriptorSddl which is much more script friendly but does require some work as it takes an Sddl string. 

    So I wrote a function to generate one – it takes the default WSMan SSDL – removes all of the permissions (local administrators group and interactive users) and then adds a domain security group with full permissions.

    Function New-SSDLForADGroup
    {
    param(
        [String]$GroupName = [String]::Empty
        )
        try {
        #retreave the default SSDL as a base
        $defaultSSDL = (Get-Item WsMan:\localhost\service\rootSDDL).Value
        $isContainer = $false
        $isDS = $false
        $SecurityDescriptor = New-Object -TypeName `
            Security.AccessControl.CommonSecurityDescriptor `
            $isContainer, $isDS, $defaultSSDL

        #remove the default groups (Administrators and Interactive User)
        while($SecurityDescriptor.DiscretionaryAcl.Count -gt 0)
        {
            $ssdl = $SecurityDescriptor.DiscretionaryAcl[0]
            $SecurityDescriptor.DiscretionaryAcl.RemoveAccess(
                [System.Security.AccessControl.AccessControlType]::Allow,
                $ssdl.SecurityIdentifier,
                $ssdl.AccessMask,
                $ssdl.InheritanceFlags,
                $ssdl.PropagationFlags) | Out-Null
        }

        #get the SID for the specified Group and add it to the SSDL
        $AdminGroup = New-Object Security.Principal.NTAccount $GroupName
        $AdminGroupSid = $AdminGroup.Translate(`
            [Security.Principal.SecurityIdentifier]).Value

        $SecurityDescriptor.DiscretionaryAcl.AddAccess(
            [System.Security.AccessControl.AccessControlType]::Allow,
            $AdminGroupSid,
            268435456, #full control all operations
            [System.Security.AccessControl.InheritanceFlags]::None,
            [System.Security.AccessControl.PropagationFlags]::None) | Out-Null

        return $SecurityDescriptor.GetSddlForm("All")
        }
        catch [Exception] {
            Write-Error -Message "Failed To Generate SSDL (review inner exception):`n $_.Message" `
                -Exception $_.Exception
        }
    }

    Now if we combine that with some active directory scripting to grab all of the Hyper-V Servers in my security group and run the register command on them then all of my Hyper-V hosts will be setup to run delegated commands for any user in my Hyper-V administrators group.  You may notice that I specify –NoServiceRestart in the first command and then restart the service in the second – the reason for this is to ensure that if the first command failed I would get full exception handling.

    $HyperVServersGroup = "hyper-v\hv-hosts"
    $HyperVAdminsGroup = "hyper-v\hv-admins"
    $HyperVRemoteAdminRunAs = Get-Credential "hyper-v\HyperVRemoteCommands"

    $HvServersAD = Get-ADGroupMember $HyperVServersGroup
    $ssdlForSession = New-SSDLForADGroup -GroupName "hyper-v\hv-admins"

    $remoteScriptBlock = {Register-PSSessionConfiguration -Name "HyperVRemoteAdmin" `
                            -SessionType DefaultRemoteShell -AccessMode Remote `
                            -NoServiceRestart -Force -SecurityDescriptorSddl `
                            $args[0] -RunAsCredential $args[1]}

    foreach ($computer in $HvServersAD)
    {
        Invoke-Command -ComputerName $computer.Name -ScriptBlock $remoteScriptBlock `
            -ArgumentList @($ssdlForSession, $HyperVRemoteAdminRunAs)

        Invoke-Command -ComputerName $computer.Name `
            -ScriptBlock {Restart-Service -Name WinRM -Force} -ErrorAction Ignore
    }

    Taylor Brown
    Hyper-V Enterprise Deployment Team
    taylorb@microsoft.com
    http://blogs.msdn.com/taylorb

    WS08R2-HyperV_v_rgb

    Author: "Taylor Brown [Microsoft Hyper-V]" Tags: "Hyper-V - Windows 8"
    Comments Send by mail Print  Save  Delicious 
    Date: Saturday, 24 Mar 2012 00:05

    In reference to Enabling Hyper-V Remote Management - Configuring Constrained Delegation For SMB and Highly Available SMB and Enabling Hyper-V Remote Management - Configuring Constrained Delegation For Non-Clustered Live Migration I’ve had some people ask me about scripting these settings… Well in the first post there was the optional step of creating a security group for all of your Hyper-V servers – there’s actually another reason that I like to do this.

    Here’s the script I use… It takes the name of the security group, the name of the SMB server and wither or not live migration should be enabled.  This does require that you have the Active Directory PowerShell module.

    $HyperVServersGroup = "hv-hosts"
    $SMBServer = "HV-W8-BETA-SMB"
    $EnableLiveMigration = $true

    $SMBServerAD = Get-ADComputer $SMBServer
    $AllowedToDelegateToSMB = @(
        ("cifs/"+$SMBServerAD.Name),
        ("cifs/"+$SMBServerAD.DNSHostName))

    $HvServersAD = Get-ADGroupMember $HyperVServersGroup

    for ($serverCounter = 0; $serverCounter -lt $HvServersAD.Count; $serverCounter++)
    {
        $AllowedToDelegateTo = $AllowedToDelegateToSMB
        if ($EnableLiveMigration)
        {
            for ($deligateCounter = 0; $deligateCounter -lt $HvServersAD.Count; $deligateCounter++)
            {
                if ($deligateCounter -ne $serverCounter)
                {
                    $deligationServer = $HvServersAD[$deligateCounter] | Get-ADComputer
                    $AllowedToDelegateTo += @(
                        ("Microsoft Virtual System Migration Service/"+$deligationServer.Name),
                        ("Microsoft Virtual System Migration Service/"+$deligationServer.DNSHostName))      
                }
            }
        }
        ($HvServersAD[$serverCounter] | Get-ADComputer) | Set-ADObject -Add @{"msDS-AllowedToDelegateTo"=$AllowedToDelegateTo}
    }

    Taylor Brown
    Hyper-V Enterprise Deployment Team
    taylorb@microsoft.com
    http://blogs.msdn.com/taylorb

    WS08R2-HyperV_v_rgb

    Author: "Taylor Brown [Microsoft Hyper-V]" Tags: "Hyper-V - Windows 8"
    Comments Send by mail Print  Save  Delicious 
    Date: Friday, 23 Mar 2012 23:53

    You may have already read my previous two posts on Hyper-V remote management using the UI and configuring Constrained Delegation, for some people that will not be an option or is just undesirable...  Well with Windows 8 and the joy of PowerShell we have another option.  Many of the new Hyper-V PowerShell cmdlets (http://technet.microsoft.com/en-us/library/hh848559.aspx) take a computername parameter to allow for remote usage however if you are creating a virtual machine using SMB storage or if your are live migrating a VM you run into the same double hop constrained delegation problem as with the UI.  Luckily we have PowerShell remoting or WinRM remoting more specifically.

    Overview_webGoing back to the example I’ve been using we have a two node Windows Server 8 Scale-Out file server cluster, two standalone Hyper-V Servers and a remote management workstation.  In this case we will be using PowerShell from the management workstation as opposed to the Hyper-V UI.  The other nice part about PowerShell remoting is that your management workstation could be of a different domain or no domain at all depending on how you choice to send the credentials.



    Creating a New VM Remotely with SMB Storage – Failure

    I’ll start with the error you will get if you try to create a VM remotely using SMB storage in Beta – the error message is wrong (it’s a bug and already fixed) but non the less you can see that using ComputerName parameter with the VM on an SMB share it fails.
    PS C:\Windows\system32> New-VM -Name "VMOverSMB" -Path \\hv-w8-beta-smb\VirtualMachines -ComputerName 37-4611K2615L
    New-VM : The Virtual Machine Management Service on host '37-4611K2615L' is not running.
    At line:1 char:1
    + New-VM -Name "VMOverSMB" -Path \\hv-w8-beta-smb\VirtualMachines -ComputerName 37 ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [New-VM], VirtualizationOperationFailedException
        + FullyQualifiedErrorId : Microsoft.HyperV.PowerShell.Commands.NewVMCommand

    Credential Delegation – CredSSP/Kerberos

    In order to avoid the double hop and credential delegation issues we need to issue the command in the context of the Hyper-V server.  The easiest way to accomplish this is by using CredSSP and WsMan/WinRM.  By default CredSSP is disabled or more specifically the “AllowFreshCredentials” and “Allow CredSSP authentication” polcies are disabled you can either enable these via group policy or you can enabled them via the Enable-WSManCredSSP cmdlet.  I utilize group policy to enable CredSSP for my environment and have it pretty well locked down such that only systems on my domain and specific trusted domains can provide credentials and further more WinRM only listens on specific IP ranges.

    Enable-WSManCredSSP -Role Client -DelegateComputer "*.hyper-v.selfhost.corp.microsoft.com"
    Enable-WSManCredSSP -Role Server

    It is worth stating the Kerberos delegation is also an option – it does carry with it some caveats as well.  When using Kerberos delegation you have to enable unconstrained delegation on the computer account and unconstrained delegation and constrained don’t seem to get along so it prevents Hyper-V remote UI management.

    Using Credential Delegation

    There are a few ways in PowerShell to use credential delegation – you can use Invoke-Command with a script block, computer name, credentials or you can create a PSSession and either pass that to InvokeCommand or enter the PSSession and execute the commands locally.  I’ll start with the PSSession example as it breaks down the concepts well.

    The first step is getting the credentials that will be used on the remote machine – this is done via the Get-Credential cmdlet which will popup a standard Windows credential dialog, in my case I provide my username so I don’t have to type it in again.  The next step is to create a session via the New-PSSession cmdlet using CredSSP as my authentication and the credentials I got in step 1.  Next I enter the session with Enter-PSSession, after this command I am effectively typing on the remote computer and that’s evidenced by the computer name before my command prompt.  At this point I can create the New VM and away we go.
    PS C:\> $remotingCreds = Get-Credential -Credential "hyper-v\taylorb"
    PS C:\> $Session = New-PSSession -Authentication Credssp -Credential $remotingCreds  -ComputerName "37-4611K2617L"
    PS C:\> Enter-PSSession $Session
    [37-4611K2617L]: PS C:\Users\taylorb\Documents> New-VM -Name "VMOverSMB" -Path \\hv-w8-beta-smb\VirtualMachines
    Name      State CPUUsage(%) MemoryAssigned(M) MemoryDemand(M) MemoryStatus Uptime   Status             ReplicationState
    ----      ----- ----------- ----------------- --------------- ------------ ------   ------             ----------------
    VMOverSMB Off   0           0                 0                            00:00:00 Operating normally Disabled

    In this example the first two steps are the same but as opposed to entering the PS Sessions I use Invoke-Command to execute a script block on the remote server.
    PS C:\> $remotingCreds = Get-Credential -Credential "hyper-v\taylorb"
    PS C:\> $Session = New-PSSession -Authentication Credssp -Credential $remotingCreds -ComputerName "37-4611K2615L"
    PS C:\> Invoke-Command -Session $Session -ScriptBlock {New-VM -Name "VMOverSMB" -Path \\hv-w8-beta-smb\VirtualMachines}

    We can also use Invoke-Command without a PSSession (though it will just create one for you and close it when it’s done).
    PS C:\> Invoke-Command -Authentication Credssp -Credential (Get-Credential) -ComputerName "37-4611K2617L" -ScriptBlock {New-VM -Name "VMOverSMB" -Path \\hv-w8-beta-smb\VirtualMachines}

    Or if you have unconstrained delegation enabled you can use Kerberos – also note that with Kerberos there is no need to provide credentials as the current users credentials will be delegated for you.
    PS C:\> Invoke-Command -Authentication Kerberos -ComputerName "37-4611K2617L" -ScriptBlock {New-VM -Name "VMOverSMB" -Path \\hv-w8-beta-smb\VirtualMachines}

    Live Storage Migration and Live Migration

    These seem to be the biggest challenges for remote management – since they implicitly require a third hop I wanted to make sure there where some samples…

    PS C:\> $remotingCreds = Get-Credential -Credential "hyper-v\taylorb"
    PS C:\> $Session = New-PSSession -Authentication Credssp -Credential $remotingCreds  -ComputerName "37-4611K2617L"
    PS C:\> Invoke-Command -Session $Session -ScriptBlock {Move-VM -Name "VMOverSMB" -DestinationHost "37-4611K2615L"}

    PS C:\> $remotingCreds = Get-Credential -Credential "hyper-v\taylorb"
    PS C:\> $Session = New-PSSession -Authentication Credssp -Credential $remotingCreds -ComputerName "37-4611K2617L"
    PS C:\> Invoke-Command -Session $Session -ScriptBlock {Move-VMStorage -VMName LocalVM -DestinationStoragePath \\hv-w8-beta-smb\VirtualMachines\LocalVM

    Taylor Brown
    Hyper-V Enterprise Deployment Team
    taylorb@microsoft.com
    http://blogs.msdn.com/taylorb

    WS08R2-HyperV_v_rgb

    Author: "Taylor Brown [Microsoft Hyper-V]" Tags: "Hyper-V - Windows 8"
    Comments Send by mail Print  Save  Delicious 
    Date: Wednesday, 21 Mar 2012 00:40

    In Windows Server 8 we added the ability to live migrate virtual machines without the requirement of a cluster i.e. standalone live migration.  For this feature to work the storage the virtual machine is using must be available to both Hyper-V severs which implies that it’s hosted on an SMB share – we also have the ability to perform a live storage migration in concert with the virtual machine live migration in Windows Server 8 but I’ll get to that latter. If you read my last post on Enabling Hyper-V Remote Management - Configuring Constrained Delegation For SMB and Highly Available SMB which discusses configuring the Hyper-V severs to delegate credentials to the SMB server this process is similar to that and the configuration of the SMB delegation is a prerequisite for this post.

    overview_web

    Going back to the example from my last post let’s take an environment similar to this – we have a two node Windows Server 8 Scale-Out file server cluster, two standalone Hyper-V servers and a remote management workstation.  In the last post we configured constrained delegation between the two Hyper-V servers and the SMB server which allowed us to create a new virtual machine on the one of the Hyper-V servers with the virtual machines storage residing on the SMB share.  Now we want to live migrate that virtual machine to the second Hyper-V server.  In order to accomplish this we again must enable constrained delegation.


    Overview of Process

    1. Configure Constrained Delegation Between the two Hyper-V Servers
    2. Enable Live Migration on Both Hyper-V Servers
    3. Live Migrate The Virtual Machine

    Configure Constrained Delegation Between the two Hyper-V Servers

    For Each Hyper-V Server…

    1. Using The Active Directory Users and Computers Dialog Open The Properties Dialog On The Computer Account and Select The Delegation Tab 
      blogs.msdn.com_taylorb.fix3
    2. “Trust this computer for deliberation to the specified services only” Correction Use Kerberos only works and “Use any authentication protocol”  should already be selected and the CIFS service should be enabled with the SMB server.
    3. Select “Add” and Provide the Name Of The Other Hyper-V Server(s) (37-4611K2717L in my example)
      2 blogs.msdn.com_taylorb.fix1

    Enable Live Migration on Both Hyper-V Servers

    For each Hyper-V Server you need to enable live migration this is disabled by default as a security precaution as not every server may want to allow migrations to and from it. 

    1. From the Hyper-V Manager UI open the Hyper-V Settings
    2. Select the Live Migration node
    3. Check the “Enable incoming and outgoing live migrations” option
    4. Select “Use Kerberos” from the authentication protocol – if you don’t select this when you try to live migrate using a remote UI you will get an error (here’s the error message so bing will find it when someone forgets this step :)
      “Virtual machine migration failed at migration source. Failed to establish a connection with host <destination> The credentials supplied to the package where not recognized (0x8009030D). Failed to authenticate the connection at the source host: no suitable credentials available.”
    5. Optionally you can specify the networks that allow live migrations over them – this is recommended to prevent live migrations (which are unencrypted) from going over public networks.
      4

    Live Migrate The Virtual Machine

    We are now ready to live migrate the virtual machine.

    1. From the Hyper-V Manager Right Click on The Virtual Machine and Select Move
      5
    2. Select “Move the virtual machine” to specify a live migration
      6
    3. From the Move Options Page Select “Move only the virtual machine” as the VHD and configuration are already on our SMB server
      7
    4. Select Finish To Start the Live Migration
      89

    Done…

     

    Taylor Brown
    Hyper-V Enterprise Deployment Team
    taylorb@microsoft.com
    http://blogs.msdn.com/taylorb

    WS08R2-HyperV_v_rgb

    Author: "Taylor Brown [Microsoft Hyper-V]" Tags: "Hyper-V - Windows 8"
    Comments Send by mail Print  Save  Delicious 
    Date: Tuesday, 20 Mar 2012 17:46

     

    blogs.msnd.com_taylorb35Windows Server 8 brings support for storing and running Hyper-V virtual machines on SMB2.2 file shares, which is pretty handy, especially with the new Scale-Out/Continuously Available file server features in Windows Server 8.  However it does bring one challenge to the table – if you want to remotely manage your Hyper-V servers and use SMB then Kerberos's single hop tickets become a problem.

    The basic issue is that when you login to a domain and want to access a remote machine the domain issues a security token which is presented to the remote server to saying who you are and what not – however just like a concert ticket once it’s scanned at the door it’s no good.  This means that in the case of Hyper-V remote management your token is only valid between the computer running the UI and the Hyper-V server so if/when you try to configure a virtual machine to use resources on a third computer there is no longer a valid token to ensure that you, the person configuring that virtual machine, should have access to the resources on the third machine.  Now once the VM has been configured the remote resources are accessed in the context of the Hyper-V servers computer account but during virtual machine creation or when attaching VHDs/ISOs to the VM we have to ensure that the user that’s performing that operation also has access to those resource and isn’t just piggy backing on the Hyper-V servers rights to access those files.

    Overview_webIn order to solve this challenge we need to enable constrained delegation which tells active directory that between two computers, in this case the Hyper-V server and the SMB server, and for specific services, in this case CIFS/SMB, its allowed to effectively re-issue the token for the user – kind of like a re-admission stamp.  For the examples below let’s take an environment similar to this – we have a two node Windows Server 8 Scale-Out file server cluster, two standalone Hyper-V Servers and a remote management workstation.  In this environment we want to create an SMB share and then create a new VM on that share.  If we just create the SMB share and try to create a virtual machine on that share creating the VM will fail with access denied or the operation has failed errors – so we have to configure the security and delegation.

     

    Please be aware that Hyper-V on Windows Server 2008 or R2 does not support virtual machines using SMB or any NAS storage – this is a new feature for Windows Server 8 and requires that the the SMB server support SMB 2.2.  See http://technet.microsoft.com/en-us/library/dd183729.aspx for more details.


    Overview Of Process

    1. Create Active Directory Groups For Hyper-V Server and Hyper-V Administrative Users (optional)
    2. Configure Constrained Delegation Between Hyper-V Servers and SMB Server
    3. Create SMB Share For Virtual Machines
    4. Create Virtual Machines

    Create Active Directory Groups For Hyper-V Server and Hyper-V Administrative Users (optional)
    This is an optional step – you can chose to specify all of the computer and user accounts specifically during section 3 “Create SMB Share For Virtual Machines” steps 7.2, 7.3, 8.2, 8.3.  I like utilizing security groups as it ensures that as I change or grow an environment that new servers and users get access to resources in a uniform way.

    1. Create A New Security Group Which Will Contain All Hyper-V Servers That Will Host VMs On The SMB Share (hv-hosts in my example)
      blogs.msnd.com_taylorb12
    2. Add The Computer Accounts Of All Hyper-V Servers To The Security Group (37-4611K2615L and 37-4611K2617L in my example)
      blogs.msnd.com_taylorb14 blogs.msnd.com_taylorb13
    3. Create A New Security Group Which Will Contain All Users Accounts Of Admins That Will Create VMs On The SMB Share (hv-admins in my example)
    4. Add The User Accounts of The Admins To The Security Group

    Configure Constrained Delegation Between Hyper-V Servers and SMB Server

    For Each Hyper-V Server…

    1. Using The Active Directory Users and Computers Dialog Open The Properties Dialog On The Computer Account and Select The Delegation Tab
      blogs.msnd.com_taylorb2
    2. Select “Trust this computer for deliberation to the specified services only” Correction Use Kerberos only works and “Use any authentication protocol”
       blogs.msdn.com_taylorb.fix2
    3. Select “Add” and Provide the Name Of The SMB Server (or Cluster Access Point for Scale Out of Highly Available Shares) (hv-w8-beta-smb in my example)
      blogs.msnd.com_taylorb4
    4. Select The “cifs” Service – CIFS Is Another Name For SMB
      blogs.msnd.com_taylorb5 blogs.msdn.com_taylorb.fix3

    Create SMB Share For Virtual Machines

    These steps are specific to Windows 8 Consumer Preview (Beta) – if you are using a different OS the pertinent steps are 7.2, 7.3, 8.2, 8.3

    1. Using Server Manager Select the “File and Storage Services” Tab On the Left Side Then “Shares” From The Pop Out Menu
      blogs.msnd.com_taylorb17
    2. Select The Link To Create a New Share or From Tasks Select “Create a new share”
    3. Select the “SMB Share – Server Application” From The Profile List (this will give you the correct options in the wizard)
      blogs.msnd.com_taylorb27
    4. Select the Server and Volume (or path) Where You Want To Create the Share (hv-w8-beta-smb and c:\clusterstorage\volume1 in my example)
      blogs.msnd.com_taylorb28
    5. Provide a Name For the Share (VirtualMachines in my example)
      blogs.msnd.com_taylorb29
    6. Ensure That “Enable Continuous availability” Is Selected
      blogs.msnd.com_taylorb30
    7. On The Permissions Tab Select Customize Permissions
      1. The Following Few Steps are Optional – I Personally Don’t Like Inherited Permissions or Local Groups Because They Reduce My Control Over Access
        1. Select “Disable Inheritance” and “Convert inherited permissions into explicit permissions on this object”
          blogs.msnd.com_taylorb33
        2. Remove The Following Permissions: Users (Special), Users (Read & Execute), Administrators (Full Control/This Folder), Administrators (Full Control/Subfolders)
          blogs.msnd.com_taylorb34
        3. Change The Owner From Administrators To The Active Directory Group Created Earlier Containing The Hyper-V Administrators, or another group as desired (hv-admins in my example)
          blogs.msnd.com_taylorb18
      2. Add Full Control Permissions For The Hyper-V Administrators Using The Active Directory Group Created Earlier (hv-admins in my example)
        blogs.msnd.com_taylorb19
      3. Add Full Control Permissions For The Hyper-V Servers Using The Active Directory Group Created Earlier (hv-hosts in my example)
        blogs.msnd.com_taylorb20
    8. On The Share Tab 
      1. Remove The Allow Everyone Entry
      2. Create a Full Control Entry For The Hyper-V Administrators Using The Active Directory Group Created Earlier (hv-admins in my example)
      3. Create a Full Control Entry For The Hyper-V Servers Using The Active Directory Group Created Earlier (hv-hosts in my example)
        blogs.msnd.com_taylorb23
    9. Verify Your Settings and Create the Share
      blogs.msnd.com_taylorb25blogs.msnd.com_taylorb26

    Create Virtual Machines

    1. Using Hyper-V Manager Open The New Virtual Machine Wizard
      blogs.msnd.com_taylorb37
    2. Specify a Name For the Virtual Machine and The Location as Being On The SMB Share Previously Created (this is the location that will contain the configuration, smart paging and save state files for the virtual machine)
      blogs.msnd.com_taylorb38
    3. Similarly Specify A VHD (VHDx) Location On The SMB Share For the Virtual Machine
      blogs.msnd.com_taylorb39
    4. Complete The Wizard And You’ve Got a VM Created on SMB All Done Via Remote Management
      blogs.msnd.com_taylorb40

    Done…

    I would like to thank Jose Barreto – his blog post Using Constrained Delegation to remotely manage a server running Hyper-V that uses CIFS/SMB file shares gives a great overview of this process as well.

    Taylor Brown
    Hyper-V Enterprise Deployment Team
    taylorb@microsoft.com
    http://blogs.msdn.com/taylorb

    WS08R2-HyperV_v_rgb

    Author: "Taylor Brown [Microsoft Hyper-V]" Tags: "Hyper-V - Windows 8"
    Comments Send by mail Print  Save  Delicious 
    Date: Thursday, 15 Mar 2012 16:31

    It’s been a busy couple months (years) but Windows Server “8” Beta has shipped and is publically available for download,  I’m personally very proud of all the work that went into Windows Server “8” especially in Hyper-V (maybe I’m biased) but really across the whole OS…  In the coming days, weeks, months I’m planning a series of posts highlighting some of the new scenarios enabled by the new features in Hyper-V and in corporation with several of the other new features from our partner teams. If you haven’t yet been to TechNet to see all the new features and functionality in Windows Server “8” Beta you should definitely take a look…

    Here’s a few particularly relevant links:

    Taylor Brown
    Hyper-V Enterprise Deployment Team
    taylorb@microsoft.com
    http://blogs.msdn.com/taylorb

    WS08R2-HyperV_v_rgb

    Author: "Taylor Brown [Microsoft Hyper-V]" Tags: "Hyper-V - Windows 8"
    Comments Send by mail Print  Save  Delicious 
    Date: Wednesday, 07 Mar 2012 21:12

    In response to a few of my old posts Hyper-V WMI Using PowerShell Scripts – Part 5 (Creating Virtual Switchs/Networks) and Hyper-V V2: Guest Only External Networks + Add Roles Wizard Changes I’ve had a lot of people ask me how to create external virtual switches that do not allow management traffic i.e. guest only external switches or vm only external switches. 

    So Here you go – do note that I am using my ProcessWMIJob function from my past posting Hyper-V WMI: Rich Error Messages for Non-Zero ReturnValue (no more 32773, 32768, 32700…).

    function CreateSwitch
    {
    param
    (
        [string] $SwitchName = $null,
        [string] $PhysicalNICName = $null 
    )
    
        $VirtualSwitchService = Get-WmiObject -Namespace "root\virtualization"  -Class "Msvm_VirtualSwitchManagementService"
        
        $CreatedSwitch = ($VirtualSwitchService.CreateSwitch([guid]::NewGuid().ToString(), $SwitchName, "1024","") `
            | ProcessWMIJob $VirtualSwitchService "CreateSwitch").CreatedVirtualSwitch
    
        $ExternalNic = Get-WmiObject -Namespace "root\virtualization" -Class "Msvm_ExternalEthernetPort" `
            -Filter "Name = '$PhysicalNICName'"
        
        $VirtualSwitchService.BindExternalEthernetPort($ExternalNic.__PATH) `
            | ProcessWMIJob $VirtualSwitchService "BindExternalEthernetPort"
        
        $ExternalNicEndPoint = $ExternalNic.GetRelated("CIM_LanEndpoint")
        
        $ExternalSwitchPort = ($VirtualSwitchService.CreateSwitchPort($CreatedSwitch, `
            [Guid]::NewGuid().ToString(), "ExternalSwitchPort", "") `
            | ProcessWMIJob $VirtualSwitchService "CreateSwitchPort").CreatedSwitchPort
            
        $VirtualSwitchService.ConnectSwitchPort($ExternalSwitchPort, $ExternalNicEndPoint) `
            | ProcessWMIJob $VirtualSwitchService "ConnectSwitchPort"
    }

    The process is pretty straight forward – and even more so if you consider the Hyper-V networking model…

    1. We create a new virtual switch using the CreateSwitch(…) API.  think of this as racking a new physical switch
    2. We identify the external network adapter we are going to connect to.  think of this as identifying to path port you will connect the switch to
    3. We bind the Hyper-V virtual switch driver to the physical NIC with the BindExternalEthernetPort(…) API.  think of this as plugging one end of a cable into the patch panel
    4. We identify the Lan Endpoint of the physical nic.  think of this as finding the other end of the cable from the patch panel
    5. We create an external port of the virtual switch we created in step 1.  think of this as configuring and enabling the uplink port on the new switch
    6. We connect the ports… Plug the uplink cable into the new switch.

     

    Taylor Brown
    Hyper-V Enterprise Deployment Team
    taylorb@microsoft.com
    http://blogs.msdn.com/taylorb

    WS08R2-HyperV_v_rgb

    Author: "Taylor Brown [Microsoft Hyper-V]" Tags: "WMI, Hyper-V - Windows Server 2008 R2"
    Comments Send by mail Print  Save  Delicious 
    Date: Tuesday, 10 Jan 2012 18:50

    Today we released a fix for to resolve an issue that can lead to guest VM’s crashing after a live migration.  This issue only impacted virtual machines that where utilizing virtual SCSI controllers and was only seen under some specific stress conditions however if you have VM’s with SCSI controllers and utilize live migration than I would recommend investigating and installing this hotfix.

    http://support.microsoft.com/kb/2636573

    Article ID: 2636573 - Last Review: January 10, 2012 - Revision: 1.0

    FIX: The guest operating system may crash when you perform a live migration of Hyper-V virtual machines in a Windows Server 2008 R2 environment

     

    Symptoms

    In a Windows Server 2008 R2 environment, you perform a live migration of Hyper-V virtual machines. In this scenario, the guest operating system may crash. Additionally, you receive a Stop error message that resembles the following:

    STOP 0x000000D1 (parameter1, parameter2, parameter3, parameter4)
    DRIVER_IRQL_NOT_LESS_OR_EQUAL

    Resolution

    To resolve this problem, install this update on the host computer where the Hyper-V virtual machines are located.

    Update information
    To resolve this problem, install this update from Microsoft Windows Update (http://update.microsoft.com) .
    Additionally, you can install this update from the Microsoft Download Center.
    The following files are available for download from the Microsoft Download Center:

    Download the update package now. (http://www.microsoft.com/downloads/details.aspx?FamilyId=06c9e6e0-26de-44dc-a2e7-6a87fe0d5e76)
    Release Date: January 10, 2012
    For more information about how to download Microsoft support files, click the following article number to view the article in the Microsoft Knowledge Base:

    119591 (http://support.microsoft.com/kb/119591/ ) How to obtain Microsoft support files from online services

    Microsoft scanned this file for viruses. Microsoft used the most current virus-detection software that was available on the date that the file was posted. The file is stored on security-enhanced servers that help prevent any unauthorized changes to the file.

    Prerequisites
    To apply this hotfix, you must be running Windows Server 2008 R2 Service Pack 1 (SP1).
    For more information about how to obtain Service Pack 1 for Windows Server 2008 R2, click the following article number to view the article in the Microsoft Knowledge Base:

    976932 (http://support.microsoft.com/kb/976932/ ) Information about Service Pack 1 for Windows 7 and for Windows Server 2008 R2

    Registry information
    To use the hotfix in this package, you do not have to make any changes to the registry.
    Restart information

    You must restart the computer after you apply this hotfix.

    Taylor Brown
    Hyper-V Enterprise Deployment Team
    taylorb@microsoft.com
    http://blogs.msdn.com/taylorb

    WS08R2-HyperV_v_rgb

    Author: "Taylor Brown [Microsoft Hyper-V]" Tags: "Hyper-V - Windows Server 2008 R2"
    Comments Send by mail Print  Save  Delicious 
    Date: Tuesday, 02 Aug 2011 16:52

    The SQL CAT team has published a new whitepaper regarding dynamic memory best practices with Hyper-V…  If your virtualizing SQL I would highly recommend taking a look!

    Summary:
    Memory is a critical resource to Microsoft SQL Server workloads, especially in a virtualized environment where resources are shared and contention for shared resources can lead to negative impact on the workload. Windows Server 2008 R2 SP1 introduced Hyper-V Dynamic Memory, which enables virtual machines to make more efficient use of physical memory resources. Hyper-V Dynamic Memory treats memory as a shared resource that can be reallocated automatically among running virtual machines. There are unique considerations that apply to virtual machines that run SQL Server workloads in such environments. This whitepaper provides insight into considerations and best practices for running SQL Server 2008 R2 in Hyper-V Dynamic Memory configurations on Windows Server 2008 R2 SP1.

    To continue reading, please download the whitepaper: http://msdn.microsoft.com/en-us/library/hh372970.aspx

    Taylor Brown
    Hyper-V Enterprise Deployment Team
    taylorb@microsoft.com
    http://blogs.msdn.com/taylorb

    WS08R2-HyperV_v_rgb

    Author: "Taylor Brown [Microsoft Hyper-V]"
    Comments Send by mail Print  Save  Delicious 
    Date: Tuesday, 26 Apr 2011 19:00

    If you are running a cluster with Windows Server 2008 R2 SP1 and three or more nodes you should install this KB.

    KB Link: http://support.microsoft.com/kb/2531907

    Symptoms

    Consider the following scenario:

    • You configure a failover cluster that has three or more nodes that are running Windows Server 2008 R2 Service Pack 1 (SP1).
    • You have cluster disks that are configured in groups other than the Available Storage group or that are used for Cluster Shared Volumes (CSV).
    • These disks are online when you run the Validate SCSI Device Vital Product Data (VPD) test or the List Potential Cluster Disks storage validation test.
    In this scenario, the Validate SCSI Device Vital Product Data (VPD) test fails. Additionally, you receive an error message that resembles the following:

    Failed to get SCSI page 83h VPD descriptors for cluster disk <number> from <node name> status 2

    The List Potential Cluster Disks storage validation test may display a warning message that resembles the following:

    Disk with identifier <value> has a Persistent Reservation on it. The disk might be part of some other cluster. Removing the disk from validation set.

    Resolution

    The following hotfix resolves an issue in which the storage test runs on disks that are online and incorrectly not in the Available Storage group.
    The error and warning messages that are mentioned in the "Symptoms" section may also occur because of other issues such as storage problems or an incorrect configuration. Therefore, you should investigate other events, check the storage configuration, or contact your storage vendor if this issue still occurs after you install the following hotfix.

     

    Taylor Brown
    Hyper-V Enterprise Deployment Team
    taylorb@microsoft.com
    http://blogs.msdn.com/taylorb

    WS08R2-HyperV_v_rgb

    Author: "Taylor Brown [Microsoft Hyper-V]" Tags: "IT Professional, Hyper-V - Windows Serve..."
    Comments Send by mail Print  Save  Delicious 
    Previous page - Next page
    » You can also retrieve older items : Read
    » © All content and copyrights belong to their respective authors.«
    » © FeedShow - Online RSS Feeds Reader