Taylor Brown's Blog

Distribuir contenido
Sr. Software Developer in Test for Hyper-V Enterprise Deployment Validation Team
Actualizado: hace 1 día 4 horas

High Performance SQL Server Workloads on Hyper-V Whitepaper

Mar, 06/07/2010 - 19:28

A new whitepaper detailing high performance SQL workloads running in Hyper-V R2 virtual machines.  The paper can be downloaded here...  Below are a few highlights/examples from the paper.

Dedicated Passthough LUN’s vs VHD’s

Figure 3: I/O and disk latency for dedicated pass-through disks versus VHDs

Multi-Instance Throughput: Native versus Virtual (16 core server)

The results of this test are summarized as follows:

  • Slightly higher logical processor utilization is required to achieve the same throughput with virtualization due to minimal additional processor overhead.
  • Native instances and virtual instances achieve the same level of scalability.
  • I/O performance of ~5 percent for pass-through disks is greater than fixed-size VHDs as shown in Figure 3. Note that pass-through disks have an approximately one millisecond lower latency as compared to fixed-size VHDs.

Figure 4: Multi-Instance throughput: native instances versus virtual instances (16 cores)

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

Categorías: Virtualización

Getting More Information About You Cluster LUN’s (Part 3 of 3)

Jue, 01/07/2010 - 18:00
So here’s the scenario you need or want to figure out which LUN is which on your cluster…

On Tuesday I published part 1 where I utilized Get-ClusterParameter and the DiskUniqueIds property to enumerate LUN information for cluster storage, in part 2 I simplified that same approach.   In today’s post I am going to continue utilizing the Get-ClusterParameter again looking at the Physical Disk Private Properties however in this post I’ll be looking at the DiskIdGuid property.  This property contains the GUID for a physical disk formatted with as GPT.  Using this GUID we can match it with VDS and get all of the good information that VDS has about disks.

Method 1

This method is fully supported by Microsoft and is relatively strait forward.

Step 1: Import the FailoverClusters module into your PowerShell Window  
              Import-Module FailoverClusters
Step 2: Get the CSV object your interested in using the Get-ClusterSharedVolume cmdlet
              $csv = Get-ClusterSharedVolume –Name “MyCSV”
Step 3: Get the Cluster Parameters for the CSV object using Get-ClusterParameter
              $CSVParams = Get-ClusterParameter -InputObject $csv
Step 4: Filter to get just the DiskIdGuid 
              ($CSVParams | Where-object -FilterScript {$_.Name -eq "DiskIdGuid"}).Value

Ok now you’ve got the GUID for the LUN it will be something like {32443078-9afc-4c0a-b142-466f582a4051}.

Step 5: Start diskpart.exe
Step 6: Start iterating over disks using select disk <number> and then uniqueid disk until you match the GUID’s. It will look like this:

C:\Users\taylorb>diskpart.exe
Microsoft DiskPart version 6.1.7601
Copyright (C) 1999-2008 Microsoft Corporation.
On computer: 37-4611K2713G

DISKPART> select disk 1
Disk 1 is now the selected disk.

DISKPART> uniqueid disk
Disk ID: {F1B5319E-FF92-40BB-9BC9-D5FFAD0AD66B}

DISKPART> select disk 2
Disk 2 is now the selected disk.

DISKPART> uniqueid disk
Disk ID: {32443078-9AFC-4C0A-B142-466F582A4051}


Step 7: Once you find the disk you want you can use the detail disk command to get more information.  It will look like this:

DISKPART> detail disk

IBM 2810XIV  Multi-Path Disk Device
Disk ID: {32443078-9AFC-4C0A-B142-466F582A4051}
Type   : FIBRE
Status : Reserved
Path   : 0
Target : 1
LUN ID : 2
Location Path : UNAVAILABLE
Current Read-only State : No
Read-only  : No
Boot Disk  : No
Pagefile Disk  : No
Hibernation File Disk  : No
Crashdump Disk  : No
Clustered Disk  : Yes

