Map LUN NAA id to Virtual Machine (VM) using PowerCLI

Have you had a situation in which you wanted to detach a RDM LUN or LUN using NAA id, but could not because there were multiple LUNs with the same size. In such a situation you cannot distinguish which LUN NAA to pick? This post is your answer because what you need is to map the NAA id to a VM. LUNs already in use will show connected to a VM and the LUNs that are not in use should not be attached to any VM. It’s that simple.

Today I was looking to detach some LUNs and it worked fine for the most part until I came across one LUN which had a conflict with another.

Two LUNs had the same size and the same HLU. Moreover, they were also presented as RDM in the same cluster. So it made a bit confusing to find out which LUN I should remove since all I could was identify the LUN using naa id.

Looking around, I came across VMware KB – 2001823 that shows very clearly how to identify virtual machines with Raw Device Mappings (RDMs) attached to them.

The command is very simple and all you need to do is connect to vCenter and run the query –

connect-viserver -server EnterYourvCenterName

Get-VM | Get-HardDisk -DiskType “RawPhysical”,”RawVirtual” | Select Parent,Name,DiskType,ScsiCanonicalName,DeviceName | fl > output.txt

 

Note that I took the output to a file (KB uses a different syntax). When you work with a large number of LUNs it is great to have flexibility in searching through a file.

The output came across in the following format :

Parent : Virtual Machine Display Name
Name : Hard disk 4
DiskType : RawVirtual
ScsiCanonicalName : naa.600601602ec03800b92de53df9a6e411
DeviceName : vml.020000000060123456789abcdef0123456789abcde1234567890ab

 

When I ran the above command, I received a listing of all VMs with their RDM devices. All I had to do after the output was generated was to copy the LUN Identifier (NAA id) from vCenter – one naa id at a time, and search in this file.

If you find it then skip that NAA identifier and do not detach the LUN because that particular LUN is in use. If you search and cannot find the NAA identifier in this file – that would be the one to detach.

Now if anyone has the question – what if there are multiple LUN naa id’s and they cannot be found in this file, then my answer is – you can detach all of those LUNs since they are not being used. If you need to present any LUNs always try to use unique Host LUN Id’s and you would never have any confusion.

In my case, I was trying to remove something that was a legacy item and hence I had a situation with multiple LUNs having same Host LUN ID (HLU).

A couple of wordpress tips

The mighty Backslash

I encountered an issue recently with a technical post in which I had used ‘backslash – \’ and for some reason after I published the post (and I tried numerous times after changing it), WordPress would remove the backslash.

Confused, I searched online and I saw this to be a normal function and expected behaviour. But for a techie that’s unacceptable. So I posted on twitter and luckily got a reply from one WordPress user. I was told I had to switch to an html editor or disable the visual editor . Even when I tried to  switch to text editor it wouldn’t work. Finally, I downloaded a plugin called ‘Disable Visual Editor WYSIWYG’ and it allowed me the flexibility to pick and choose which posts I would disable the visual editor on.

Note that you still need to use “& # 092;” (without spaces – added a space to avoid getting the code converted to the icon) in the text editor as a replacement for backslash.

Because in normal scenarios the visual editor works great.  So I am sharing this information just in case it helps someone else.

 

WordPress Backup

I might be late to the party here so my apologies in advance. But wordpress users can stop doing the manual backup and choose a plugin like BackupWP Free, which allows you to backup the entire wordpress site with database to S3 and other cloud platforms. That is nice because I already have an S3 account and as long as you are reasonable with data volumes there is hardly anything to pay for. So I configured my backup.

Ran into one issue – the backup would keep failing. Problem was that I had enabled multi-part backup in the configuration. So disable that and things should work fine.

Besides that, happy blogging.

PowerCLI script to Detach LUNs from single or multiple ESXi hosts

During this past weekend I had to get a couple of scripts created using PowerCLI. Doing the activity manually would have taken me really long so PowerCLI came to my rescue.

My requirement was to detach LUN using naa id on one or multiple ESXi Hosts. I also had another situation in which I wanted to delete multiple LUNs using their naa id and do that on multiple ESXi hosts (each ESXi host would have multiple LUNs and there would be numerous such hosts). While looking online I came across some great scripts by @LucD22. By far Luc’s posts are on the dot when it comes to what we would need in the real world. His blog www.lucd.info has a ton of relevant information for you.

For the benefit of others I am creating one large blog post listing the scripts that I finally put together for an easy reference plus to have them in one place. I will keep adding more powercli scripts in future for the community’s benefit.

I started off with creating a LUN report so that I can identify and note the LUN’s that I needed to detach. This script will also help you in case you have any missing LUNs or a situation where some LUNs were detached but not all. Another scenario in which it will help you is in case LUNs were deleted from some hosts but not all hosts in a ESXi Cluster.

