-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSafely-Remove-Datastores.ps1
More file actions
284 lines (226 loc) · 13.4 KB
/
Copy pathSafely-Remove-Datastores.ps1
File metadata and controls
284 lines (226 loc) · 13.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
<#
.AUTHOR
Andy Townsend - andy@alphatangoconsultants.com
.SYNOPSIS
This script will automate the process of unmounting & deleting datastores based on CSV file of input. Operations will only happen if the necessary pre-req checks are passed
.DESCRIPTION
The script will perform a number of checks before performing any unmount operations to ensure it is successful. The script will also reconfigure DS Heartbeat configuration as necessary.
The pre-requisites that this script checks are as follows. These are all things that could prevent a datastore from being unmounted.
- Ensure there are no VMs in the datastore
- Checks SIOC is disabled on the datastore.
- Checks if the datastore is being used for HA heartbeats
- Checks if the datastore is part of a datastore cluster
- Checks if the datastore is being used as a scratch partition
- Checks to see if VDS config has been written to the datastore. If it has and there are no VMs on the datastore then its safe to delete the files. These files are only necessary when VMs are restarted by HA
If any of the pre-reqs fail, it will attempt to fix them.
If SIOC is enabled, it will disable it.
If the DS is being used for HA heartbeats, it will set the preferred datastores to be any DS with 3PAR in the name.
If there is a .dvsData folder, and there are no VMs on the datastore, it will remove this folder as its no longer needed.
The script requires 3 inputs, the vCenter and Cluster Hostnames as well as the path to the dsInputCSV. An example of this file is below in the .NOTES section
.EXAMPLE
.\storage-reclaims.ps1 -vCenter vcenter.com -cluster myCluster -dsInputCSV .\myCluster-datastores.csv
.NOTES
dsInputCSV requires a CSV file with the headers Host, Datastore
#>
param (
[Parameter(Mandatory=$true)][String] $vCenter,
[Parameter(Mandatory=$true)][String] $cluster,
[Parameter(Mandatory=$true)][String] $dsInputCSV
)
#Import DatastoreFunctions.ps1 credit goes here http://blogs.vmware.com/vsphere/2012/01/automating-datastore-storage-device-detachment-in-vsphere-5.html
try {
Import-Module .\DatastoreFunctions.psm1 -DisableNameChecking -ErrorAction Stop 2>&1
}
catch [Exception] {
Write-Host $("Failed to load module DatastoreFunctions - Reason: " + $($_.Exception.Message)) -foreground red;
exit
}
# Ask for some credentials & stored in a credential object
$userName = "$env:USERDOMAIN\$env:USERNAME"
$passwd = Read-Host ("Enter Password for " + $userName) -AsSecureString:$true
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList $userName,$passwd
# Generate a filename including date/time and cluster name.
$now=Get-Date -Format "yyyyMMdd_HHmmss"
$filename = "$cluster-storage-reclaim-$now"
# Create a directory to contain the output for the cluster. Start-Transcript will fail to start if there isn't a folder to write into.
if (!(Test-Path ".\$cluster")){
New-Item -ItemType Directory -Path ".\$cluster" | Out-Null
}
# Make sure transcript isn't running already from a previous failed run of the script.
try{
Stop-Transcript | Out-Null
} catch [System.InvalidOperationException] {}
# Start transcript to record script output.
Start-Transcript -Path ".\$cluster\$filename.txt"
#Connect to vCenter
Try {
Connect-VIServer -Server $vCenter -Credential $cred | Out-Null
}
Catch {
Throw "Error Connecting to $Vcenter, Please check $Vcenter name AND/OR credentials"
}
Write-Host "Importing CSV of Datastores to unmount" -BackgroundColor Yellow -ForegroundColor Blue
$csvInput = Import-CSV $dsInputCSV
# Get a cluster object to work with later in the script
$objCluster = get-cluster $cluster
# Get the datastores in use for HA heartbeats in the cluster.
$hbDatastores = @()
$hbDatastores = $objCluster.ExtensionData.RetrieveDasAdvancedRuntimeInfo() | %{ $_.HeartbeatDatastoreInfo | %{(get-View -Id $_.Datastore).Name} }
######################################################
# Check if there are any active coredumps being used #
# Check every host in cluster #
######################################################
Write-Host "Checking $vmhost for active coredumps" -BackgroundColor Yellow -ForegroundColor Blue
$vmhosts = $objCluster | get-VMhost -state Connected
foreach($vmhost in $vmhosts){
$vmkDumpFile = (get-esxcli -vmhost $vmhost).system.coredump.file.list() | where {$_.Active -eq $true}
$vmkDumpFilePath = $vmkDumpFile.Path
if ($vmkDumpFile -eq $null){
Write-Host "No active coredumps found on $vmhost" -BackgroundColor DarkGreen -ForegroundColor Green
} else {
Write-Host "Active coredumps found on $vmhost" -BackgroundColor DarkRed -ForegroundColor Red
Write-Host "ACTION: Removing $vmkDumpFile from $vmhost" -BackgroundColor Gray -ForegroundColor Yellow
(get-esxcli -vmhost $vmhost).system.coredump.file.remove($vmkDumpFilePath,$true)
}
}
####################################################
# Start looping through each line in the CSV file. #
####################################################
foreach($item in $csvInput){
$vmhost = get-vmhost -name $item.Host
$vmhostDatastores = @()
$vmhostDatastores = $vmhost | get-datastore | Select Name
$datastore = ($item.Datastore).Trim()
if ($vmhostDatastores -match $datastore){
$ds = $vmhost | get-datastore -name $datastore
} else{
write-host $datastore "is not found on $vmhost" -BackgroundColor DarkRed -ForegroundColor Red
continue}
$ds = $vmhost | get-datastore -name $datastore
# Find the UUID of the disk that's being used as the scratch location
$scratchPartition = ($vmhost | get-AdvancedSetting -name "scratchConfig.configuredscratchlocation").Value
Write-Host "Running Pre-Requisites on $ds on $vmhost" -BackgroundColor Yellow -ForegroundColor Blue
$preReqsFailed = 0
###########################################################
# Check the datastore doesn't have any VMs running in it. #
###########################################################
if ($ds.ExtensionData.Vm.Count -ne 0) {
Write-Host "ERROR: $ds contains VMs" -BackgroundColor DarkRed -ForegroundColor Red
$noVMsInDS = $false
$preReqsFailed = $preReqsFailed + 1
} else {
Write-Host "PASS: $ds contains no VMs" -BackgroundColor DarkGreen -ForegroundColor Green
$noVMsInDS = $true
}
###########################################
# Check SIOC is disabled on the datastore #
###########################################
if ($ds.StorageIOControlEnabled){
Write-Host "FAIL: SIOC is enabled on $ds" -BackgroundColor DarkRed -ForegroundColor Red
Write-Host "ACTION: Disabling SIOC on $ds" -BackgroundColor Gray -ForegroundColor Yellow
$Error.Clear()
try{
set-datastore $ds -StorageIOControlEnabled $false -Confirm:$false | Out-Null
} catch {"FAIL: Unable to disable SIOC on $ds"}
if (!$Error){
Write-Host "PASS: SIOC is disabled on $ds" -BackgroundColor DarkGreen -ForegroundColor Green
}
} else { Write-Host "PASS: SIOC is disabled on $ds" -BackgroundColor DarkGreen -ForegroundColor Green }
##################################################################################
# Check if the datastore is in the array of datastores being used for heartbeats #
##################################################################################
if ($hbDatastores -contains $ds){
# Reconfigure the cluster to use any *3PAR* datastores for HA heartbeats
$preferredDatastores = "*3PAR*"
$dsMoRef = Get-Datastore -Name $preferredDatastores | %{$_.ExtensionData.MoRef}
$spec = New-Object Vmware.Vim.ClusterConfigSpec
$spec.dasConfig = New-Object Vmware.Vim.ClusterDasConfigInfo
$spec.dasConfig.hBDatastoreCandidatePolicy = "allFeasibleDsWithUserPreference"
$spec.dasConfig.heartbeatDatastore = $dsMoRef
$Error.Clear()
try{
Write-Host "ACTION: Updating HA Heartbeat datastores on $objCluster " -BackgroundColor Gray -ForegroundColor Yellow
$objCluster.ExtensionData.ReconfigureCluster($spec,$true)
} catch {"FAIL: Unable to update preferred HA hearbeat datastores" }
if (!$Error){
Write-Host "PASS: HA heartbeat datastores updated, $ds no longer used" -BackgroundColor DarkGreen -ForegroundColor Green
}
} else { Write-Host "PASS: $ds is not being used for HA heartbeats" -BackgroundColor DarkGreen -ForegroundColor Green }
####################################################
# Check if the datastore is in a Datastore Cluster #
####################################################
$dsParent = get-view $ds.ExtensionData.Parent
if ($dsParent -is [VMware.Vim.StoragePod]){
Write-Host "FAIL: $ds is part of a Datastore Cluster" -BackgroundColor DarkRed -ForegroundColor Red
$preReqsFailed = $preReqsFailed + 1
} else { Write-Host "PASS: $ds is not in a Datastore Cluster" -BackgroundColor DarkGreen -ForegroundColor Green }
################################################################
# Check if the datastore is being used for a scratch partition #
################################################################
if ($scratchPartition -eq "/vmfs/volumes/$($ds.ExtensionData.Info.VMfs.UUID)" ){
Write-Host "FAIL: $ds is being used as a scratch partition" -BackgroundColor DarkRed -ForegroundColor Red
} else { Write-Host "PASS: $ds is not being used as a scratch partition" -BackgroundColor DarkGreen -ForegroundColor Green }
#######################################################################
# Check if the datastore is being used to store any VDS configuration #
# If it does and $noVMsInDS is true then its safe to remove the file #
#######################################################################
New-PSDrive -Location $ds -Name ds -PSProvider VimDatastore -Root '\' | Out-null
$result = get-childitem -Path ds:\ | ?{$_.PSIsContainer} | Where {$_.Name -match '.dvsData'}
if($result){
if ($noVMsInDS){
#There's no VMs in this datastore so safe to delete
Write-Host "ACTION: Removing .dvsData folder from $ds" -BackgroundColor Gray -ForegroundColor Yellow
Remove-Item -Path ds:\.dvsData -Recurse -ErrorAction Stop -ErrorVariable $errs
if ($errs.Count -eq 0){
Write-Host "PASS: .dvsData removed from $ds" -BackgroundColor DarkGreen -ForegroundColor Green
} else { write-host "FAIL: Unable to remove .dvsData found in $ds" -BackgroundColor DarkRed -ForegroundColor Red }
}
}else{
write-host "PASS: no .dvsData found in $ds" -BackgroundColor DarkGreen -ForegroundColor Green
}
Remove-PSDrive -Name ds -Confirm:$false
#########################################################
# Check results and see if we can unmount the datastore #
#########################################################
if ($preReqsFailed -eq 0){
Write-Host "----Pre-Req Tests PASSED----" -BackgroundColor DarkGreen -ForegroundColor Green
#Unmount the Datastore from this host
Write-Host "ACTION: Unmounting $ds from $vmhost" -BackgroundColor Gray -ForegroundColor Yellow
get-datastore $ds | Unmount-Datastore -VMHost $vmhost -Confirm:$false -ErrorVariable $errs
if ($errs.Count -eq 0){
Write-Host "SUCCESS: $ds unmounted from $vmhost" -BackgroundColor DarkGreen -ForegroundColor Green
} else {
Write-Host "FAILED: $ds could not be unmounted from $vmhost" -BackgroundColor DarkRed -ForegroundColor Red
Exit
}
# Remove Datastore
Write-Host "ACTION: Removing $ds from $vmhost" -BackgroundColor Gray -ForegroundColor Yellow
Remove-Datastore -datastore $ds -VMhost $vmhost -Confirm:$false -ErrorVariable $errs
if ($errs.Count -eq 0){
Write-Host "SUCCESS: $ds removed from $cluster" -BackgroundColor DarkGreen -ForegroundColor Green
} else {
Write-Host "FAILED: $ds could not be removed from $cluster" -BackgroundColor DarkRed -ForegroundColor Red
Exit
}
<#
#Detach the LUN from this host
Write-Host "ACTION: Detaching $ds from $vmhost" -BackgroundColor Gray -ForegroundColor Yellow
Get-Datastore $ds | Detach-SCSILun -VMHost $vmhost -Confirm:$false -ErrorVariable $errs
if ($errs.Count -eq 0){
Write-Host "SUCCESS: $ds unmounted from $vmhost" -BackgroundColor DarkGreen -ForegroundColor Green
} else {
Write-Host "FAILED: $ds could not be unmounted from $vmhost" -BackgroundColor DarkRed -ForegroundColor Red
Exit
}
#>
} else {
Write-Host "$ds failed some of the pre-req checks, can't be unmounted at this time" -BackgroundColor DarkRed -ForegroundColor Red
}
}
Disconnect-VIserver * -confirm:$false
# Stop recording script output.
Stop-Transcript
# Fix up the file formatting of the log file. Write-Host doesn't include proper line endings.
$fixFileFormatting = Get-Content ".\$cluster\$filename.txt"
$fixFileFormatting > ".\$cluster\$filename.log"
Remove-Item ".\$cluster\$filename.txt"