PowerCLI script to forcibly delete a Datastore that is reported as in use.
- Ben Liebowitz
- 5
- 3955
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{ &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
Use this wisely. As I said, it performs a destructive action.
Ben Liebowitz, VCP, vExpert
NJ VMUG Leader
5 thoughts on “PowerCLI script to forcibly delete a Datastore that is reported as in use.”
Leave a Reply Cancel reply
This site uses Akismet to reduce spam. Learn how your comment data is processed.
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.
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. 🙂
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.
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{
<# .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
The comment was changed from what I wrote in the box, but you get the gist.