-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathActiveDR Full Failover.ps1
275 lines (149 loc) · 10.3 KB
/
ActiveDR Full Failover.ps1
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
##############################################################################################################################
# ActiveDR - Manual Failover for SQL Server
#
# Scenario:
# Manually failover Production to DR. Then fully failback.
#
# Single test database "ExampleDb" on two RDM volumes: data & log, on each SQL Server.
#
# Prerequisites:
# 1. DR Pod needs to be pre-created
# 2. Databases in DR Pod need to be "initialized" by being presented and attached to the DR SQL Server, then set offline
# 3. After Step 2 initialization, be sure to retrieve applicable DR disk serial numbers & substitute in code
# 4. On DR server, SQL Server service off. Service auto-start should be set to Manual as well.
#
# Usage Notes:
# This script is meant to be run in chunks; note the Part X headers. Each Part represents an independent workflow in
# the greater context of a DR manual failover and manual failback. DO NOT run everything at once!
#
# Disclaimer:
# This example script is provided AS-IS and meant to be a building block to be adapted to fit an individual
# organization's infrastructure.
##############################################################################################################################
#########################################
# PART 1: DEMOTE PRODUCTION POD
#########################################
# Import PowerShell modules
Import-Module PureStoragePowerShellSDK2
Import-Module SqlServer
# Set Variables
$ProductionArrayName = "flasharray1.example.com" # Production FlashArray
$PodName = "ActiveDrPod" # Pod name on the DR FlashArray
$ProductionSQLServer = "SqlServer1" # Production SQL Server
$DatabaseName = "ExampleDb" # Name of database
$TargetDiskSerialNumber1 = '6000c02022cb876dcd321example01a' # Target Disk Serial Number - ex: Data volume
$TargetDiskSerialNumber2 = '6000c02022cb876dcd321example02b' # Target Disk Serial Number - ex: Log volume
# Connect to Production VM
$ProductionSQLServerSession = New-PSSession -ComputerName $ProductionSQLServer
# Connect to FlashArray
$Credential = Get-Credential
$FlashArray = Connect-Pfa2Array -Endpoint $DRArrayName -Credential $Credential -IgnoreCertificateError
# Offline the database
$Query = "ALTER DATABASE [$DatabaseName] SET OFFLINE WITH ROLLBACK IMMEDIATE"
Invoke-Sqlcmd -ServerInstance $ProductionSQLServer -Database master -Query $Query
# Offline the volumes
Invoke-Command -Session $ProductionSQLServerSession -ScriptBlock { Get-Disk | Where-Object { $_.SerialNumber -eq $using:TargetDiskSerialNumber1 } | Set-Disk -IsOffline $True }
Invoke-Command -Session $ProductionSQLServerSession -ScriptBlock { Get-Disk | Where-Object { $_.SerialNumber -eq $using:TargetDiskSerialNumber2 } | Set-Disk -IsOffline $True }
# Confirm state of disks
Invoke-Command -Session $ProductionSQLServerSession -ScriptBlock { Get-Disk | Format-Table }
# Demote Production Pod with Quiesce
Update-Pfa2Pod -Array $FlashArray -Name $PodName -Quiesce $True -RequestedPromotionState "demoted"
# Confirm Production Pod status - PromotionStatus : demoted
Get-Pfa2Pod -Array $FlashArray -Name $PodName
#########################################
# PART 2: PROMOTE DR FAILOVER POD
#########################################
# Import PowerShell modules
Import-Module PureStoragePowerShellSDK2
Import-Module SqlServer
# Set Variables
$DRArrayName = "flasharray1.example.com" # DR FlashArray
$PodName = "ActiveDrPod" # Pod name on the DR FlashArray
$DRSQLServer = "SqlServer1" # Production SQL Server
$DatabaseName = "ExampleDb" # Name of database
# Connect to DR VM
$DRSQLServerSession = New-PSSession -ComputerName $DRSQLServer
# Connect to FlashArray
$Credential = Get-Credential
$FlashArray = Connect-Pfa2Array -Endpoint $DRArrayName -Credential $Credential -IgnoreCertificateError
# Promote DR pod
Update-Pfa2Pod -Array $FlashArray -Name $PodName -RequestedPromotionState "promoted"
# Confirm pod promoted - PromotionStatus : promoted
Get-Pfa2Pod -Array $FlashArray -Name $PodName
# Disks will be presented back to Windows but serial number may not be materialized.
# Because disk serial number can change between reboots, need to programmatically reference
# serial number to properly identify which disks to manipulate.
# Use Get-Disk to determine disk serial numbers
Invoke-Command -Session $DRSQLServerSession -ScriptBlock { Get-Disk | Format-Table }
# Set disk serial numbers to variables
$TargetDiskSerialNumber1 = "6000c02022cb876dcd321example01a" # Serial Number of data disk
$TargetDiskSerialNumber2 = "6000c02022cb876dcd321example02b" # Serial Number of log disk
# Waiting for DR volumes to come online
while (($DiskOne -eq $null) -or ($DiskTwo -eq $null)) {
Invoke-Command -Session $DRSQLServerSession -ScriptBlock { Update-HostStorageCache }
$DiskOne = Invoke-Command -Session $DRSQLServerSession -ScriptBlock { Get-Disk | Where-Object { $_.SerialNumber -eq $using:TargetDiskSerialNumber1 } }
$DiskTwo = Invoke-Command -Session $DRSQLServerSession -ScriptBlock { Get-Disk | Where-Object { $_.SerialNumber -eq $using:TargetDiskSerialNumber2 } }
}
# Online the windows disks
Invoke-Command -Session $DRSQLServerSession -ScriptBlock { Get-Disk | Where-Object { $_.SerialNumber -eq $using:TargetDiskSerialNumber1 } | Set-Disk -IsOffline $False }
Invoke-Command -Session $DRSQLServerSession -ScriptBlock { Get-Disk | Where-Object { $_.SerialNumber -eq $using:TargetDiskSerialNumber2 } | Set-Disk -IsOffline $False }
# Setting volumes to Read/Write
Invoke-Command -Session $DRSQLServerSession -ScriptBlock { Get-Disk | Where-Object { $_.SerialNumber -eq $using:TargetDiskSerialNumber1 } | Set-Disk -IsReadOnly $False }
Invoke-Command -Session $DRSQLServerSession -ScriptBlock { Get-Disk | Where-Object { $_.SerialNumber -eq $using:TargetDiskSerialNumber2 } | Set-Disk -IsReadOnly $False }
# Confirm state of disks
Invoke-Command -Session $DRSQLServerSession -ScriptBlock { Get-Disk | Format-Table }
# Online the database
$Query = "ALTER DATABASE [$DatabaseName] SET ONLINE WITH ROLLBACK IMMEDIATE"
Invoke-Sqlcmd -ServerInstance $DRSQLServer -Database master -Query $Query
#########################################
# PART 3: FAILBACK DR TO PRODUCTION
#########################################
# Import PowerShell modules
Import-Module PureStoragePowerShellSDK2
Import-Module SqlServer
# Set Variables
$ProductionArrayName = "flasharray1.example.com" # Production FlashArray
$DRArrayName = "flasharray1.example.com" # DR FlashArray
$PodName = "ActiveDrPod" # Pod name on the DR FlashArray
$ProductionSQLServer = "SqlServer1" # Production SQL Server
$DRSQLServer = "SqlServer1" # DR SQL Server
$DatabaseName = "ExampleDb" # Name of database
$TargetDiskSerialNumber1 = '6000c02022cb876dcd321example01a' # Target Disk Serial Number - ex: Data volume
$TargetDiskSerialNumber2 = '6000c02022cb876dcd321example02b' # Target Disk Serial Number - ex: Log volume
# Connect to DR VM
$DRSQLServerSession = New-PSSession -ComputerName $DRSQLServer
# Connect to FlashArray
$Credential = Get-Credential
$FlashArray = Connect-Pfa2Array -Endpoint $DRArrayName -Credential $Credential -IgnoreCertificateError
# Offline the database
$Query = "ALTER DATABASE [$DatabaseName] SET OFFLINE WITH ROLLBACK IMMEDIATE"
Invoke-Sqlcmd -ServerInstance $DRSQLServer -Database master -Query $Query
# Offline the volume
Invoke-Command -Session $DRSQLServerSession -ScriptBlock { Get-Disk | Where-Object { $_.SerialNumber -eq $using:TargetDiskSerialNumber1 } | Set-Disk -IsOffline $True }
Invoke-Command -Session $DRSQLServerSession -ScriptBlock { Get-Disk | Where-Object { $_.SerialNumber -eq $using:TargetDiskSerialNumber2 } | Set-Disk -IsOffline $True }
# Confirm state of disks
Invoke-Command -Session $DRSQLServerSession -ScriptBlock { Get-Disk | Format-Table}
# Demote Production Pod with Quiesce
Update-Pfa2Pod -Array $FlashArray -Name $PodName -Quiesce $true -RequestedPromotionState "demoted"
# Confirm Production Pod status - PromotionStatus : demoted
Get-Pfa2Pod -Array $FlashArray | Where-Object {$_.Name -eq $PodName}
# Connect to Production VM
$ProductionSQLServerSession = New-PSSession -ComputerName $ProductionSQLServer
# Connect to FlashArray
$Credential = Get-Credential
$FlashArray = Connect-Pfa2Array -Endpoint $ProductionArrayName -Credential $Credential -IgnoreCertificateError
# Promote Production pod
Update-Pfa2Pod -Array $FlashArray -Name $PodName -RequestedPromotionState "promoted"
# Confirm pod promoted - PromotionStatus : promoted
Get-Pfa2Pod -Array $FlashArray -Name $PodName
# Online the windows disks
Invoke-Command -Session $ProductionSQLServerSession -ScriptBlock { Get-Disk | Where-Object { $_.SerialNumber -eq $using:TargetDiskSerialNumber1 } | Set-Disk -IsOffline $False }
Invoke-Command -Session $ProductionSQLServerSession -ScriptBlock { Get-Disk | Where-Object { $_.SerialNumber -eq $using:TargetDiskSerialNumber2 } | Set-Disk -IsOffline $False }
# Setting volumes to Read/Write
Invoke-Command -Session $ProductionSQLServerSession -ScriptBlock { Get-Disk | Where-Object { $_.SerialNumber -eq $using:TargetDiskSerialNumber1 } | Set-Disk -IsReadOnly $False }
Invoke-Command -Session $ProductionSQLServerSession -ScriptBlock { Get-Disk | Where-Object { $_.SerialNumber -eq $using:TargetDiskSerialNumber2 } | Set-Disk -IsReadOnly $False }
# Confirm state of disks
Invoke-Command -Session $ProductionSQLServerSession -ScriptBlock { Get-Disk | Format-Table }
# Online the database
$Query = "ALTER DATABASE [$DatabaseName] SET OFFLINE WITH ROLLBACK IMMEDIATE"
Invoke-Sqlcmd -ServerInstance $ProductionSQLServer -Database master -Query $Query