Get iscsi mapped drive letter from iscsi initiator name - powershell

In PowerShell I'm trying to get the drive letter that an ISCSI target is mapped to. I'm using the following to get the ISCSI initiator name.
Get-IscsiTarget | ? {$_.IsConnected -eq $True} | Select -ExpandProperty NodeAddress
I have tried using Get-Disk | Select * and Get-PSDrive | Select * but these cmdlets do not seem to have any fields that I can link a target to, to obtain its drive letter.

As long as you have one active partition (not including reserved) per ISCSI target, you can use the following to match an ISCSI address to its corresponding drive letter.
foreach ($disk in (Get-Disk | ?{$_.BusType -Eq "iSCSI"})){
$DriveLetter = ($disk | Get-Partition | ?{$_.Type -eq "Basic"}).DriveLetter
$ISCSI = $disk | Get-IscsiSession
[pscustomobject]#{
DiskNumber=$disk.Number;
DriveLetter=$DriveLetter;
InitiatorNodeAddress=$ISCSI.InitiatorNodeAddress;
InitiatorIP=$ISCSI.InitiatorPortalAddress;
Size=$disk.Size;
}
}
This will check all connected ISCSI disks and get their corresponding drive letter, then it will put all the information into a customer PowerShell object and return it.

Related

Mapping Disks to Initiators using Powershell

I am using Windows Server 2016 with Powershell 7.0.2. I want to get the target IDs (WWNs or iSCSI Addresses) for my connected storages shown as disks. I get the disks on my Windows Server using get-disk
$Disks=get-disk
I can get if these are attached through iscsi or FC from BusType attribute. Then I can get the local port info
$Ports=Get-initiatorPort
I can get the Address (FC or ISCSI) from NodeAddress. At this point I am stuck.
How do I map which disk is using which NodeAddress on initiator
How do I get the target system ID (icsci iqn or FC WWN)
You can pass your disk object right to Get-IscsiSession which can give you some of the details you're looking for.
An example:
$DiskList = Get-Disk | Where-Object { $_.BusType -eq 'iSCSI' ]
foreach ($Disk in $DiskList) {
$SessionList = $Disk | Get-IscsiSession
foreach ($Session in $SessionList) {
[PSCustomObject]#{
Name = $Disk.FriendlyName
InitiatorNode = $Session.InitiatorNodeAddress
TargetNode = $Session.TargetNodeAddress
}
}
}
The only server I have to test on has PowerShell 4 with iSCSI multipath connections. You may not need the SessionList loop if you don't use MPIO.

How to get list of drive letters in Powershell 2.0

I'm trying to get a list of drive letters in a drop-down menu. I'm currently using the code below and it works just fine in Windows 10, but doesn't work at all in Windows 7.
$Drive_Letters = Get-WmiObject Win32_LogicalDisk
ForEach ($Drives in $Drive_Letters.DeviceID) { $Dest_Drive_Box.Items.Add($Drives) }
In Win 7 I tried adjusting the code to this...
$Drive_Letters = Get-WmiObject Win32_LogicalDisk | Select-Object DeviceID
ForEach ($Drives in $Drive_Letters) { $Dest_Drive_Box.Items.Add($Drives) }
But now it shows "#DeviceID=C:}", "#DeviceID=D:}", etc. in Win 7 and 10 for each drive letter. I need to just show "C:", "D:", etc.
Thanks!
Get-PSDrive
This will return all drives mapped in the current session. The Name property contains the drive letter.
To capture just drive letters:
(Get-PSDrive).Name -match '^[a-z]$'
Tested working in PSv2:
Get-PSDrive | Select-Object -ExpandProperty 'Name' | Select-String -Pattern '^[a-z]$'
$drives = (Get-PSDrive -PSProvider FileSystem).Root
returns an array for drives with the root path:
C:\
D:\
E:\
You can easily trim the ending if you don't want it.
$Drives = Get-WmiObject Win32_Logicaldisk | % {$_.DeviceId}
$Drives | % {$Dest_Drive_Box.Items.Add($_)}
It would appear that each item $drives is a HashTable with one Key-Value Pair DeviceID = driveletter a quick test shows that using $Drives.DeviceID returns just the value of the key-value pair.
ForEach ($Drives in $Drive_Letters) { $Dest_Drive_Box.Items.Add($Drives.DeviceID) }

Powershell Where-Object Match

