ekkis
2010-02-24 18:54:09 UTC
In my current organisation we make use of iSCSI storage, which is made
available to applications either via drives or mount points.
I have been able to map a SCSI target to a drive using WMI, but for
mount-points I seem unable to do it, though I know it's possible to do since
the GUI apps show that relationship.
At a high level, my understanding is that a mount-point is made upon a
volume; a volume consists of multiple logical disks, a logical disk maps to a
partitions on a physical disk, and physical disks are devices within a given
iSCSI initiator.
The code below expresses that relationship and works when the storage is
available via a drive, however, for mount points it fails on account of
Win32_LogicalDiskToPartition, which apparently does not represent all disks
that exist but only those that map to a drive letter (in the example below,
Disk 56 does not exist in the table).
interspersed in the code please see annotations of the values picked up
along the line. I've found an article (see link below) which seems to
suggest what I need is undoable via WMI and suggests direct interaction with
DeviceIOControl, which for Powershell (my language of choice in this
endeavour) seems available via a Powershell Community Extension.
http://blogs.msdn.com/adioltean/archive/2005/05/04/414806.aspx
if anyone out there has struggled with this, I'd love to know!
Function SCSITarget {
Param($ServerName, $MountPoint)
# V:\data_04
$MountPoint = $MountPoint -replace '\\', '\\'
$mp = WMI Win32_MountPoint |
?{ $_.Directory -eq 'Win32_Directory.Name="{0}"' -f $MountPoint }
$mp.Volume -match 'Volume{(.*)}' > $null
$vol = $matches[1]
# 2fefb657-f9c6-11dd-b503-001a4be95384
$v = WMI Win32_Volume |
?{ $_.DeviceId -eq "\\?\Volume{$vol}\" }
# ac12f521
$ld = WMI Win32_LogicalDisk |
?{ $_.VolumeSerialNumber -eq [convert]::ToString($v.SerialNumber, 16) }
# $ld.Name: X: ??? (ask Peter)
$ld2p = WMI Win32_LogicalDiskToPartition |
?{ $_.Dependent -match '"{0}"' -f $ld.Name }
# $ld2p.Antecedent: ="Disk #56, Partition #0"
# \\SQL-LA19P\root\cimv2:Win32_DiskPartition.DeviceID
$dp = WMI Win32_DiskPartition |
?{ $_.Path.Path -eq $ld2p.Antecedent }
# $dp.DiskIndex: 56
$d = WMI Win32_DiskDrive |
?{ $_.Index -eq $dp.DiskIndex }
# $d.DeviceId: \\.\PhysicalDrive56
if (WMI:List "root\wmi" | Select-String "MSiSCSI") {
$sc = wmi MSiSCSIInitiator_SessionClass "root\wmi"
$sc = $sc.Devices | ?{ $_.LegacyName -eq $d.DeviceId }
}
$sc.TargetName
}
available to applications either via drives or mount points.
I have been able to map a SCSI target to a drive using WMI, but for
mount-points I seem unable to do it, though I know it's possible to do since
the GUI apps show that relationship.
At a high level, my understanding is that a mount-point is made upon a
volume; a volume consists of multiple logical disks, a logical disk maps to a
partitions on a physical disk, and physical disks are devices within a given
iSCSI initiator.
The code below expresses that relationship and works when the storage is
available via a drive, however, for mount points it fails on account of
Win32_LogicalDiskToPartition, which apparently does not represent all disks
that exist but only those that map to a drive letter (in the example below,
Disk 56 does not exist in the table).
interspersed in the code please see annotations of the values picked up
along the line. I've found an article (see link below) which seems to
suggest what I need is undoable via WMI and suggests direct interaction with
DeviceIOControl, which for Powershell (my language of choice in this
endeavour) seems available via a Powershell Community Extension.
http://blogs.msdn.com/adioltean/archive/2005/05/04/414806.aspx
if anyone out there has struggled with this, I'd love to know!
Function SCSITarget {
Param($ServerName, $MountPoint)
# V:\data_04
$MountPoint = $MountPoint -replace '\\', '\\'
$mp = WMI Win32_MountPoint |
?{ $_.Directory -eq 'Win32_Directory.Name="{0}"' -f $MountPoint }
$mp.Volume -match 'Volume{(.*)}' > $null
$vol = $matches[1]
# 2fefb657-f9c6-11dd-b503-001a4be95384
$v = WMI Win32_Volume |
?{ $_.DeviceId -eq "\\?\Volume{$vol}\" }
# ac12f521
$ld = WMI Win32_LogicalDisk |
?{ $_.VolumeSerialNumber -eq [convert]::ToString($v.SerialNumber, 16) }
# $ld.Name: X: ??? (ask Peter)
$ld2p = WMI Win32_LogicalDiskToPartition |
?{ $_.Dependent -match '"{0}"' -f $ld.Name }
# $ld2p.Antecedent: ="Disk #56, Partition #0"
# \\SQL-LA19P\root\cimv2:Win32_DiskPartition.DeviceID
$dp = WMI Win32_DiskPartition |
?{ $_.Path.Path -eq $ld2p.Antecedent }
# $dp.DiskIndex: 56
$d = WMI Win32_DiskDrive |
?{ $_.Index -eq $dp.DiskIndex }
# $d.DeviceId: \\.\PhysicalDrive56
if (WMI:List "root\wmi" | Select-String "MSiSCSI") {
$sc = wmi MSiSCSIInitiator_SessionClass "root\wmi"
$sc = $sc.Devices | ?{ $_.LegacyName -eq $d.DeviceId }
}
$sc.TargetName
}