Guest User

Untitled

a guest
Mar 22nd, 2018
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.40 KB | None | 0 0
  1. Add-PSSnapin -Name "Microsoft.SharePoint.PowerShell"
  2.  
  3.  
  4. function Invoke-NonQuery
  5. {
  6. [cmdletbinding()]
  7. param
  8. (
  9. [Parameter(Mandatory=$true, ParameterSetName = "ConnectionString")]
  10. [string]$ConnectionString,
  11.  
  12. [Parameter(Mandatory=$true, ParameterSetName = "ConnectionComponents")]
  13. [string]$DatabaseName,
  14.  
  15. [Parameter(Mandatory=$true, ParameterSetName = "ConnectionComponents")]
  16. [string]$DatabaseServer,
  17.  
  18. [Parameter(Mandatory=$true, ParameterSetName = "ConnectionString")]
  19. [Parameter(Mandatory=$true, ParameterSetName = "ConnectionComponents")]
  20. [string]$Query,
  21.  
  22. [Parameter(Mandatory=$false, ParameterSetName = "ConnectionString")]
  23. [Parameter(Mandatory=$false, ParameterSetName = "ConnectionComponents")]
  24. [int]$CommandTimeout = 30
  25. )
  26.  
  27. begin
  28. {
  29. if( $PSCmdlet.ParameterSetName -eq "ConnectionComponents" )
  30. {
  31. $connectionString = "Data Source=$DatabaseServer;Initial Catalog=$DatabaseName;Integrated Security=True;Pooling=false"
  32. }
  33. }
  34. process
  35. {
  36. Write-Verbose "$(Get-Date): $($MyInvocation.MyCommand.Name) - Query: $Query"
  37.  
  38. try
  39. {
  40. $connection = New-Object System.Data.SqlClient.SqlConnection($ConnectionString)
  41. $connection.Open()
  42.  
  43. $command = New-Object System.Data.SqlClient.SqlCommand($Query, $connection)
  44. $command.CommandTimeout = $CommandTimeout
  45. $command.CommandType = [System.Data.CommandType]::Text
  46. $command.ExecuteNonQuery() | Out-Null
  47. }
  48. catch
  49. {
  50. Write-Error -Message "Error executing query '$Query'. Exception: $_. Connection String: $ConnectionString"
  51. throw $_.Exception
  52. }
  53. finally
  54. {
  55. if($command)
  56. {
  57. $command.Dispose()
  58. }
  59.  
  60. if($connection)
  61. {
  62. [System.Data.SqlClient.SqlConnection]::ClearPool($connection)
  63. $connection.Close()
  64. $connection.Dispose()
  65. }
  66. }
  67. }
  68. end
  69. {
  70. }
  71. }
  72.  
  73. function Get-DataTable
  74. {
  75. [cmdletbinding()]
  76. param
  77. (
  78. [Parameter(Mandatory=$true)][string]$DatabaseServer,
  79. [Parameter(Mandatory=$true)][string]$DatabaseName,
  80. [Parameter(Mandatory=$true)][string]$Query
  81. )
  82.  
  83. $connectionString = "Data Source=$DatabaseServer;Initial Catalog=$DatabaseName;Integrated Security=True;Enlist=False;Connect Timeout=5"
  84.  
  85. Write-Verbose "$(Get-Date): $($MyInvocation.MyCommand.Name) - Query: $Query"
  86.  
  87. try
  88. {
  89. $dataSet = New-Object System.Data.DataSet
  90. $dataAdapter = New-Object System.Data.SqlClient.SqlDataAdapter($Query, $connectionString)
  91. $dataAdapter.Fill($dataSet) | Out-Null
  92. return $dataSet.Tables[0]
  93. }
  94. catch
  95. {
  96. Write-Error -Message "Error executing query '$Query'. Exception: $_. Connection String: $connectionString"
  97. throw $_.Exception
  98. }
  99. finally
  100. {
  101. if($dataSet)
  102. {
  103. $dataSet.Dispose()
  104. }
  105.  
  106. if($dataAdapter)
  107. {
  108. $dataAdapter.Dispose()
  109. }
  110. }
  111. }
  112.  
  113. function Invoke-ScalarQuery
  114. {
  115. [cmdletbinding()]
  116. param
  117. (
  118. [Parameter(Mandatory=$true)][string]$DatabaseName,
  119. [Parameter(Mandatory=$true)][string]$DatabaseServer,
  120. [Parameter(Mandatory=$true)][string]$Query,
  121. [int]$CommandTimeout=30 # The default is 30 seconds
  122. )
  123.  
  124. $connectionString = "Data Source=$DatabaseServer;Initial Catalog=$DatabaseName;Integrated Security=True;Enlist=False;Connect Timeout=5"
  125.  
  126. Write-Verbose "$(Get-Date): $($MyInvocation.MyCommand.Name) - Query: $Query"
  127.  
  128. try
  129. {
  130. $connection = New-Object System.Data.SqlClient.SqlConnection($connectionString)
  131. $connection.Open()
  132.  
  133. $command = New-Object system.Data.SqlClient.SqlCommand($Query, $connection)
  134. $command.CommandTimeout = $CommandTimeout
  135. $result = $command.ExecuteScalar()
  136.  
  137. return $result
  138. }
  139. catch
  140. {
  141. Write-Error -Message "Error executing query '$Query'. Exception: $_. Connection String: $connectionString"
  142. throw $_.Exception
  143. }
  144. finally
  145. {
  146. if($connection)
  147. {
  148. $connection.Close()
  149. $connection.Dispose()
  150. }
  151. }
  152. }
  153.  
  154. function Remove-Database
  155. {
  156. [CmdletBinding()]
  157. param
  158. (
  159. [Parameter(Mandatory=$true, ParameterSetName = "ConnectionString")]
  160. [string]$ConnectionString,
  161.  
  162. [Parameter(Mandatory=$true, ParameterSetName = "ConnectionComponents")]
  163. [string]$DatabaseName,
  164.  
  165. [Parameter(Mandatory=$true, ParameterSetName = "ConnectionComponents")]
  166. [string]$DatabaseServer
  167. )
  168.  
  169. begin
  170. {
  171. }
  172. process
  173. {
  174. if( $PSCmdlet.ParameterSetName -eq "ConnectionString" )
  175. {
  176. $builder = New-Object System.Data.SqlClient.SqlConnectionStringBuilder($ConnectionString)
  177. $DatabaseName = $builder.InitialCatalog
  178. $DatabaseServer = $builder.DataSource
  179. }
  180.  
  181. try
  182. {
  183. Invoke-NonQuery -DatabaseName "master" -DatabaseServer $DatabaseServer -Query "ALTER DATABASE [$DatabaseName] SET SINGLE_USER WITH ROLLBACK IMMEDIATE" -CommandTimeout 0
  184. }
  185. catch
  186. {
  187. Write-Error -Message "Error setting database $DatabaseName into SINGLE_USER mode. Exception: $_"
  188. throw $_.Exception
  189. }
  190.  
  191. try
  192. {
  193. Invoke-NonQuery -DatabaseName "master" -DatabaseServer $DatabaseServer -Query "DROP DATABASE [$DatabaseName]" -CommandTimeout 0
  194. }
  195. catch
  196. {
  197. Write-Error -Message "Error dropping database $DatabaseName. Exception: $_"
  198. throw $_.Exception
  199. }
  200. }
  201. end
  202. {
  203. }
  204. }
  205.  
  206. function Backup-Database
  207. {
  208. [CmdletBinding()]
  209. param
  210. (
  211. [Parameter(Mandatory=$true, ParameterSetName = "ConnectionString")]
  212. [string]$ConnectionString,
  213.  
  214. [Parameter(Mandatory=$true, ParameterSetName = "ConnectionComponents")]
  215. [string]$DatabaseName,
  216.  
  217. [Parameter(Mandatory=$true, ParameterSetName = "ConnectionComponents")]
  218. [string]$DatabaseServer,
  219.  
  220. [Parameter(Mandatory=$true, ParameterSetName = "ConnectionComponents")]
  221. [Parameter(Mandatory=$true, ParameterSetName = "ConnectionString")]
  222. [string]$FilePath
  223. )
  224.  
  225. begin
  226. {
  227. }
  228. process
  229. {
  230. if( $PSCmdlet.ParameterSetName -eq "ConnectionString" )
  231. {
  232. $builder = New-Object System.Data.SqlClient.SqlConnectionStringBuilder($ConnectionString)
  233. $DatabaseName = $builder.InitialCatalog
  234. $DatabaseServer = $builder.DataSource
  235. }
  236.  
  237. try
  238. {
  239. Invoke-NonQuery -DatabaseName $DatabaseName -DatabaseServer $DatabaseServer -Query "BACKUP DATABASE [$DatabaseName] TO DISK = N'$FilePath' WITH NOFORMAT, NOINIT, NAME = N'$DatabaseName-Full Database Backup', SKIP, NOREWIND, NOUNLOAD" -CommandTimeout 0
  240. }
  241. catch
  242. {
  243. Write-Error -Message "Error backing up database $DatabaseName to $FilePath. Exception: $_"
  244. throw $_.Exception
  245. }
  246. }
  247. end
  248. {
  249. }
  250. }
  251.  
  252. function Get-DatabaseAvailabilityGroupName
  253. {
  254. [CmdletBinding()]
  255. param
  256. (
  257. [parameter(Mandatory=$true)][string]$DatabaseServer,
  258. [parameter(Mandatory=$true)][string]$DatabaseName
  259. )
  260.  
  261. begin
  262. {
  263. }
  264. process
  265. {
  266. Get-DataTable -DatabaseName "master" -DatabaseServer $DatabaseServer -Query "SELECT name FROM sys.availability_databases_cluster c JOIN sys.availability_groups g ON g.group_id = c.group_id WHERE database_name = '$DatabaseName'" | SELECT -First 1 -ExpandProperty name
  267. }
  268. end
  269. {
  270. }
  271. }
  272.  
  273. function Test-DatabaseName
  274. {
  275. [cmdletbinding()]
  276. param
  277. (
  278. [Parameter(Mandatory=$true)][string]$DatabaseName,
  279. [Parameter(Mandatory=$true)][string]$DatabaseServer
  280. )
  281.  
  282. try
  283. {
  284. [Convert]::ToBoolean( (Invoke-ScalarQuery -DatabaseName "master" -DatabaseServer $DatabaseServer -Query "SELECT COUNT(*) FROM sys.databases (nolock) WHERE [Name] = '$DatabaseName'") )
  285. }
  286. catch
  287. {
  288. Write-Error -Message "Error testing database name '$DatabaseName'. Exception: $_"
  289. throw $_
  290. }
  291. }
  292.  
  293. function Get-DatabaseFileMoveSyntax
  294. {
  295. [cmdletbinding()]
  296. param
  297. (
  298. [Parameter(Mandatory=$true)][object[]]$FileNameInfo,
  299. [Parameter(Mandatory=$true)][string]$TargetLogFilePath,
  300. [Parameter(Mandatory=$true)][string]$TargetDataFilePath
  301. )
  302.  
  303. $sqlSyntax = ""
  304.  
  305. try
  306. {
  307. $FileNameInfo | % {
  308.  
  309. $physicalNameInfo = New-Object System.IO.FileInfo($_.PhysicalName)
  310. $logicalFileName = $_.LogicalName
  311. $filePath = ""
  312.  
  313. switch($_.Type)
  314. {
  315. "D" # data file
  316. {
  317. $filePath = [System.IO.Path]::Combine( $TargetDataFilePath, $physicalNameInfo.Name )
  318. }
  319. "L" # log file
  320. {
  321. $filePath = [System.IO.Path]::Combine( $TargetLogFilePath, $physicalNameInfo.Name )
  322. }
  323. }
  324.  
  325. $sqlSyntax += "MOVE N'$logicalFileName' TO N'$filePath', "
  326. }
  327.  
  328. return $sqlSyntax
  329. }
  330. catch
  331. {
  332. Write-Error -Message "Error generating move database file syntax. Exception: $_"
  333. throw $_.Exception
  334. }
  335. }
  336.  
  337. function Get-DatabaseBackupFileInfo
  338. {
  339. [cmdletbinding()]
  340. param
  341. (
  342. [Parameter(Mandatory=$true)][string]$DatabaseServer,
  343. [Parameter(Mandatory=$true)][string]$BackupFilePath
  344. )
  345.  
  346. try
  347. {
  348. Get-DataTable -DatabaseServer $DatabaseServer -DatabaseName "master" -Query "RESTORE FILELISTONLY FROM DISK = N'$BackupFilePath' WITH NOUNLOAD" | SELECT LogicalName, PhysicalName, Type
  349. }
  350. catch
  351. {
  352. Write-Error -Message "Error reading database backup file info. Exception: $_"
  353. throw $_.Exception
  354. }
  355. }
  356.  
  357. function Restore-Database
  358. {
  359. [cmdletbinding()]
  360. param
  361. (
  362. [Parameter(Mandatory=$true)][string]$DatabaseName,
  363. [Parameter(Mandatory=$true)][string]$DatabaseServer,
  364. [Parameter(Mandatory=$true)][string]$BackupFilePath,
  365. [Parameter(Mandatory=$false)][string]$DataFilePath,
  366. [Parameter(Mandatory=$false)][string]$LogFilePath
  367. )
  368.  
  369. try
  370. {
  371. # if the database exists, we can't restore it
  372. if( Test-DatabaseName -DatabaseName $databaseName -DatabaseServer $DatabaseServer )
  373. {
  374. throw "A database with the name '$databaseName' already exists on server $DatabaseServer"
  375. }
  376.  
  377. if( -not $DataFilePath )
  378. {
  379. Write-Verbose "$(Get-Date): $($MyInvocation.MyCommand.Name) - Getting data file path"
  380.  
  381. # get the default log file path
  382. $DataFilePath = Invoke-ScalarQuery -DatabaseName "master" -DatabaseServer $DatabaseServer -Query "SELECT SERVERPROPERTY('INSTANCEDEFAULTDATAPATH')" -Verbose
  383. }
  384.  
  385. if( -not $LogFilePath )
  386. {
  387. Write-Verbose "$(Get-Date): $($MyInvocation.MyCommand.Name) - Getting log file path"
  388.  
  389. # get the default data file path
  390. $LogFilePath = Invoke-ScalarQuery -DatabaseName "master" -DatabaseServer $DatabaseServer -Query "SELECT SERVERPROPERTY('INSTANCEDEFAULTLOGPATH')" -Verbose
  391. }
  392.  
  393. Write-Verbose "$(Get-Date): $($MyInvocation.MyCommand.Name) - Data file path: $DataFilePath"
  394. Write-Verbose "$(Get-Date): $($MyInvocation.MyCommand.Name) - Log file path: $LogFilePath"
  395.  
  396. # pull the logical and physical file names from the backup file
  397. $fileNameInfo = Get-DatabaseBackupFileInfo -DatabaseServer $DatabaseServer -BackupFilePath $BackupFilePath
  398.  
  399. # get the sql syntax required to point the data and log files to the appropriate locations
  400. $fileMoveSyntax = Get-DatabaseFileMoveSyntax -FileNameInfo $fileNameInfo -TargetLogFilePath $LogFilePath -TargetDataFilePath $DataFilePath
  401.  
  402. Invoke-NonQuery -DatabaseName "master" -DatabaseServer $DatabaseServer -Query "RESTORE DATABASE [$databaseName] FROM DISK = N'$BackupFilePath' WITH RECOVERY, $fileMoveSyntax NOUNLOAD" -CommandTimeout 0
  403. }
  404. catch
  405. {
  406. Write-Error -Message "Error restoring database $($DatabaseName) from $BackupFilePath. Exception: $_"
  407. throw $_
  408. }
  409. }
  410.  
  411. function Move-SPContentDatabase
  412. {
  413. [cmdletbinding()]
  414. param
  415. (
  416. [Parameter(Mandatory=$true)][string]$DatabaseName,
  417. [Parameter(Mandatory=$true)][string]$TargetServer,
  418. [Parameter(Mandatory=$true)][string]$BackupPath,
  419. [Parameter(Mandatory=$false)][string]$TargetAGName,
  420. [Parameter(Mandatory=$false)][switch]$RemoveSourceDatabase,
  421. [Parameter(Mandatory=$false)][string]$DataFilePath,
  422. [Parameter(Mandatory=$false)][string]$LogFilePath
  423.  
  424. )
  425.  
  426. begin
  427. {
  428. # bind to the source database
  429. $sourceDatabase = Get-SPContentDatabase -Identity $DatabaseName -ErrorAction SilentlyContinue
  430. }
  431. process
  432. {
  433. if( $sourceDatabase )
  434. {
  435. # grab the settings from the source database before doing anything
  436.  
  437. $webApplication = $sourceDatabase.WebApplication
  438. $maxSiteCount = $sourceDatabase.MaximumSiteCount
  439. $minSiteCount = $sourceDatabase.WarningSiteCount
  440. $connectionStr = $sourceDatabase.DatabaseConnectionString
  441. $databaseServer = $sourceDatabase.Server
  442.  
  443.  
  444. # REMOVE FROM CURRENT AVAILABILITY GROUP
  445.  
  446. try
  447. {
  448. $databaseAvailabilityGroupName = Get-DatabaseAvailabilityGroupName -DatabaseServer $databaseServer -DatabaseName $DatabaseName
  449.  
  450. if( $databaseAvailabilityGroupName )
  451. {
  452. $err = $null
  453.  
  454. Write-Verbose "$(Get-Date): $($MyInvocation.MyCommand.Name) - Removing database from Availability Group"
  455.  
  456. Remove-DatabaseFromAvailabilityGroup -AGName $databaseAvailabilityGroupName -DatabaseName $DatabaseName -Force -ErrorVariable err
  457.  
  458. if( $err )
  459. {
  460. throw $err
  461. }
  462. Write-Verbose "$(Get-Date): $($MyInvocation.MyCommand.Name) - Database removed from Availability Group"
  463. }
  464. }
  465. catch
  466. {
  467. Write-Error -Message "Error removing database $($DatabaseName) from Availalbity Group. Exception: $_"
  468. return
  469. }
  470.  
  471.  
  472. # DETACH SOURCE DATABASE FROM SHAREPOINT
  473.  
  474. try
  475. {
  476. $sourceDatabase | Dismount-SPContentDatabase -Confirm:$false
  477. }
  478. catch
  479. {
  480. Write-Error -Message "Error removing database $($DatabaseName) from SharePoint. Exception: $_"
  481. return
  482. }
  483.  
  484.  
  485. # BACKUP SOURCE DATABASE
  486.  
  487. try
  488. {
  489. $databaseBackupFilePath = Join-Path -Path $BackupPath -ChildPath "$($DatabaseName)_$(Get-Date -Format 'yyyyMMdd-hhmmss').bak"
  490.  
  491. Write-Verbose "$(Get-Date): $($MyInvocation.MyCommand.Name) - Backing up database to $databaseBackupFilePath"
  492. Backup-Database -DatabaseName $DatabaseName -DatabaseServer $databaseServer -FilePath $databaseBackupFilePath
  493. }
  494. catch
  495. {
  496. Write-Error -Message "Error backing up database $($DatabaseName) to $databaseBackupFilePath. Exception: $_"
  497. return
  498. }
  499.  
  500.  
  501. # DROP SOURCE DATABASE
  502.  
  503. if( $RemoveSourceDatabase )
  504. {
  505. try
  506. {
  507. # drop content database from SQL
  508. Remove-Database -DatabaseName $DatabaseName -DatabaseServer $databaseServer
  509. }
  510. catch
  511. {
  512. return
  513. }
  514. }
  515.  
  516.  
  517.  
  518. # RESTORE SOURCE DATABASE TO TARGET SQL INSTANCE
  519.  
  520. try
  521. {
  522. if( Test-Path -Path $databaseBackupFilePath -PathType Leaf )
  523. {
  524. Write-Verbose "$(Get-Date): $($MyInvocation.MyCommand.Name) - Restoring database to $TargetServer"
  525. Restore-Database -DatabaseName $DatabaseName -DatabaseServer $TargetServer -BackupFilePath $databaseBackupFilePath -DataFilePath $DataFilePath -LogFilePath $LogFilePath
  526. }
  527. else
  528. {
  529. Write-Error -Message "Backup file not found: $databaseBackupFilePath"
  530. return
  531. }
  532. }
  533. catch
  534. {
  535. Write-Error -Message "Error restoring database $DatabaseName to $TargetServer. Error: $_"
  536. return
  537. }
  538.  
  539.  
  540. # ATTACH DATABASE TO SHAREPOINT
  541.  
  542. try
  543. {
  544. $targetContentDatabase = Mount-SPContentDatabase -WebApplication $webApplication -Name $DatabaseName -DatabaseServer $TargetServer -MaxSiteCount $maxSiteCount -WarningSiteCount $minSiteCount -SkipIntegrityChecks
  545. }
  546. catch
  547. {
  548. Write-Error -Message "Error mounting database $DatabaseName to SharePoint. Error: $_"
  549. return
  550. }
  551.  
  552.  
  553. # ADD DATABASE TO NEW AG
  554.  
  555. try
  556. {
  557. if( $targetContentDatabase -and $TargetAGName )
  558. {
  559. Add-DatabaseToAvailabilityGroup -AGName $TargetAGName -DatabaseName $DatabaseName -FileShare $BackupPath
  560. }
  561. }
  562. catch
  563. {
  564. Write-Error -Message "Error adding database to Availability Group. Error: $_"
  565. return
  566. }
  567. }
  568. else
  569. {
  570. Write-Error "Database not found: $DatabaseName"
  571. }
  572. }
  573. end
  574. {
  575. }
  576. }
  577.  
  578. # it's required that the source and target SQL service accounts have write and read perms, respectively, to the backup share path
  579. Move-SPContentDatabase -DatabaseName "SCRIPT_TEST_003" -TargetServer "SQL-0" -BackupPath "\\sps-web-0\Backups" -TargetAGName "sp2013agau-ag" -RemoveSourceDatabase -Verbose
Add Comment
Please, Sign In to add comment