There are no volumes.

Method 2

This method utilizes an undocumented and unsupported class I first posted about previously in Using The Virtual Disk Service (VDS) From Powershell to Mount and Use VHD's as well as in Virtual Disk Service (VDS) Powershell Script Version 2 - Previously Created Volume Support + Mount Points + Bug Fixes.  Again I must reiterate this is not an officially supported API it has no warrantee – it may break at any time and Microsoft Support can not and will not help you with it.  Now that the disclaimer is over – in this example I am using the VDS api’s to do the mapping for me.

Script #Load the Microsoft Storage VDS Library
#This is an undocumented, unsupported library, there is no warrantee nor gaurantees.
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Storage.Vds") | Out-Null
$VdsServiceLoader = New-Object Microsoft.Storage.Vds.ServiceLoader
$VdsService = $VdsServiceLoader.LoadService($null)
$VdsService.WaitForServiceReady()
$VdsService.Reenumerate()

#Build up a collection of all disks presented to the os
$Disks = ($VdsService.Providers |% {$_.Packs}) |% {$_.Disks}

#Import the FailoverClusters module
Import-Module FailoverClusters

#Retreve all of the CSV Lun's
$AllCSVs = Get-ClusterSharedVolume
foreach ($Csv in $AllCSVs)
{
    $CSVParams = Get-ClusterParameter -InputObject $Csv
    
    #Retreve the DiskIDGuid Object from the Cluster Parameters
$DiskGUIDString = ($CSVParams | Where-object -FilterScript {$_.Name -eq "DiskIdGuid"}).Value
    
    #Match up the DiskID's
$Disk = ($Disks | Where-Object -FilterScript {$_.DiskGuid -eq $DiskGUIDString})
        Write-Host "CSV ClusterResourceName: " $Csv.Name
        Write-Host "DiskID: " $DiskGUIDString
        Write-Host "DiskFriendlyName: " $Disk.FriendlyName
        Write-Host "DiskName: " $Disk.Name
        Write-Host "DiskAddress: " $Disk.DiskAddress
        Write-Host
}
Sample Output Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.

PS C:\Users\taylorb>.\GetCSVDevInfo1.ps1

CSV ClusterResourceName:  Cluster_CSV1_IBMXIV
DiskID:  {32443078-9afc-4c0a-b142-466f582a4051}
DiskFriendlyName:  IBM 2810XIV  Multi-Path Disk Device
DiskName:  \\?\PhysicalDrive2
DiskAddress:  Port1Path0Target1Lun2

CSV ClusterResourceName:  Cluster_CSV2_IBMXIV
DiskID:  {ee36e403-75cb-4e23-87b4-e82af7949f4e}
DiskFriendlyName:  IBM 2810XIV  Multi-Path Disk Device
DiskName:  \\?\PhysicalDrive3
DiskAddress:  Port1Path0Target1Lun3

CSV ClusterResourceName:  Cluster_CSV3_IBMXIV
DiskID:  {5db28bcb-6ed3-4b80-b363-861a25cc10e4}
DiskFriendlyName:  IBM 2810XIV  Multi-Path Disk Device
DiskName:  \\?\PhysicalDrive4
DiskAddress:  Port1Path0Target1Lun4

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

Categorías: Virtualización

Getting More Information About You Cluster LUN’s (Part 2 of 3)

Mié, 30/06/2010 - 18:08
So here’s the scenario you need or want to figure out which LUN is which on your cluster…

Yesterday I posted a script which used Get-ClusterParameter and the Physical Disk Private Properties to gather information on the storage being used by the cluster – as promised here’s a less verbose version of that script…

Script Import-Module FailoverClusters
$csv1 = Get-ClusterSharedVolume Cluster_CSV1_IBMXIV
$csvParams = Get-ClusterParameter -InputObject $csv1
$DiskUniqueIds = ($csvParams | Where-object -FilterScript {$_.Name -eq "DiskUniqueIds"}).Value

