2016-04-14 95 views
0

任何vmware powershell人都在那裏?我希望有人能幫助我。有沒有簡單的方法向我展示服務器上連接磁盤的驅動器標籤以及該磁盤所在的數據存儲區?例如,我們現在有一個名爲'SQL01 \ Tlog'的安裝點的SQL Server,我現在該如何找到該磁盤所在的數據存儲? 此命令顯示每個磁盤的路徑: (get-vm Computername).Guest.Disks 此命令顯示服務器上的數據存儲: get-vm Computername | Get-Datastore 我該怎麼做才能看到數據存儲的路徑呢?如何根據磁盤路徑確定數據存儲?

回答

0

在過去,我不得不以可靠的方式將虛擬機的虛擬磁盤與操作系統的磁盤進行匹配。假設虛擬機配置中的第一個磁盤是操作系統中的第一個磁盤是不安全的。下面的方法首先嚐試匹配基於序列號的磁盤。如果失敗,它也會嘗試匹配SCSI目標ID。其給出的主機名和虛擬機的名稱爲$ CN計算機...

#define the computer & VM name 
$CN = 'mycomputer' 

#get OS disk information 
$GWOsplat = ` 
    @{computername = $CN 
    class = 'win32_diskdrive' 
    erroraction = [system.management.automation.actionpreference]::stop} 
$OSdisk = get-WMIobject @GWOsplat 

#get VM disk information 
$GVsplat = ` 
    @{viewtype = ([VMware.VIM.virtualmachine]) 
    filter = @{name="^$CN`$"} 
    property = @('name','config.hardware.device') 
    erroraction = [system.management.automation.actionpreference]::stop} 
$VM = get-view @GVsplat 
$VMdisk = $VM.config.hardware.device | where-object {$_.deviceinfo.label -like 'hard disk*'} 

#get the number of SCSI controllers 
$controllercount = ($VMdisk.controllerkey | group-object | measure-object).count 

