murano-deployment/WindowsPowerShell/Functions/Failover-Cluster.ps1

220 lines
6.0 KiB
PowerShell

<#
.DESCRIPTION
## Failover Cluster Input Data (from the UI)
* Domain Membership
- [String] / [Select box] $DomainName - Domain name
* Domain User Credentials
- [String] $UserName - Username
- [Password string] $UserPassword - User password
* Shared Folder Information
- [String] $ShareServer - Server which will host the folder
- [String] $ShareName - Share name
- [String] $SharePath - Shared folder internal path
* Failover Cluster Members
- [String] $ClusterName - Cluster name
- [String] $ClusterIP - Static IP address that will be assigned to the cluster
- [String[]] $ClusterNodes - List of node names
## Failover Cluster creation workflow
* Create AD domain
* Join all the VMs to that domain
* Prepare nodes
- Install Failover Cluster prerequisites on all FC nodes
* Create failover cluster
- Create new cluster
- Add members
* Confugure FC quorum
- Create new folder that will be shared
- Share that folder with appropriate permissions
- Configure quorum mode
## Helpful SmbShare* Functions
* New-SmbShare
* Grant-SmbShareAccess
#>
function Install-FailoverClusterPrerequisites {
Import-Module FailoverClusters
Add-WindowsFeature Failover-Clustering, RSAT-Clustering-PowerShell
}
function New-FailoverClusterSharedFolder {
param (
[String] $ClusterName,
[String] $DomainName,
[String] $ShareServer,
[String] $SharePath = $($Env:SystemDrive + '\FCShare'),
[String] $ShareName = 'FCShare',
[String] $UserName,
[String] $UserPassword,
$Credential = $null
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
Write-Log "--> New-FailoverClusterSharedFolder"
Write-Log "Creating shared folder for Failover Cluster ..."
if ($Credential -eq $null) {
$Credential = New-Credential -UserName "$DomainName\$UserName" -Password "$UserPassword"
}
if ((Test-Connection -ComputerName $ShareServer -Count 1 -Quiet) -eq $false) {
throw("Server '$ShareServer' is unreachable via ICMP.")
}
$Session = New-PSSession -ComputerName $ShareServer -Credential $Credential
Write-Log "Creating folder on '$ShareServer' ..."
Invoke-Command -Session $Session -ScriptBlock {
param (
[String] $SharePath,
[String] $ShareName,
[String] $ClusterAccount
)
Remove-SmbShare -Name $ShareName -Force -ErrorAction 'SilentlyContinue'
Remove-Item -Path $SharePath -Force -ErrorAction 'SilentlyContinue'
New-Item -Path $SharePath -ItemType Container -Force
New-SmbShare -Path $SharePath `
-Name $ShareName `
-FullAccess "$ClusterAccount" `
-Description "Shared folder for Failover Cluster."
} -ArgumentList $SharePath, $ShareName, "$DomainName\$ClusterName`$"
Write-Log "Confguring Failover Cluster to use shared folder as qourum resourse ..."
$null = Set-ClusterQuorum -NodeAndFileShareMajority "\\$ShareServer\$ShareName"
Write-Log "<-- New-FailoverClusterSharedFolder"
}
}
function New-FailoverCluster {
param (
[String] $ClusterName,
[String] $StaticAddress,
[String[]] $ClusterNodes,
[String] $DomainName,
[String] $UserName,
[String] $UserPassword,
$Credential
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
Write-Log "ClusterNodes: $($ClusterNodes -join ', ')"
if ($Credential -eq $null) {
$Credential = New-Credential -UserName "$DomainName\$UserName" -Password "$UserPassword"
}
Import-Module FailoverClusters
if ((Get-Cluster $ClusterName -ErrorAction SilentlyContinue) -eq $null) {
Write-Log "Creating new cluster '$ClusterName' ..."
Start-PowerShellProcess -Command @"
Import-Module FailoverClusters
New-Cluster -Name '$ClusterName' -StaticAddress '$StaticAddress'
"@ -Credential $Credential -NoBase64
Start-Sleep -Seconds 15
}
else {
Write-Log "Cluster '$ClusterName' already exists."
}
foreach ($Node in $ClusterNodes) {
Write-Log "Adding node '$Node' to the cluster '$ClusterName' ..."
if ((Get-ClusterNode $Node -ErrorAction SilentlyContinue) -eq $null) {
Write-Log "Adding node ..."
Start-PowerShellProcess -Command @"
Import-Module FailoverClusters
Add-ClusterNode -Cluster '$ClusterName' -Name '$Node'
"@ -Credential $Credential -NoBase64
}
else {
Write-Log "Node '$Node' already a part of the cluster '$ClusterName'."
}
}
}
}
<#
# Example
$DomainName = 'fc-acme.local'
$DomainUser = 'Administrator'
$DomainPassword = 'P@ssw0rd'
$ClusterName = 'fc-test'
$ClusterIP = '10.200.0.60'
$ClusterNodes = @('fc-node-01','fc-node-02','fc-node-03')
$ShareServer = 'fc-dc-01'
$ShareName = 'FCShare'
$SharePath = "C:\$ShareName"
Import-Module CoreFunctions -Force
$Creds = New-Credential `
-UserName "$DomainName\$DomainUser" `
-Password "$DomainPassword"
New-FailoverCluster `
-ClusterName $ClusterName `
-StaticAddress $ClusterIP `
-ClusterNodes $ClusterNodes `
-Credential $Creds
New-FailoverClusterSharedFolder `
-ClusterName $ClusterName `
-DomainName $DomainName `
-ShareServer $ShareServer `
-SharePath "$SharePath" `
-ShareName "$ShareName" `
-Credential $Creds
#>