$CountOfIdentifiers = $DiskUniqueIds[8]

$currentArrayIndex = 12
for($a = 0; $a -lt $CountOfIdentifiers; $a++)
{
    $CodeSet = $DiskUniqueIds[$currentArrayIndex]
    $Length = $DiskUniqueIds[$currentArrayIndex+8]
    $NextOffset = $DiskUniqueIds[$currentArrayIndex+10]
    
    switch ($DiskUniqueIds[$currentArrayIndex+4])
    {
    0 {Write-Host "StorageIdType: VendorSpecific";break}
    1 {Write-Host "StorageIdType: VendorId";break}
    2 {Write-Host "StorageIdType: EUI64";break}
    3 {Write-Host "StorageIdType: FCPHName";break}
    4 {Write-Host "StorageIdType: PortRelative";break}
    5 {Write-Host "StorageIdType: TargetPortGroup";break}
    6 {Write-Host "StorageIdType: LogicalUnitGroup";break}
    7 {Write-Host "StorageIdType: MD5LogicalUnitIdentifier";break}
    8 {Write-Host "StorageIdType: ScsiNameString";break}
    }
    
    switch ($DiskUniqueIds[$currentArrayIndex+12])
    {
    0 {Write-Host "StorageIdAssoc: Device";break}
    1 {Write-Host "StorageIdAssoc: Port";break}
    2 {Write-Host "StorageIdAssoc: Target";break}
    }
    
    $Data = $null
    switch($CodeSet)
    {
    2 { #StorageIdCodeSetAscii
$DiskUniqueIds_ptr = [System.Runtime.InteropServices.Marshal]::UnsafeAddrOfPinnedArrayElement($DiskUniqueIds, $currentArrayIndex+16)
        $Data = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($DiskUniqueIds_ptr, $Length)
        break
        }
    
    3 { #StorageIdCodeSetUtf8
$DiskUniqueIds_ptr = [System.Runtime.InteropServices.Marshal]::UnsafeAddrOfPinnedArrayElement($DiskUniqueIds, $currentArrayIndex+16)
        $Data = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($DiskUniqueIds_ptr, $Length)
        break
        }
    
    default { #0=StorageIdCodeSetReserved, 1=StorageIdCodeSetBinary
for($x = ($currentArrayIndex+16); $x -lt ($currentArrayIndex + 16 + $Length); $x++)
        {
            $Data += , $DiskUniqueIds[$x]
        }
        break
        }
    }
    Write-Host "Data: " $Data
    $currentArrayIndex+=$NextOffset

    Write-Host
}
Sample Output

Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.

PS C:\Users\taylorb>.\GetCSVDevInfo1.ps1

StorageIdType:  EUI64
StorageIdAssoc:  Device
Data:  0 23 56 0 1 19 0 28

StorageIdType:  VendorId
StorageIdAssoc:  Device
Data:  IBM     2810XIV          1300113001C

StorageIdType:  VendorSpecific
StorageIdAssoc:  Device
Data:  vol=CSV_1

StorageIdType:  VendorSpecific
StorageIdAssoc:  Device
Data:  host=37-4611K2713K

StorageIdType:  TargetPortGroup
StorageIdAssoc:  Port
Data:  0 0 0 0

StorageIdType:  PortRelative
StorageIdAssoc:  Port
Data:  0 0 7 1

 

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

Categorías: Virtualización

Getting More Information About You Cluster LUN’s (Part 1 of 3)

Mar, 29/06/2010 - 23:00
So here’s the scenario you need or want to figure out which LUN is which on your cluster… 

Well if you just use the Get-ClusterSharedVolume cmdlet it won’t get you very far…  However there’s another cmdlet Get-ClusterParameter that will give you enough data that when combined with some other PowerShell/.Net magic will.  This function will return the Cluster Object Private Properties for a given object you can look on MSDN to see all of them – in this case we are interested specifically in the Physical Disk Private Properties.

