2016-04-14 7 views
0

irgendwelche vmware Powershell Leute da draußen? Ich hoffe, dass mir jemand helfen kann. Gibt es eine einfache Möglichkeit, mir die Laufwerksbeschriftungen der angehängten Festplatte auf einem Server zu zeigen, und welchen Datenspeicher diese Festplatte hat? Zum Beispiel haben wir einen SQL Server mit dem Mount-Punkt 'SQL01 \ Tlog'. Wie kann ich den Datenspeicher finden, auf dem sich der Datenträger befindet? Dieser Befehl zeigt mir den Pfad jeder Festplatte: (get-vm Computername) .Guest.Disks Dieser Befehl zeigt mir die Datenspeicher auf dem Server: Get-VM Computername | Get-Datastore Wie kann ich das tun, damit ich den Pfad zusammen mit dem Datenspeicher sehen kann?Wie wird der Datenspeicher basierend auf dem Festplattenpfad bestimmt?

Antwort

0

In der Vergangenheit musste ich die virtuellen Festplatten einer VM zuverlässig mit den Festplatten des Betriebssystems abgleichen. Es ist nicht sicher anzunehmen, dass die erste Festplatte in der Konfiguration einer VM die erste Festplatte im Betriebssystem ist. Bei der folgenden Methode wird zuerst versucht, die Festplatten anhand der Seriennummer abzugleichen. Wenn dies fehlschlägt, versucht es auch, auf der SCSI-Ziel-ID übereinzustimmen. ein Computer, dessen Hostnamen und VM-Name ist $ 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 
    } 
    } 
} 

der Grund, warum ich nur versuchen, SCSI-Ziel-ID-Abgleich

gegeben, wenn es einen einzigen SCSI-Controller ist i nicht eine zuverlässige Art und Weise finden könnte einen SCSI übereinstimmen Controller im Betriebssystem mit dem SCSI-Controller einer VM. Es sollte ein sehr kleiner Nachteil sein, da die meisten Festplatten auf der Seriennummer übereinstimmen und die meisten VMs nicht mehrere SCSI-Controller haben.


bearbeiten 1

unten sind 2-Funktionen "Gruppe-volumedisk" und "Gruppe-VMOSdisk". Ich habe sie nicht vollständig kommentiert, aber sie haben einige Kommentare, und sie sind ziemlich einfach.

Gruppe-VMOSdisk verwendet group-volumedisk, um eine Zuordnung der win32_volume-Instanzen eines Computers zu den win32_diskdrive-Instanzen zu erhalten. group-VMOSdisk macht hauptsächlich das, was im ersten Abschnitt dieses Posts war.

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 
      } 
     } 
     } 
    } 
    } 
} 

Verbinden Sie sich mit Ihrem vSphere-Server und pipen Sie dann $ CN an die Gruppe-VMOSdisk.

Gruppe-volumedisk wurde aus angepasst: http://www.powershelladmin.com/wiki/PowerShell_Get-MountPointData_Cmdlet

+0

cwr Danke für die Hilfe. Ich habe Ihr Skript gegen einen SQL-Server ausgeführt, den ich habe, beide Laufwerkbuchstaben, C und E. Allerdings haben wir mehrere Mount-Punkte unter E, die sich auf einer eigenen Festplatte befinden. Wie kann ich dieses Skript modifizieren, um Mount-Punkte zu berücksichtigen? Danke im Voraus. – Bill

+0

bearbeitet ursprünglichen Beitrag mit Funktionen zur Unterstützung von Festplatten in Ordnern montiert – cwr

Verwandte Themen