PowerCLI script to forcibly delete a Datastore that is reported as in use.

Have you ever tried to delete a datastore and get an error saying the Datastore is in use? You browse the datastore and see nothing on it. The pre-checks when you unmount it all pass, yet you cannot delete it. We had this problem.

VMware support directed us to delete the partition using the partedUtil command, but I didn’t like the possibility of human error in doing it their way. I wrote a PowerCLI script that performs the following.
1. Connect to vCenter. (choose from a list if necessary)
2. Choose which Cluster has a host with the datastore.
3. Choose a host that the datastore is presented to.
4. Displays the contents of the datastore (same as BROWSE DATASTORE.
5. Validates to make sure the datastore doesn’t have sDRS turned on, has no VMs, no vD Swap File, not being used for HA Heartbeat, no SOIC, and doesn’t contain a scratch partition. This step utilizes a function written by Luc Dekens (@lucd22).
6. Displays the Runtime Name which includes the LUN ID to verify.
7. Displays the Canonical Name of the LUN to verify.
8. It then displays a warning that future steps will perform DESTRUCTIVE ACTIONS.
9. It then unmounts the datastore from all hosts that it’s currently mounted to.
10. SSH is started on the host in Step 3.
You’ll need to go into the code and enter the ID/PW.
11. It connects via SSH to the server you choose in STEP 3 and runs partedUtil getptbl to list the partitions on the device.
12. It DELETES the partition listed in STEP 10.
13. It runs partedUtil getptbl again to verify the partition has been removed.
14. SSH is stopped.
15. The datastore is DELETED/REMOVED.
16. The get-datastore command is run to verify it’s been removed (You should see RED TEXT when this runs (aka blood splatter).
16. It disconnects from vCenter.

 

In the documentation I wrote up for my team members, I put the following prerequisites…

– Delete all files (except the .sdd.sf folder) from the datastore before running the script.
– plink.exe should be stored in the root of the C drive.
– If at ANY POINT in the script something looks wrong, press CTRL-C to cancel the script

 

#################################################
#
# PowerCLI Script to Remove a datastore
# Created by BLiebowitz on 7/12/2017
# 
#################################################

# Define the LunDatastoreName 
# I found this function from: http://www.vsysad.com/2013/07/powercli-script-to-get-naa-and-datastore-name-of-all-storage-on-esx-server/
         function</pre><pre>	New-VIProperty -Name lunDatastoreName -ObjectType ScsiLun -Value {
		param($lun)
	 
		$ds = $lun.VMHost.ExtensionData.Datastore | %{Get-View $_} | `
			where {$_.Summary.Type -eq "VMFS" -and
				($_.Info.Vmfs.Extent | where {$_.DiskName -eq $lun.CanonicalName})}
		if($ds){
			$ds.Name
		}
	} -Force | Out-Null

# Build Pause Function
	Function Pause($M="Press any key to continue . . . "){If($psISE){$S=New-Object -ComObject "WScript.Shell";$B=$S.Popup("Click OK to continue.",0,"Script Paused",0);Return};Write-Host -NoNewline $M;$I=16,17,18,20,91,92,93,144,145,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183;While($K.VirtualKeyCode -Eq $Null -Or $I -Contains $K.VirtualKeyCode){$K=$Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")};Write-Host}	
	
# Define the GetStatstoreUnmountStatus Function
# function courtesy of Luc Dekens: http://www.lucd.info/2012/04/15/test-if-the-datastore-can-be-unmounted/
	function Get-DatastoreUnmountStatus{
	<# .SYNOPSIS Check if a datastore can be unmounted. .DESCRIPTION The function checks a number of prerequisites that need to be met to be able to unmount a datastore. .NOTES Author: Luc Dekens .PARAMETER Datastore The datastore for which you want to chekc the conditions. You can pass the name of the datastore or the Datastore object returned by Get-Datastore .EXAMPLE PS> Get-DatastoreUnmountStatus -Datastore DS1
	.EXAMPLE
	PS> Get-Datastore | Get-DatastoreUnmountStatus
	#>
	param(
	[CmdletBinding()]
	[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
	[PSObject[]]$Datastore
	)
	process{
	foreach($ds in $Datastore){
	if($ds.GetType().Name -eq "string"){
	$ds = Get-Datastore -Name $ds
	}
	$parent = Get-View $ds.ExtensionData.Parent
	New-Object PSObject -Property @{
	Datastore = $ds.Name
	# No Virtual machines
	NoVM = $ds.ExtensionData.VM.Count -eq 0
	# Not in a Datastore Cluster
	NoDastoreClusterMember = $parent -isnot [VMware.Vim.StoragePod]
	# Not managed by sDRS
	NosDRS = &{
	if($parent -is [VMware.Vim.StoragePod]){
	!$parent.PodStorageDrsEntry.StorageDrsConfig.PodConfig.Enabled
	}
	else {$true}
	}
	# SIOC disabled
	NoSIOC = !$ds.StorageIOControlEnabled
	# No HA heartbeat
	NoHAheartbeat = &{
	$hbDatastores = @()
	$cls = Get-View -ViewType ClusterComputeResource -Property Host |
	where{$_.Host -contains $ds.ExtensionData.Host[0].Key}
	if($cls){
	$cls | %{
	(                $_.RetrieveDasAdvancedRuntimeInfo()).HeartbeatDatastoreInfo | %{
	$hbDatastores += $_.Datastore
	}
	}
	$hbDatastores -notcontains $ds.ExtensionData.MoRef
	}
	else{$true}
	}
	# No vdSW file
	NovdSwFile = &{
	New-PSDrive -Location $ds -Name ds -PSProvider VimDatastore -Root '\' | Out-Null
	$result = Get-ChildItem -Path ds:\ -Recurse |
	where {$_.Name -match '.dvsData'}
	Remove-PSDrive -Name ds -Confirm:$false
	if($result){$false}else{$true}
	}
	# No scratch partition
	NoScratchPartition = &{
	$result = $true
	$ds.ExtensionData.Host | %{Get-View $_.Key} | %{
	$diagSys = Get-View $_.ConfigManager.DiagnosticSystem
	$dsDisks = $ds.ExtensionData.Info.Vmfs.Extent | %{$_.DiskName}
	if($dsDisks -contains $diagSys.ActivePartition.Id.DiskName){
	$result = $false
	}
	}
	$result
	}
	}
	}
	}
	}

# Define the Detach Datastore Function
# This function is courtsey of William Lan: https://blogs.vmware.com/vsphere/2012/01/automating-datastore-storage-device-detachment-in-vsphere-5.html
	Function Detach-Datastore {
		[CmdletBinding()]
		Param (
			[Parameter(ValueFromPipeline=$true)]
			$Datastore
		)
		Process {
			if (-not $Datastore) {
				Write-Host "No Datastore defined as input"
				Exit
			}
			Foreach ($ds in $Datastore) {
				$hostviewDSDiskName = $ds.ExtensionData.Info.vmfs.extent[0].Diskname
				if ($ds.ExtensionData.Host) {
					$attachedHosts = $ds.ExtensionData.Host
					Foreach ($VMHost in $attachedHosts) {
						$hostview = Get-View $VMHost.Key
						$StorageSys = Get-View $HostView.ConfigManager.StorageSystem
						$devices = $StorageSys.StorageDeviceInfo.ScsiLun
						Foreach ($device in $devices) {
							if ($device.canonicalName -eq $hostviewDSDiskName) {
								$LunUUID = $Device.Uuid
								Write-Host "Detaching LUN $($Device.CanonicalName) from host $($hostview.Name)..."
								$StorageSys.DetachScsiLun($LunUUID);
							}
						}
					}
				}
			}
		}
	}

# Define the Unmount Datastore Function
# This function is courtsey of William Lan: https://blogs.vmware.com/vsphere/2012/01/automating-datastore-storage-device-detachment-in-vsphere-5.html
	Function Unmount-Datastore {
		[CmdletBinding()]
		Param (
			[Parameter(ValueFromPipeline=$true)]
			$Datastore
		)
		Process {
			if (-not $Datastore) {
				Write-Host "No Datastore defined as input"
				Exit
			}
			Foreach ($ds in $Datastore) {
				$hostviewDSDiskName = $ds.ExtensionData.Info.vmfs.extent[0].Diskname
				if ($ds.ExtensionData.Host) {
					$attachedHosts = $ds.ExtensionData.Host
					Foreach ($VMHost in $attachedHosts) {
						$hostview = Get-View $VMHost.Key
						$StorageSys = Get-View $HostView.ConfigManager.StorageSystem
						Write-Host "Unmounting VMFS Datastore $($DS.Name) from host $($hostview.Name)..."
						$StorageSys.UnmountVmfsVolume($DS.ExtensionData.Info.vmfs.uuid);
					}
				}
			}
		}
	}	
	
# Select which vCenter you want to connect to
# Build array for each vCenter
	Write-host "Select which vCenter to connect to:"
	Write-Host ""
	Write-Host "1. vCenter1"
	Write-Host "2. vCenter2"
	Write-Host "3. vCenter3"

	$Ivcenter = read-host "Select a vCenter Server. Enter Number."
	 
	if ($Ivcenter -match "1") {
	$vcenter = "vCenter1"
	} elseif ($Ivcenter -match "2") {
	$vcenter = "vCenter2"
	} else {
	$vcenter = "vCenter3"
	} 
	 
	write-host ""
	Write-Host "You Picked: $($vcenter)"
	write-host ""
	start-sleep -s 3

# connect to selected vCenter
	connect-viserver $vcenter

# List Clusters
	write-host ""
	Write-host "Choose which Cluster where the LUN you want to remove presented:"
	write-host "(it may take a few seconds to build the list)"
	write-host ""
	$ICLUSTER = get-cluster | Select Name | Sort-object Name
	$i = 1
	$ICLUSTER | %{Write-Host $i":" $_.Name; $i++}
	$HCLUSTER = Read-host "Enter the number for the host to Patch."
	$SCLUSTER = $ICLUSTER[$HCLUSTER -1].Name
	write-host "You have selected $($SCLUSTER)."
	start-sleep -s 3
	
# List hosts to select
	write-host ""
	Write-host "Choose which vSphere host that has the LUN presented."
	write-host "(it may take a few seconds to build the list)"
	write-host ""
	$IHOST = get-cluster $SCLUSTER | Get-VMhost | Select Name | Sort-object Name
	$i = 1
	$IHOST | %{Write-Host $i":" $_.Name; $i++}
	$DSHost = Read-host "Enter the number for the host to Patch."
	$SHOST = $IHOST[$DSHost -1].Name
	write-host "you have selected" $SHOST"."	

# List all scsi devices
	write-host ""
	Write-host "Choose which LUN to remove.  *** VERIFY VIA THE vSPHERE CLIENT ***"
	write-host "(it may take a minute to build the list)"
	write-host ""
	$ILUN = get-scsilun -vmhost $SHOST | Select LunDatastoreName, CanonicalName, RuntimeName, CapacityGB | Sort lundatastorename
	$i = 1
	$ILUN | %{Write-Host $i":" $_.lunDatastoreName, $_.RuntimeName, $_.CapacityGB; $i++}
	$DSLUN = Read-host "Enter the number for the LUN to remove."
	$SLUN = $ILUN[$DSLUN -1].LunDatastoreName
	write-host "you have selected" $SLUN"."

# List the files on the LUN you selected
	get-childitem (get-datastore $SLUN).datastorebrowserpath | Select FullName

# Pause for input while you verify the Datastore Contents.
	Write-host "Verify there is nothing on the datastore."
	Write-Host "FYI - The .sdd.sf Folder cannot be removed."
	Pause
	
# Check to see if the datastore is in use
	Get-DatastoreUnmountStatus -datastore $SLUN
	
# Pause for input while datastore unmount status is verified.
	Write-Host "Verify the datastore passes unmount verification."  
	Write-host "All should be set to TRUE"
	Pause
	
# Verify the LUN ID is correct
	Write-Host ""
	Get-Datastore $SLUN | get-scsilun | Select -First 1 -ExpandProperty RuntimeName	
	Write-Host ""
	
# Pause for input while the LUN ID is verified
	Write-Host "Verify the last characters of the LUN ID match."
	Pause
	
# Pipe datastore to get-scsilun to get canonicalname
	$LUN = Get-Datastore $SLUN | get-scsilun | Select -First 1 -ExpandProperty CanonicalName
	Write-Host "The CanonicalName of the Datastore is $($LUN)"
	
# Warn about future steps will perform destructive actions
	Write-Host ""
	Write-Host ""
	Write-Host "WARNING:  All Steps from here on out will perform DESTRUCTIVE ACTIONS!!"
	Write-Host "Press CTRL-C to cancel the script or any key to continue"
	Write-Host ""
	Write-Host ""
	Pause

# Unmount the Datastore
	get-datastore $SLUN | Unmount-Datastore
	
# Pause and verify the Datastore was unmounted successfully
	Write-host "Verify Datastore $($SLUN) Unmounted successfully"
	Pause
	
# Start SSH
	Write-Host "Starting SSH"
	$ssh = Get-VMHostService -vmhost $SHOST | Where {$_.Key -eq "TSM-SSH"}
	Start-VMHostService -HostService ($ssh) -Confirm:$false 

# Verify SSH started successfully	
	Write-Host "Verify SSH started successfully."
	Pause

# Validate and delete the partition
	$User = "root"
	$Pswd = "password"
	$plink = "c:\plink.exe"

	$plinkoptions = " -v -batch -pw $Pswd"
	$cmd1 = 'partedUtil getptbl /vmfs/devices/disks/$LUN'

	$remoteCommand = '"' + $cmd1 + '"'
	$command = $plink + " " + $plinkoptions + " " + $User + "@" + $SHOST + " " + $remoteCommand

	$msg = Invoke-Expression -command $command
	Write-Host "This command displays the partitions on the LUN."
	$msg
	Pause

	$cmd1 = "partedUtil delete /vmfs/devices/disks/$LUN 1"
	
	$remoteCommand = '"' + $cmd1 + '"'
	$command = $plink + " " + $plinkoptions + " " + $User + "@" + $SHOST + " " + $remoteCommand
	
	$msg = Invoke-Expression -command $command
	
	Write-Host "This command DELETES the partition on the LUN."
	$msg
	Pause
	
	$cmd1 = 'partedUtil getptbl /vmfs/devices/disks/$LUN'

	$remoteCommand = '"' + $cmd1 + '"'
	$command = $plink + " " + $plinkoptions + " " + $User + "@" + $SHOST + " " + $remoteCommand

	$msg = Invoke-Expression -command $command
	write-host "This command verifies the partition has been removed."
	$msg
	Pause
	
# Stop SSH
	Write-Host "Stopping SSH"
	Stop-VMHostService -HostService ($ssh) -Confirm:$false 	
	
# Detach the LUN
	Get-datastore $SLUN | Detach-Datastore  

# Pause and verify the Datastore was Detached successfully
	Write-host "Verify Datastore $($SLUN) Detached successfully"
	Pause
	
# Delete Datastore
	get-datastore $SLUN | get-vmhost | remove-datastore $SLUN -confirm:$false
	
# Verify Datastore is removed
	Write-Host "Verify the datastore has been removed."
	Write-Host "There SHOULD be red text (aka blood spatter) below."
	get-datastore $SLUN 
	
# Disconnect from vCenter
	disconnect-viserver $vcenter -confirm:$false
	

Use this wisely. As I said, it performs a destructive action.

Ben Liebowitz, VCP, vExpert
NJ VMUG Leader

Share This:

5 thoughts on “PowerCLI script to forcibly delete a Datastore that is reported as in use.

  1. If you actually have performed those checks and all done, the only reason is VM snapshot(s) that references to ISO which was on that datastore. Find and delete those snapshots and you will be able to remove the datastore.

    1. The datastore was completely blank. No VM files or anything were present. It even passed the vCenter check for it being in use.

      We worked with VMware support who gave us the PartedUtil commands to run to get rid of it. I just scripted the process. 🙂

  2. Any chance you could post a link to the raw script? The one here gets all f’d up by the code display script.

    Eg. the first line of the first function shows as:
    “function</pre><pre> New-VIProperty -Name lunDatastoreName -ObjectType ScsiLun -Value {”

    This is on multiple OSes and browsers.

    1. Here you go.

      #################################################
      #
      # PowerCLI Script to Remove a datastore
      # Created by BLiebowitz on 7/12/2017
      #
      #################################################

      # Define the LunDatastoreName
      # I found this function from: http://www.vsysad.com/2013/07/powercli-script-to-get-naa-and-datastore-name-of-all-storage-on-esx-server/
      function</pre><pre> New-VIProperty -Name lunDatastoreName -ObjectType ScsiLun -Value {
      param($lun)

      $ds = $lun.VMHost.ExtensionData.Datastore | %{Get-View $_} | `
      where {$_.Summary.Type -eq “VMFS” -and
      ($_.Info.Vmfs.Extent | where {$_.DiskName -eq $lun.CanonicalName})}
      if($ds){
      $ds.Name
      }
      } -Force | Out-Null

      # Build Pause Function
      Function Pause($M=”Press any key to continue . . . “){If($psISE){$S=New-Object -ComObject “WScript.Shell”;$B=$S.Popup(“Click OK to continue.”,0,”Script Paused”,0);Return};Write-Host -NoNewline $M;$I=16,17,18,20,91,92,93,144,145,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183;While($K.VirtualKeyCode -Eq $Null -Or $I -Contains $K.VirtualKeyCode){$K=$Host.UI.RawUI.ReadKey(“NoEcho,IncludeKeyDown”)};Write-Host}

      # Define the GetStatstoreUnmountStatus Function
      # function courtesy of Luc Dekens: http://www.lucd.info/2012/04/15/test-if-the-datastore-can-be-unmounted/
      function Get-DatastoreUnmountStatus{
      &lt;# .SYNOPSIS Check if a datastore can be unmounted. .DESCRIPTION The function checks a number of prerequisites that need to be met to be able to unmount a datastore. .NOTES Author: Luc Dekens .PARAMETER Datastore The datastore for which you want to chekc the conditions. You can pass the name of the datastore or the Datastore object returned by Get-Datastore .EXAMPLE PS&gt; Get-DatastoreUnmountStatus -Datastore DS1
      .EXAMPLE
      PS&gt; Get-Datastore | Get-DatastoreUnmountStatus
      #&gt;
      param(
      [CmdletBinding()]
      [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
      [PSObject[]]$Datastore
      )
      process{
      foreach($ds in $Datastore){
      if($ds.GetType().Name -eq “string”){
      $ds = Get-Datastore -Name $ds
      }
      $parent = Get-View $ds.ExtensionData.Parent
      New-Object PSObject -Property @{
      Datastore = $ds.Name
      # No Virtual machines
      NoVM = $ds.ExtensionData.VM.Count -eq 0
      # Not in a Datastore Cluster
      NoDastoreClusterMember = $parent -isnot [VMware.Vim.StoragePod]
      # Not managed by sDRS
      NosDRS = &amp;{
      if($parent -is [VMware.Vim.StoragePod]){
      !$parent.PodStorageDrsEntry.StorageDrsConfig.PodConfig.Enabled
      }
      else {$true}
      }
      # SIOC disabled
      NoSIOC = !$ds.StorageIOControlEnabled
      # No HA heartbeat
      NoHAheartbeat = &amp;{
      $hbDatastores = @()
      $cls = Get-View -ViewType ClusterComputeResource -Property Host |
      where{$_.Host -contains $ds.ExtensionData.Host[0].Key}
      if($cls){
      $cls | %{
      ( $_.RetrieveDasAdvancedRuntimeInfo()).HeartbeatDatastoreInfo | %{
      $hbDatastores += $_.Datastore
      }
      }
      $hbDatastores -notcontains $ds.ExtensionData.MoRef
      }
      else{$true}
      }
      # No vdSW file
      NovdSwFile = &amp;{
      New-PSDrive -Location $ds -Name ds -PSProvider VimDatastore -Root ‘\’ | Out-Null
      $result = Get-ChildItem -Path ds:\ -Recurse |
      where {$_.Name -match ‘.dvsData’}
      Remove-PSDrive -Name ds -Confirm:$false
      if($result){$false}else{$true}
      }
      # No scratch partition
      NoScratchPartition = &amp;{
      $result = $true
      $ds.ExtensionData.Host | %{Get-View $_.Key} | %{
      $diagSys = Get-View $_.ConfigManager.DiagnosticSystem
      $dsDisks = $ds.ExtensionData.Info.Vmfs.Extent | %{$_.DiskName}
      if($dsDisks -contains $diagSys.ActivePartition.Id.DiskName){
      $result = $false
      }
      }
      $result
      }
      }
      }
      }
      }

      # Define the Detach Datastore Function
      # This function is courtsey of William Lan: https://blogs.vmware.com/vsphere/2012/01/automating-datastore-storage-device-detachment-in-vsphere-5.html
      Function Detach-Datastore {
      [CmdletBinding()]
      Param (
      [Parameter(ValueFromPipeline=$true)]
      $Datastore
      )
      Process {
      if (-not $Datastore) {
      Write-Host “No Datastore defined as input”
      Exit
      }
      Foreach ($ds in $Datastore) {
      $hostviewDSDiskName = $ds.ExtensionData.Info.vmfs.extent[0].Diskname
      if ($ds.ExtensionData.Host) {
      $attachedHosts = $ds.ExtensionData.Host
      Foreach ($VMHost in $attachedHosts) {
      $hostview = Get-View $VMHost.Key
      $StorageSys = Get-View $HostView.ConfigManager.StorageSystem
      $devices = $StorageSys.StorageDeviceInfo.ScsiLun
      Foreach ($device in $devices) {
      if ($device.canonicalName -eq $hostviewDSDiskName) {
      $LunUUID = $Device.Uuid
      Write-Host “Detaching LUN $($Device.CanonicalName) from host $($hostview.Name)…”
      $StorageSys.DetachScsiLun($LunUUID);
      }
      }
      }
      }
      }
      }
      }

      # Define the Unmount Datastore Function
      # This function is courtsey of William Lan: https://blogs.vmware.com/vsphere/2012/01/automating-datastore-storage-device-detachment-in-vsphere-5.html
      Function Unmount-Datastore {
      [CmdletBinding()]
      Param (
      [Parameter(ValueFromPipeline=$true)]
      $Datastore
      )
      Process {
      if (-not $Datastore) {
      Write-Host “No Datastore defined as input”
      Exit
      }
      Foreach ($ds in $Datastore) {
      $hostviewDSDiskName = $ds.ExtensionData.Info.vmfs.extent[0].Diskname
      if ($ds.ExtensionData.Host) {
      $attachedHosts = $ds.ExtensionData.Host
      Foreach ($VMHost in $attachedHosts) {
      $hostview = Get-View $VMHost.Key
      $StorageSys = Get-View $HostView.ConfigManager.StorageSystem
      Write-Host “Unmounting VMFS Datastore $($DS.Name) from host $($hostview.Name)…”
      $StorageSys.UnmountVmfsVolume($DS.ExtensionData.Info.vmfs.uuid);
      }
      }
      }
      }
      }

      # Select which vCenter you want to connect to
      # Build array for each vCenter
      Write-host “Select which vCenter to connect to:”
      Write-Host “”
      Write-Host “1. vCenter1”
      Write-Host “2. vCenter2”
      Write-Host “3. vCenter3”

      $Ivcenter = read-host “Select a vCenter Server. Enter Number.”

      if ($Ivcenter -match “1”) {
      $vcenter = “vCenter1”
      } elseif ($Ivcenter -match “2”) {
      $vcenter = “vCenter2”
      } else {
      $vcenter = “vCenter3”
      }

      write-host “”
      Write-Host “You Picked: $($vcenter)”
      write-host “”
      start-sleep -s 3

      # connect to selected vCenter
      connect-viserver $vcenter

      # List Clusters
      write-host “”
      Write-host “Choose which Cluster where the LUN you want to remove presented:”
      write-host “(it may take a few seconds to build the list)”
      write-host “”
      $ICLUSTER = get-cluster | Select Name | Sort-object Name
      $i = 1
      $ICLUSTER | %{Write-Host $i”:” $_.Name; $i++}
      $HCLUSTER = Read-host “Enter the number for the host to Patch.”
      $SCLUSTER = $ICLUSTER[$HCLUSTER -1].Name
      write-host “You have selected $($SCLUSTER).”
      start-sleep -s 3

      # List hosts to select
      write-host “”
      Write-host “Choose which vSphere host that has the LUN presented.”
      write-host “(it may take a few seconds to build the list)”
      write-host “”
      $IHOST = get-cluster $SCLUSTER | Get-VMhost | Select Name | Sort-object Name
      $i = 1
      $IHOST | %{Write-Host $i”:” $_.Name; $i++}
      $DSHost = Read-host “Enter the number for the host to Patch.”
      $SHOST = $IHOST[$DSHost -1].Name
      write-host “you have selected” $SHOST”.”

      # List all scsi devices
      write-host “”
      Write-host “Choose which LUN to remove. *** VERIFY VIA THE vSPHERE CLIENT ***”
      write-host “(it may take a minute to build the list)”
      write-host “”
      $ILUN = get-scsilun -vmhost $SHOST | Select LunDatastoreName, CanonicalName, RuntimeName, CapacityGB | Sort lundatastorename
      $i = 1
      $ILUN | %{Write-Host $i”:” $_.lunDatastoreName, $_.RuntimeName, $_.CapacityGB; $i++}
      $DSLUN = Read-host “Enter the number for the LUN to remove.”
      $SLUN = $ILUN[$DSLUN -1].LunDatastoreName
      write-host “you have selected” $SLUN”.”

      # List the files on the LUN you selected
      get-childitem (get-datastore $SLUN).datastorebrowserpath | Select FullName

      # Pause for input while you verify the Datastore Contents.
      Write-host “Verify there is nothing on the datastore.”
      Write-Host “FYI – The .sdd.sf Folder cannot be removed.”
      Pause

      # Check to see if the datastore is in use
      Get-DatastoreUnmountStatus -datastore $SLUN

      # Pause for input while datastore unmount status is verified.
      Write-Host “Verify the datastore passes unmount verification.”
      Write-host “All should be set to TRUE”
      Pause

      # Verify the LUN ID is correct
      Write-Host “”
      Get-Datastore $SLUN | get-scsilun | Select -First 1 -ExpandProperty RuntimeName
      Write-Host “”

      # Pause for input while the LUN ID is verified
      Write-Host “Verify the last characters of the LUN ID match.”
      Pause

      # Pipe datastore to get-scsilun to get canonicalname
      $LUN = Get-Datastore $SLUN | get-scsilun | Select -First 1 -ExpandProperty CanonicalName
      Write-Host “The CanonicalName of the Datastore is $($LUN)”

      # Warn about future steps will perform destructive actions
      Write-Host “”
      Write-Host “”
      Write-Host “WARNING: All Steps from here on out will perform DESTRUCTIVE ACTIONS!!”
      Write-Host “Press CTRL-C to cancel the script or any key to continue”
      Write-Host “”
      Write-Host “”
      Pause

      # Unmount the Datastore
      get-datastore $SLUN | Unmount-Datastore

      # Pause and verify the Datastore was unmounted successfully
      Write-host “Verify Datastore $($SLUN) Unmounted successfully”
      Pause

      # Start SSH
      Write-Host “Starting SSH”
      $ssh = Get-VMHostService -vmhost $SHOST | Where {$_.Key -eq “TSM-SSH”}
      Start-VMHostService -HostService ($ssh) -Confirm:$false

      # Verify SSH started successfully
      Write-Host “Verify SSH started successfully.”
      Pause

      # Validate and delete the partition
      $User = “root”
      $Pswd = “password”
      $plink = “c:\plink.exe”

      $plinkoptions = ” -v -batch -pw $Pswd”
      $cmd1 = ‘partedUtil getptbl /vmfs/devices/disks/$LUN’

      $remoteCommand = ‘”‘ + $cmd1 + ‘”‘
      $command = $plink + ” ” + $plinkoptions + ” ” + $User + “@” + $SHOST + ” ” + $remoteCommand

      $msg = Invoke-Expression -command $command
      Write-Host “This command displays the partitions on the LUN.”
      $msg
      Pause

      $cmd1 = “partedUtil delete /vmfs/devices/disks/$LUN 1″

      $remoteCommand = ‘”‘ + $cmd1 + ‘”‘
      $command = $plink + ” ” + $plinkoptions + ” ” + $User + “@” + $SHOST + ” ” + $remoteCommand

      $msg = Invoke-Expression -command $command

      Write-Host “This command DELETES the partition on the LUN.”
      $msg
      Pause

      $cmd1 = ‘partedUtil getptbl /vmfs/devices/disks/$LUN’

      $remoteCommand = ‘”‘ + $cmd1 + ‘”‘
      $command = $plink + ” ” + $plinkoptions + ” ” + $User + “@” + $SHOST + ” ” + $remoteCommand

      $msg = Invoke-Expression -command $command
      write-host “This command verifies the partition has been removed.”
      $msg
      Pause

      # Stop SSH
      Write-Host “Stopping SSH”
      Stop-VMHostService -HostService ($ssh) -Confirm:$false

      # Detach the LUN
      Get-datastore $SLUN | Detach-Datastore

      # Pause and verify the Datastore was Detached successfully
      Write-host “Verify Datastore $($SLUN) Detached successfully”
      Pause

      # Delete Datastore
      get-datastore $SLUN | get-vmhost | remove-datastore $SLUN -confirm:$false

      # Verify Datastore is removed
      Write-Host “Verify the datastore has been removed.”
      Write-Host “There SHOULD be red text (aka blood spatter) below.”
      get-datastore $SLUN

      # Disconnect from vCenter
      disconnect-viserver $vcenter -confirm:$false

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.