For this first example I am going to utilize the DiskUniqueIds property to extract information about the specific LUN.  Looking at the documentation for this property it returns a STORAGE_DEVICE_ID_DESCRIPTOR structure which has a set of identifiers – after some more digging around it turns out these identifiers are actually STORAGE_IDENTIFIER structures which have some interesting values.  For most of the storage I have in the lab at the very least the vendor ID (StorageIdTypeEUI64) which is actually a bit mask of the IEEE vendor ID along with some vendor specific data (the bit map is documented here and you can search for vendor ID’s here) as well as a VendorID string and some LUN information although some will tell you what port is being used etc…

In order to format all of this data I’m using some inline C# to define a class with the reprehensive structures and enumerations – just copied from MSDN and made pretty for .Net interop.  I also wrote a function in the C# class named DiskUniqueIdstoStorageId, this function takes the byte array returned from calling the Get-ClusterParameter cmdlet and marshel’s it or formats it into the C# classes thus allowing me to consume the now managed object’s in C#.  All in all it might be overkill so look for a shorter version coming soon.

Script $StorageDevice= @"
using System;
using System.Runtime.InteropServices;

public static class StorageDevice
{
    public enum StorageIdCodeSet
    {
        Reserved = 0,
        Binary = 1,
        Ascii = 2,
        Utf8 = 3
    }

    public enum StorageIdType
    {
        VendorSpecific = 0,
        VendorId = 1,
        EUI64 = 2,
        FCPHName = 3,
        PortRelative = 4,
        TargetPortGroup = 5,
        LogicalUnitGroup = 6,
        MD5LogicalUnitIdentifier = 7,
        ScsiNameString = 8
    }

    public enum StorageIdAssoc
    {
        Device = 0,
        Port = 1,
        Target = 2
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct STORAGE_IDENTIFIER
    {
        public StorageDevice.StorageIdCodeSet CodeSet;
        public StorageDevice.StorageIdType Type;
        public UInt16 IdentifierSize;
        public UInt16 NextOffset;
        public StorageDevice.StorageIdAssoc Association;
        
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1)]
        public string Identifiers;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct STORAGE_DEVICE_ID_DESCRIPTOR
    {
        public UInt32 Version;
        public UInt32 Size;
        public UInt32 NumberOfIdentifiers;
        
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1)]
        public string Identifiers;
    }


    public static STORAGE_IDENTIFIER[] DiskUniqueIdstoStorageId(byte[] DiskUniqueIds)
    {
        IntPtr ArrayAddress = Marshal.UnsafeAddrOfPinnedArrayElement(DiskUniqueIds, 0);

        STORAGE_DEVICE_ID_DESCRIPTOR devId = 
            (STORAGE_DEVICE_ID_DESCRIPTOR)Marshal.PtrToStructure(
            ArrayAddress, typeof(STORAGE_DEVICE_ID_DESCRIPTOR));

        IntPtr AddressOfIdentifiers = (IntPtr)
            ((long)ArrayAddress + 
            (long)(Marshal.OffsetOf(
            typeof(STORAGE_DEVICE_ID_DESCRIPTOR), "Identifiers")));

        IntPtr OffsetOfIdentifiersStrings = Marshal.OffsetOf(
            typeof(STORAGE_IDENTIFIER), "Identifiers");
            
        STORAGE_IDENTIFIER[] ArrayofSTORAGE_IDENTIFIER = 
            new STORAGE_IDENTIFIER[devId.NumberOfIdentifiers];
            
        IntPtr CurrentAddressOfIdentifiers=AddressOfIdentifiers;
        
        for (int i = 0; i < devId.NumberOfIdentifiers; i++)
        {
            ArrayofSTORAGE_IDENTIFIER[i] = 
                (STORAGE_IDENTIFIER)Marshal.PtrToStructure(
                CurrentAddressOfIdentifiers, typeof(STORAGE_IDENTIFIER));

            IntPtr AddressOfIdentifiersString = 
                (IntPtr)((long)CurrentAddressOfIdentifiers + 
                (long)OffsetOfIdentifiersStrings);
                
            switch (ArrayofSTORAGE_IDENTIFIER[i].CodeSet)
            {
                case StorageIdCodeSet.Ascii:
                    ArrayofSTORAGE_IDENTIFIER[i].Identifiers = 
                        Marshal.PtrToStringAnsi(AddressOfIdentifiersString,
                        (Int32)ArrayofSTORAGE_IDENTIFIER[i].IdentifierSize);
                        
                    break;
                    
                case StorageIdCodeSet.Utf8:
                    ArrayofSTORAGE_IDENTIFIER[i].Identifiers = 
                        Marshal.PtrToStringUni(AddressOfIdentifiersString,
                        (Int32)ArrayofSTORAGE_IDENTIFIER[i].IdentifierSize);
                        
                    break;
                    
                default:
                    for (int x=0; x < ArrayofSTORAGE_IDENTIFIER[i].IdentifierSize; x++)
                    {
                        ArrayofSTORAGE_IDENTIFIER[i].Identifiers = 
                            String.Format("{0} {1:X}", 
                            ArrayofSTORAGE_IDENTIFIER[i].Identifiers,
                            Marshal.ReadByte(AddressOfIdentifiersString, x));
                    }
                    break;
            }
            CurrentAddressOfIdentifiers = (IntPtr)
                ((long)CurrentAddressOfIdentifiers + 
                (long)ArrayofSTORAGE_IDENTIFIER[i].NextOffset);
        }
        return ArrayofSTORAGE_IDENTIFIER;
    }
}
"@
add-type -TypeDefinition $StorageDevice