Note – I gave my scripts specific names – you can choose to give a different name. I also saved my scripts in c:\scripts folder on my laptop

Before you run the scripts you need to understand (especially for newbies) which naa id’s you need to work with. They can be copied from the vSphere web client but when we are working with multiple LUNs that becomes a hassle. So run this report that is sourced from LucD’s website here and can be run for each individual cluster.

To run the scripts download and install PowerCLI from VMware website. Then launch PowerCLI and if you aren’t connected to the vCenter let’s do that first. I prefer to connect to the vCenter since it is easy to manage stuff in large env.

To get going we need LUN information first. 

The LUN Report script is based on each VM Cluster (actually that is preferred for sake of control as well) – the only thing you need to change in script below is the first line and specify where you want to store the CSV file that gets generated. In my case I used c:\Scripts\Output

———

param($clusName,$csvName=("C:\Scripts\Output" + $clusName + "-LUN.csv"))
 
$rndNum = Get-Random -Maximum 99999
 
$LunInfoDef = @"
  public string ClusterName;
  public string CanonicalName;
  public string UsedBy;
  public string SizeMB;
"@
$LunInfoDef = "public struct LunInfo" + $rndNum + "{`n" + $LunInfoDef
 
$esxServers = Get-Cluster $clusName | Get-VMHost | Sort-Object -Property Name
$esxServers | %{
  $LunInfoDef += ("`n`tpublic string " + ($_.Name.Split(".")[0]) + ";")
}
$LunInfoDef += "`n}"
 
Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef
 
$scsiTab = @{}
$esxServers | %{
  $esxImpl = $_
 
# Get SCSI LUNs
  $esxImpl | Get-ScsiLun | where {$_.LunType -eq "Disk"} | %{
 
    $key = $esxImpl.Name.Split(".")[0] + "-" + $_.CanonicalName.Split(".")[1]
    if(!$scsiTab.ContainsKey($key)){
 
      $scsiTab[$key] = $_.CanonicalName,"",$_.CapacityMB
    }
  }
 
# Get the VMFS datastores
  $esxImpl | Get-Datastore | where {$_.Type -eq "VMFS"} | Get-View | %{
    $dsName = $_.Name
    $_.Info.Vmfs.Extent | %{
      $key = $esxImpl.Name.Split(".")[0] + "-" + $_.DiskName.Split(".")[1]
      $scsiTab[$key] = $scsiTab[$key][0], $dsName, $scsiTab[$key][2]
    }
  }
}
 
# Get the RDM disks
Get-Cluster $clusName | Get-VM | Get-View | %{
  $vm = $_
  $vm.Config.Hardware.Device | where {$_.gettype().Name -eq "VirtualDisk"} | %{
    if("physicalMode","virtualmode" -contains $_.Backing.CompatibilityMode){
      $disk = $_.Backing.LunUuid.Substring(10,32)
      $key = (Get-View $vm.Runtime.Host).Name.Split(".")[0] + "-" + $disk
      $scsiTab[$key][1] = $vm.Name + "/" + $_.DeviceInfo.Label
    }
  }
}
 
$scsiTab.GetEnumerator() | Group-Object -Property {$_.Key.Split("-")[1]} | %{
  $lun = New-Object ("LunInfo" + $rndNum)
  $lun.ClusterName = $clusName
  $_.Group | %{
    $esxName = $_.Key.Split("-")[0]
    $lun.$esxName = "ok"
    if(!$lun.CanonicalName){$lun.CanonicalName = $_.Value[0]}
    if(!$lun.UsedBy){$lun.UsedBy = $_.Value[1]}
    if(!$lun.SizeMB){$lun.SizeMB = $_.Value[2]}
 
  }
  $lun
} | Export-Csv $csvName -NoTypeInformation -UseCulture
Invoke-Item $csvName

———

Copy/Paste the above text in a notepad and  save the file as ClusterLUNList.ps1 (in c:\scripts folder) or with another name of your choice. For annotation details visit Luc’s blog post

Let’s use PowerCLI to connect to vCenter first

POWERCLI C:\scripts> Connect-VIServer -server vCentername (assuming you use domain credentials)

If you don’t use domain credentials connect using

POWERCLI C:\scripts> Connect-VIServer -server vCentername -user Username -password Password (note that you can use lower case letters for the command syntax and it works fine except for your user id and password)

POWERCLI C:\scripts> Get-Cluster (this should provide you with the cluster names for the vCenter that you connected to earlier)

If by any means you are confused as to what the actual cluster name should look like in a command line, then run the above command first

POWERCLI C:\scripts>.\ClusterLUNList.ps1 YourClusterName

