iSCSI, iscsicli, and WMI, Oh My!

I have been doing a lot of work with clustering Hyper-V lately and our storage is all iSCSI. Without going into all the gory details, iSCSI supports multipathing. My iSCSI SAN has two heads, each head has 3 NIC’s. On my Hyper-V hosts, we have two NIC’s that are used for iSCSI. Each NIC has a “target” for each IP on each head. Some quick math and you realize that’s a lot of connections, and a pain the butt to configure when you have a ton of nodes using this configuration. So naturally I started looking at scripting and didn’t find any cmdlets to work with iSCSI. However, there is a tool called ISCSICLI.

To add a an iSCSI target you can use the QAddTargetPortal command. Assuming your SAN’s iSCSI IP address is 192.168.168.10 you would use this command

iscsicli QAddTargetPortal 192.168.168.10

That’s fine, but what if you want to specify a source IP Address. This is pretty straight forward using the iSCSI Control Panel. In advanced settings you can choose both the “Microsoft iSCSI initiator” and the Initiator IP.

image

It turns out QAddTarget is “Quick Add Target” which gives you very few options. You can also use AddTargetPortal.

image

So there are a few things you should know. TargetPortalAddress is the IP address of the SAN you are connecting to. TargetPortalSocket is not really the socket, but just the port number, which is typically 3260. Normally a socket consists of an IP Address and a port number. The HBA name actually refers to Initiator Adapter. In this case it would be “Microsoft iSCSI Initiator.” Finally we get to the Port Number. It turns out that this port number is what is mapped to a source IP Address. The problem was that I could not find any documentation telling me how this port number was associated with an IP address on the server. At first I thought it might be the index of an interface, but quickly learned that was not the case, as you could have multiple IP’s on one interface anyway.

When something doesn’t show up in the GUI, I go exploring with WMI and PowerShell. It turns out there is a ton of iSCSI info buried in the root\wmi namespace

image

Looking around I found a msIScsi_portalinfoclass.

image

The PortalInformation property looked like it had some good info in it as well so I went digging into that.

image

Sweet! I see IPAddr and a port number. This looks promising. But when I crack open IPAddr I don’t see what I was expecting to see

image

Seriously.. since when is 1865687562 an IP V4 address? I was so close and then remembered that there is an IPAddress type in System.Net. Let’s just test something out here.

image

Woo Hoo! Given this I can now write my Get-IscsiPortNumber function in PowerShell.

001
002
003
004
005
006
007
Function Get-IscsiPortNumber {
$query = "select portalinformation from MSiSCSI_PortalInfoClass" 
$portalInfo = get-wmiobject -namespace root\wmi -query $query
$eScriptBlock ={([Net.IPAddress]$_.ipaddr.IPV4Address).IPAddressToString}
$customLabel = @{Label="IpAddress"; expression = $eScriptBlock}
$portalInfo.portalInformation | select port,$customlabel
}

Now that we have that info, we can use it in our iscsicli command

iscsicli addtargetportal 192.168.168.10 3260 ROOT\ISCSIPRT\0000_0 2 * * * * * * * * * *

Oh yeah, the ROOT\ISCSIPRT\0000_0 means MS Iscsi Initiator. There are some login flags as well that you would probably want to set for multipath as well.

image

So if your port number is 2 the final command would be

iscsicli addtargetportal 192.168.168.10 3260 ROOT\ISCSIPRT\0000_0 2 * 0x2 * * * * * * * *

Comments (3) -

Jason Ochoa 9/24/2009 3:09:07 PM

Very nice post!
At my organization we have a very similar configuration.  I like the [Net.IPAddress] type.  In my scrip I was converting the value to an IP manually. The script I use gets passed a couple of IPs and returns the iSCSICLI commands to establish the persistent bindings for the MPIO session mesh.
This all works well and good until I add/remove/change an IP or network setting.  Even if the IPs used in the iSCSI binding remain unmodified, often the ‘port number’ value changes.  This causes problems for us because iSCSI traffic will then be routed out the wrong interface on the server, or the session will fail to establish at all.  IPv6 changes also cause index changes as well as all IPs on a system are given a ‘port number’.
Sometimes it’s as simple as a drive update that causes the issue.  This is an ugly sort of problem because iSCSI traffic still tends to work, it is just routing improperly or not using all the paths it should.
How are you addressing this issue in your environment?

Jason

Gregory Strike 1/22/2010 7:01:29 PM

The line above should read: "Take each byte now and convert them back into decimal…"

Always, a typo...  Always.

Gregory Strike 1/22/2010 7:01:51 PM

Great post.  Thank you!

You may already know this but for those readers that may not the reason the IPv4 address showed up as 1865687562 is because that's a Decimal representation of the IPv4 address which is store in binary:

1,865,687,562 to Binary is 01101111 00110100 00100010 00001010, each eight bits is a byte.  Each byte represents a different octet in the IP address.
Take each byte now and convert them back into binary...

01101111 = 111
00110100 = 52
00100010 = 34
00001010 = 10

10.34.52.111  Outstanding!

P.S. I enjoy converting numbers between different bases. Can you tell?  Smile

Pingbacks and trackbacks (1)+

Comments are closed