Import-Module FailoverClusters
$AllCSVLuns = Get-ClusterSharedVolume
foreach ($CSV in $AllCSVLuns)
{
    $CSVParams = Get-ClusterParameter -InputObject $CSV
    $DiskUniqueId = ($CSVParams | Where-object -FilterScript {$_.Name -eq "DiskUniqueIds"}).Value
    $StorageId = [StorageDevice]::DiskUniqueIdstoStorageId($DiskUniqueId)
    Write-Host "CSV ClusterResourceName: " $CSV.Name
    Write-Host "Identifiers: "
    $StorageId
    Write-Host
    Write-Host
}
  Sample Output

Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.

PS C:\Users\taylorb>.\GetCSVDevInfo1.ps1

CSV ClusterResourceName:  Cluster_CSV1_IBMXIV
Identifiers:
CodeSet        : Binary
Type           : EUI64
IdentifierSize : 8
NextOffset     : 28
Association    : Device
Identifiers    :  0 17 38 0 1 13 0 1C

CodeSet        : Ascii
Type           : VendorId
IdentifierSize : 36
NextOffset     : 56
Association    : Device
Identifiers    : IBM     2810XIV          1300113001C

CodeSet        : Ascii
Type           : VendorSpecific
IdentifierSize : 13
NextOffset     : 32
Association    : Device
Identifiers    : vol=CSV_1

CodeSet        : Ascii
Type           : VendorSpecific
IdentifierSize : 22
NextOffset     : 40
Association    : Device
Identifiers    : host=37-4611K2713K

CodeSet        : Binary
Type           : TargetPortGroup
IdentifierSize : 4
NextOffset     : 24
Association    : Port
Identifiers    :  0 0 0 0

CodeSet        : Binary
Type           : PortRelative
IdentifierSize : 4
NextOffset     : 24
Association    : Port
Identifiers    :  0 0 7 1

CSV ClusterResourceName:  Cluster_CSV2_IBMXIV
Identifiers:
CodeSet        : Binary
Type           : EUI64
IdentifierSize : 8
NextOffset     : 28
Association    : Device
Identifiers    :  0 17 38 0 1 13 0 1D

CodeSet        : Ascii
Type           : VendorId
IdentifierSize : 36
NextOffset     : 56
Association    : Device
Identifiers    : IBM     2810XIV          1300113001D