I want to use the Where-Object to limit the Output of Get-PSDrive to only network shares.
Get-PSDrive shows me the following:
Name Used (GB) Free (GB) Provider Root CurrentLocation
---- --------- --------- -------- ---- ---------------
A FileSystem A:\
Alias Alias
C 16.19 43.47 FileSystem C:\ Users\HansB\Documents
Cert Certificate \
D FileSystem D:\
Env Environment
Function Function
HKCU Registry HKEY_CURRENT_USER
HKLM Registry HKEY_LOCAL_MACHINE
V 451.39 159.76 FileSystem \\192.168.71.31\fs_log_target
Variable Variable
W 197.72 FileSystem \\192.168.71.32\perf200
WSMan WSMan
X 197.72 FileSystem \\192.168.71.32\perf100
Y 271.52 34.33 FileSystem \\192.168.71.30\group200
Z 271.52 34.33 FileSystem \\192.168.71.30\group100
Then I want to get the \\192.168.71.30\group100 Network Share:
Get-PSDrive | Where-Object { $_.Root -match "\\\\192.168.71.30\\group100" }
But I get nothing, why does -match not work?
Use DisplayRoot instead of Root property
Get-PSDrive | Where-Object { $_.DisplayRoot -match "\\\\192.168.71.30\\group100" }
try to run
Get-PSDrive | Where-Object { $_.DisplayRoot -match "\\\\192.168.71.30\\group100" } | select *
Root will be your mapped drive letter, and DisplayRoot your UNC Path
EDIT: as a side note. For escaping regex use [regex]::Escape() method.
PS > [regex]::Escape("\\192.168.71.30\group100")
\\\\192\.168\.71\.30\\group100
Try using -eq instead:
Get-PSDrive | Where-Object {$_.Root -eq "\\192.168.71.30\group100"}
If yoy type Get-PSDrive | select root you will notice that for network drives it will print nothing. So there is something strange with network share roots.
Get-PSDrive | select root | %{write-host $_.Root.GetType()} will show that it's a system string, so not quite sure why it seems to be empty for network drives.

Powershell free disk space for drives without drive letter

I am working on a power shell script based on http://www.powershellneedfulthings.com/?p=36 to check the disk space for volumes that do not have a driver letter assigned.
The script works pretty well, but I'd like to filter that only drives are shown that have less than 10% free disk space. I'm running into troubles using the where-object filter with hash tables.
# calculations for displaying disk size information
$TotalGB = #{Name="Capacity(GB)";expression={[math]::round(($_.Capacity/ 1GB),2)}}
$FreeGB = #{Name="FreeSpace(GB)";expression={[math]::round(($_.FreeSpace / 1GB),2)}}
$FreePerc = #{Name="Free(%)";expression={[math]::round(((($_.FreeSpace / 1GB)/($_.Capacity / 1073741824)) * 100),0)}}
# array declarations
$volumes = #()
# import server names to check
$servers = (Get-Content .\servers.txt)
# check disk space for volumes without drive letter
foreach ($server in $servers){
$volumes += Get-WmiObject -computer $server win32_volume | Where-Object {$_.DriveLetter -eq $null -and $_.Label -ne "System Reserved"}
}
$volumes | Select SystemName, Label, $TotalGB, $FreeGB, $FreePerc | Format-Table -AutoSize
What I tried is:
Where-Object {$FreePerc -le 10}
The current output is:
SystemName Label Capacity(GB) FreeSpace(GB) Free(%)
---------- ----- ------------ ------------- ----
SERVER01 X:\data\ 9.97 0.89 9
SERVER01 X:\log\ 9.97 1.20 12
SERVER01 X:\info\ 9.97 3.49 35
I'd like to only show the volumes that have less than 10% free disk space. So in this case, only the first entry should be shown.
Thanks!
I think the where clause variable $FreePerc is the issue. Arco had the right idea.
$volumes | Select SystemName, Label, $TotalGB, $FreeGB, $FreePerc | Where-Object {$_.'Free(%)' -le 10} | Format-Table -AutoSize
I put the property in single quotes because i think PowerShell would try to evaluate (%) otherwise. Also to make Arco's solution work it might just be easier to call the Name propery of $FreePerc. That way you only have to update one location
$volumes | Select SystemName, Label, $TotalGB, $FreeGB, $FreePerc | Where-Object {$_.($FreePerc.Name) -le 10} | Format-Table -AutoSize

Get a partition name with PowerShell

I have a flash drive which I formatted so that the volume label on the drive is "PHILIP".
I am using Get-PSDrive H -PSProvider FileSystem to determine if the drive is plugged in, however I would really like to determine if the drive is plugged in by the volume label, i.e. Get-PSDrive -VolumeLabel PHILIP -PSProvider FileSystem. Of course the VolumeLabel parameter does not exist so this doesn't work.
Is there a way to list the drives in a computer by volume name?
You can use WMI, I guess:
Get-WMIObject Win32_Volume | ? { $_.Label -eq 'PHILIP' }
You can use the DriveInfo class from the .NET framework as well:
PS> [System.IO.DriveInfo]::GetDrives()
Name : C:\
DriveType : Fixed
DriveFormat : NTFS
IsReady : True
AvailableFreeSpace : 217269202944
TotalFreeSpace : 217269202944
TotalSize : 320070479872
RootDirectory : C:\
VolumeLabel : OS
You can then pipe that to the Where-Object cmdlet (both ? and Where are aliases) to filter that to just the volume you are looking for:
PS> [System.IO.DriveInfo]::GetDrives() | ? {$_.VolumeLabel -eq "PHILIP" }
I use Get-WMIObject like Joey proposes.
To link the wmi results to for example a get-partition i use the caption parameter.
In this example I set the partition letter of volume Philip to D
$datavolume=Get-WMIObject Win32_Volume | ? { $_.Label -eq 'PHILIP' }
$datavolume=$datavolume.Caption
get-partition -DiskNumber 0 | where {$_.accesspaths -like "$datavolume"} | Set-Partition -NewDriveLetter D