This should generate a CSV file in the C:\Scripts\Output folder that you defined on the 1st line of the script. Review the script and note down the naa id’s. If you are confused on mapping the naa id with the actual LUNs you will need the help of your storage admin to give you the Host LUN Id from storage array. Then you can reference that against the device information in vCenter.

Moving ahead

1.  To detach a specific LUN with its Canonical Name (naa id) on a specific host – copy/paste the contents in a notepad file and save it with a name (I used DetachDisk.ps1 as the name)

—————-

function Detach-Disk{
param(
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.VMHostImpl]$VMHost,
[string]$CanonicalName
)

$storSys = Get-View $VMHost.Extensiondata.ConfigManager.StorageSystem
$lunUuid = (Get-ScsiLun -VmHost $VMHost |
where {$_.CanonicalName -eq $CanonicalName}).ExtensionData.Uuid

$storSys.DetachScsiLun($lunUuid)
}

$esx = get-vmhost YourEsxi.domainname.com
$name = “naa.0x0x0x0x0x0x0x0xnumber
Detach-Disk -VMHost $esx -CanonicalName $name

—————-

In the above script only replace “YourEsxi.domainname.com” and “naa.0x0x0x0x0x0x0x0xnumber” with your values.

Run the script

POWERCLI C:\scripts>.\DetachDisk.ps1

2.  To detach one LUN from multiple ESXi hosts that are part of one cluster you can copy/paste the following contents and save the script (save it for e.g. as DetachDiskMultipleHosts.ps1)

——–

function Detach-Disk{
param(
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.VMHostImpl]$VMHost,
[string]$CanonicalName
)

$storSys = Get-View $VMHost.Extensiondata.ConfigManager.StorageSystem
$lunUuid = (Get-ScsiLun -VmHost $VMHost |
where {$_.CanonicalName -eq $CanonicalName}).ExtensionData.Uuid

$storSys.DetachScsiLun($lunUuid)
}

$CanonicalName=”naa.6006016099102200173cd3d6202ee011
Get-Cluster -Name YourClusterName | Get-VMHost | %{Detach-Disk -VMHost $_ -CanonicalName $CanonicalName}

———

Note that you are only modifying the naa number above to the one you want to detach and providing the Cluster name manually. This is to ensure you don’t impact something else in the environment. Leave the rest of syntax as is

Run the above script with the following command

POWERCLI C:\scripts>.\DetachDiskMultipleHosts.ps1

3. Finally, if you need to detach multiple LUNs from multiple ESXi hosts then look at the next instance. In this scenario and using the script below, you will be able to detach a list of LUNs one at a time from each host, and do this activity on multiple hosts – all through one script

——–

function Detach-Disk{
param(
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.VMHostImpl]$VMHost,
[string]$CanonicalName
)

$storSys = Get-View $VMHost.Extensiondata.ConfigManager.StorageSystem
$lunUuid = (Get-ScsiLun -VmHost $VMHost |
where {$_.CanonicalName -eq $CanonicalName}).ExtensionData.Uuid

$storSys.DetachScsiLun($lunUuid)
}
$hostslist = import-csv HostList.csv
$luns = import-csv LunList.csv

foreach ($vmhost in $hostslist){
$hostname=$vmhost.host
write-host “Starting $hostname”
$esx = get-vmhost $hostname
foreach ($lun in $luns){
$naa=$lun.naa
write-host “Detaching LUN $naa from $esx”
detach-disk -vmhost $esx -CanonicalName $naa
write-host “Detach Complete”
}
}

———

I have highlighted two CSV files that you need to keep in the C:\Scripts folder. The CSV file should have a header – in our case the HostList.csv will have a header row with text called host and the LUNList.csv file will have a header row with text called naa since we are trying to detach LUNs with naa id.

host
esxi17.domain.com
esxi11.domain.com
esxi13.domain.com

 

naa
naa.6006016059d02a00187932b4eebae111
naa.6006016059d02a00f4dbce8deebae111

 

Don’t forget that the files need to be saved as .csv

 

Afer that it is very straightforward and all you have to do is run the script. It will print information about the naa id that the script is detaching and the name of the host that the LUN is being detached on. I named my script DetachMultipleLunsOnHosts.ps1 and you may choose to pick a different name.

POWERCLI C:\scripts>.\DetachMultipleLunsOnHosts.ps1

 

Hope this helps and if you have any questions or feedback please drop a line or reach me via twitter.

Reference Links that I used

  • http://www.lucd.info/2010/04/09/lun-report-datastores-rdms-and-node-visibility/
  • http://www.lucd.info/2011/11/25/lun-juggling-in-vsphere-5/
  • https://communities.vmware.com/message/2265677
  • https://communities.vmware.com/thread/419714