#iterate through VM disks 
foreach($VMD in $VMdisk) 
{ 
    #get VM disk serial number and SCSI target ID 
    $VMDSN = $VMD.backing.UUID -replace '-','' 
    $VMDSID = $VMD.unitnumber 

    #iterate through operating system disks 
    foreach($OSD in $OSdisk) 
    { 
    #get OS disk serial number and SCSI target ID 
    $OSDSN = $OSD.serialnumber 
    $OSDSID = $OSD.SCSItargetID 
    if(($VMDSN -eq $OSDSN) -or (($controllercount -eq 1) -and ($VMDSID -eq $OSDSID))) 
    { 
     #matching OSdisk found 

     #get datastore 
     $DS = get-datastore -ID $VMD.backing.datastore 

     #get partitions within OSdisk 
     $GWOsplat = ` 
     @{computername = $CN 
     query = "associators of {win32_diskdrive.deviceID='$($OSD.deviceID)'} WHERE resultrole=dependent" 
     erroraction = [system.management.automation.actionpreference]::stop} 
     $partition = get-WMIobject @GWOsplat 

     #get logicaldisks within partitions 
     foreach($P in $partition) 
     { 
     $GWOsplat = ` 
      @{computername = $CN 
      query = "associators of {win32_diskpartition.deviceID='$($P.deviceID)'} WHERE resultrole=dependent" 
      erroraction = [system.management.automation.actionpreference]::stop} 
     $logicaldisk = get-WMIobject @GWOsplat 

     #output custom object mapping drive letter to datastore 
     foreach($LD in $logicaldisk) 
     { 
      [PScustomobject] ` 
      @{computername = $CN 
      datastore = $DS 
      drive = $LD.deviceID} 
     } 
     } 
     break 
    } 
    } 
} 

的原因,我只嘗試SCSI目標ID匹配,如果有一個SCSI控制器是我無法找到一個可靠的方式來匹配SCSI使用虛擬機的SCSI控制器在操作系統中控制器。它應該是一個非常小的缺點,因爲大多數磁盤將在序列號上匹配,並且大多數虛擬機沒有多個SCSI控制器。下面


編輯1

是2層的功能, 「基團的volumedisk」 和 「基團的VMOSdisk」。我沒有完全評論他們,但他們確實有一些評論,而且他們相當直接。

group-VMOSdisk使用group-volumedisk獲取計算機的win32_volume實例到它的win32_diskdrive實例的映射。 group-VMOSdisk主要是這篇文章第一部分的內容。

function group-volumedisk 
{ 
    [cmdletbinding()] 
    param 
    (
    [parameter(valuefrompipeline=$true,valuefrompipelinebypropertyname=$true)] 
    [alias('CN')] 
    [system.string[]]$computername 
) 
    begin 
    { 
    new-variable -option constant -name localhost -value ([system.environment]::machinename) 
    new-variable -option constant -name dbgpfx -value "$localhost`: $($myinvocation.mycommand):" 
    new-variable -option constant -name dispprop -value @('computername','volume','diskdrive') 
    new-variable -option constant -name SB -value ` 
    { 
     begin 
     { 
     add-type -typedefinition @" 
      namespace GDFVNS 
      { 
      using Microsoft.Win32.SafeHandles; 
      using System.Runtime.InteropServices; 

      [StructLayout(LayoutKind.Sequential)] 
      public struct DiskExtent 
      { 
       public int DiskNumber; 
       public System.Int64 StartingOffset; 
       public System.Int64 ExtentLength; 
      }; 

      [StructLayout(LayoutKind.Sequential)] 
      public struct DiskExtents 
      { 
       public int numberOfExtents; 
       public DiskExtent first; 
      }; 

      public class GDFVname 
      { 
       public const uint IoctlVolumeGetVolumeDiskExtents = 0x560000; 


       [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
       public static extern SafeFileHandle CreateFile(
       string lpFileName, 
       [MarshalAs(UnmanagedType.U4)] System.IO.FileAccess dwDesiredAccess, 
       [MarshalAs(UnmanagedType.U4)] System.IO.FileShare dwShareMode, 
       System.IntPtr lpSecurityAttributes, 
       [MarshalAs(UnmanagedType.U4)] System.IO.FileMode dwCreationDisposition, 
       [MarshalAs(UnmanagedType.U4)] System.IO.FileAttributes dwFlagsAndAttributes, 
       System.IntPtr hTemplateFile); 

       [DllImport("Kernel32.dll", SetLastError = false, CharSet = CharSet.Auto)] 
       public static extern bool DeviceIoControl(
       SafeFileHandle hDevice, 
       uint IoControlCode, 
       [MarshalAs(UnmanagedType.AsAny)] [In] object InBuffer, 
       uint nInBufferSize, 
       ref DiskExtents OutBuffer, 
       int nOutBufferSize, 
       ref uint pBytesReturned, 
       System.IntPtr Overlapped); 
      } 
      } 
"@ 
     } 
     end 
     { 
     $volume = get-WMIobject -class win32_volume -filter "drivetype = 3" 
     foreach($V in $volume) 
     { 
      # get the volume's path and format it properly 
      $path = $V.deviceID 
      $path = $path.trimstart('\?') 
      $path = $path.trimend('\') 
      if($path -notlike '\.\*') 
      { 
      $path = "\\.\$path" 
      } 
      "$dbgpfx path ($path)" | write-verbose 

      #get a handle to the volume 
      $handle = [GDFVNS.GDFVname]::createfile($path,[system.IO.fileaccess]::read,[system.IO.fileshare]::read -bor [system.IO.fileshare]::write,[system.intptr]::zero,[system.IO.filemode]::open,0,[system.intptr]::zero) 
      "handle ($($handle | out-string))" | write-verbose 
      if($handle.isinvalid) 
      { 
      $lastAPIerr = [system.runtime.interopservices.marshal]::getlastwin32error() 
      "createfile call failed ($lastAPIerr)" | write-error 
      continue 
      } 

      #get disk extents of the volume pointed to by $handle 
      $returnbytes = new-object -typename system.Uint32 
      $DE = new-object -typename GDFVNS.diskextents 
      $result = [GDFVNS.GDFVname]::DeviceIoControl($handle,[GDFVNS.GDFVname]::IoctlVolumeGetVolumeDiskExtents,[system.intptr]::zero,0,[ref]$DE,[system.runtime.interopservices.marshal]::sizeof($DE),[ref]$returnbytes,[system.intptr]::zero) 
      "result ($result)" | write-verbose 
      if($result -eq 0) 
      { 
      $lastAPIerr = [system.runtime.interopservices.marshal]::getlastwin32error() 
      "DeviceIoControl call failed ($lastAPIerr)" | write-error 
      continue 
      } 

      #parse the deviceID of the disk and get its win32_diskdrive 
      $deviceID = "\\.\PHYSICALDRIVE$($DE.first.DiskNumber)" -replace '\\','\\' 
      $diskdrive = get-WMIobject -class win32_diskdrive -filter "deviceID = '$deviceID'" 

      #output custom object mapping the win32_volume to its parent win32_diskdrive 
      new-object -typename system.management.automation.PSobject -property ` 
      @{computername = $V.PScomputername 
      volume = $V 
      diskdrive = $diskdrive} 
     } 
     } 
    } 
    } 
    process 
    { 
    foreach($CN in $computername) 
    { 
     $ICsplat = ` 
     @{computername = $CN 
     scriptblock = $SB 
     erroraction = [system.management.automation.actionpreference]::stop} 
     try 
     { 
     invoke-command @ICsplat | select-object -property $dispprop 
     } 
     catch 
     { 
     "invoke-command failed`n$_" | write-error 
     continue 
     } 
    } 
    } 
} 
function group-VMOSdisk 
{ 
    [cmdletbinding()] 
    param 
    (
    [parameter(valuefrompipeline=$true)] 
    [alias('CN')] 
    [system.string[]]$computername 
) 
    begin 
    { 
    new-variable -option constant -name localhost -value ([system.environment]::machinename) 
    new-variable -option constant -name dbgpfx -value "$localhost`: $($myinvocation.mycommand):" 
    } 
    process 
    { 
    foreach($CN in $computername) 
    { 
     #get OS disks 
     $GWOsplat = ` 
     @{computername = $CN 
     class = 'win32_diskdrive' 
     erroraction = [system.management.automation.actionpreference]::stop} 
     $OSdisk = get-WMIobject @GWOsplat 

     #get mapping of volumes to disks 
     $voldiskmap = $CN | group-volumedisk 

     #get VM disks 
     $GVsplat = ` 
     @{viewtype = ([VMware.VIM.virtualmachine]) 
     filter = @{name="^$CN$"} 
     erroraction = [system.management.automation.actionpreference]::stop} 
     $VM = get-view @GVsplat 
     $VMdisk = $VM.config.hardware.device | where-object {$_.deviceinfo.label -like 'hard disk*'} 

     #get SCSI controller count 
     $controllercount = ($VMdisk.controllerkey | group-object | measure-object).count 

     #iterate through VMdisks 
     foreach($VMD in $VMdisk) 
     { 
     #get the VMdisk serial number and SCSI target ID 
     $VMDSN = $VMD.backing.UUID -replace '-','' 
     $VMDSID = $VMD.unitnumber 
     foreach($OSD in $OSdisk) 
     { 
      #get the OSdisk serial number and SCSI target ID 
      $OSDSN = $OSD.serialnumber 
      $OSDSID = $OSD.SCSItargetID 
      if(($VMDSN -eq $OSDSN) -or (($controllercount -eq 1) -and ($VMDSID -eq $OSDSID))) 
      { 
      #matching OSdisk found 

      #get datastore 
      $DS = get-datastore -ID $VMD.backing.datastore 

      #get volumes within this OSdisk 
      $volume = ($voldiskmap | where-object {$_.diskdrive.deviceID -eq $OSD.deviceID}).volume 

      #output custom object mapping volume to datastore 
      foreach($V in $volume) 
      { 
       [PScustomobject] ` 
       @{computername = $CN 
       datastore = $DS 
       volume = $V.name} 
      } 
      break 
      } 
     } 
     } 
    } 
    } 
} 

連接到您的vSphere服務器,然後將$ CN連接到group-VMOSdisk。

group-volumedisk改編自:http://www.powershelladmin.com/wiki/PowerShell_Get-MountPointData_Cmdlet

+0

cwr感謝您的幫助。我將腳本運行在我有的SQL服務器上,它同時返回了驅動器號,C和E.但是我們在E下有多個Mount點,這些點位於它們自己的磁盤上,我如何修改這個腳本來考慮Mount點?提前致謝。 – Bill

+0

編輯原始帖子,具有支持安裝在文件夾中的磁盤的功能 – cwr