CodeSet        : Ascii
Type           : VendorSpecific
IdentifierSize : 13
NextOffset     : 32
Association    : Device
Identifiers    : vol=CSV_2

CodeSet        : Ascii
Type           : VendorSpecific
IdentifierSize : 22
NextOffset     : 40
Association    : Device
Identifiers    : host=37-4611K2713F

CodeSet        : Binary
Type           : TargetPortGroup
IdentifierSize : 4
NextOffset     : 24
Association    : Port
Identifiers    :  0 0 0 0

CodeSet        : Binary
Type           : PortRelative
IdentifierSize : 4
NextOffset     : 24
Association    : Port
Identifiers    :  0 0 7 3

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

Categorías: Virtualización

TechEd 2010

Lun, 14/06/2010 - 17:49

Last week was TechEd 2010 held in New Orleans, it was a great conference with over 10,000 attendees (speakers, exhibitors, attendees combined).  It was also a very very busy week – between working at our Microsoft Virtualization booth, presenting and attending dinner’s/parties the days where long.  This year all of the sessions from TechEd where recorded and are available for free to anyone.  Below is the session that I presented with Vijay Tewari.  Additionally all of the virtualization sessions can be found at http://www.msteched.com/Tracks/Virtualization, there are a few that are missing currently however expect those to be uploaded over the next few days.

Networking and Windows Server 2008 R2 Hyper-V: Deployment Considerations

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

Categorías: Virtualización

Writing Your Own VMConnect App/Web Interface For VM Console Access To Hyper-V VM’s

Mié, 02/06/2010 - 02:02

 

Ever since Hyper-V’s first beta I’ve had people ask about the ability to write there own custom interface to replace VMConnect.  Some wanted a windows application other’s wanted to write a web application.  The goal’s varied from wanting to just show the console session for monitoring to integrating it VM’s into existing physical machine applications to wanting to develop custom hosting applications allowing users to do some things like start/stop and interact but nothing more.  When we started developing Hyper-V we decided that instead of writing our own transport for sending over screen images, key strokes, mouse etc… that we would instead leverage the existing remote desktop protocol (RDP, Terminal Services, TS, what ever you want to call it).

That means that accomplishing developing such a applications is actually pretty straight forward if you know the magic incantation.  The good news is that the Dynamic Datacenter Tool Kit team has posted a full C# sample for just this.  If you combine this code with some of the other code posted either here on my blog or on MSDN you can pretty easily write your very own Hyper-V UI.

The Dynamic Data Center Toolkit for Hosters is located at http://code.msdn.microsoft.com/ddc and the Hyper-V RDP Active X control sample is a sub project off of that page.

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

Categorías: Virtualización

Writing Your Own VMConnect App/Web Interface For VM Console Access To Hyper-V VM’s

Mar, 18/05/2010 - 18:23
 

Ever since Hyper-V’s first beta I’ve had people ask about the ability to write there own custom interface to replace VMConnect.  Some wanted a windows application other’s wanted to write a web application.  The goal’s varied from wanting to just show the console session for monitoring to integrating it VM’s into existing physical machine applications to wanting to develop custom hosting applications allowing users to do some things like start/stop and interact but nothing more.  When we started developing Hyper-V we decided that instead of writing our own transport for sending over screen images, key strokes, mouse etc… that we would instead leverage the existing remote desktop protocol (RDP, Terminal Services, TS, what ever you want to call it).

That means that accomplishing developing such a applications is actually pretty straight forward if you know the magic incantation.  The good news is that the Dynamic Datacenter Tool Kit team has posted a full C# sample for just this.  If you combine this code with some of the other code posted either here on my blog or on MSDN you can pretty easily write your very own Hyper-V UI.

 

The Dynamic Data Center Toolkit for Hosters is located at http://code.msdn.microsoft.com/ddc and the Hyper-V RDP Active X control sample is a sub project off of that page.

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

Categorías: Virtualización