SharedResources/Src/InstallHpcNode/xHpcPack/DSCResources/MSFT_xHpcNodeInstall/MSFT_xHpcNodeInstall.psm1 (207 lines of code) (raw):
#
# xHpcPackInstall: DSC resource to install HPC Pack.
#
function Get-TargetResource
{
[OutputType([System.Collections.Hashtable])]
param
(
[parameter(Mandatory = $true)]
[ValidateSet("ComputeNode", "BrokerNode", "HeadNodePreReq", "PassiveHeadNode")]
[string] $NodeType,
[parameter(Mandatory = $true)]
[string] $HeadNodeList,
[parameter(Mandatory = $true)]
[string] $SetupPkgPath,
[parameter(Mandatory = $true)]
[string] $SSLThumbprint
)
return $PSBoundParameters
}
function Set-TargetResource
{
param
(
[parameter(Mandatory = $true)]
[ValidateSet("ComputeNode", "BrokerNode", "HeadNodePreReq", "PassiveHeadNode")]
[string] $NodeType,
[parameter(Mandatory = $true)]
[string] $HeadNodeList,
[parameter(Mandatory = $true)]
[string] $SetupPkgPath,
[parameter(Mandatory = $true)]
[string] $SSLThumbprint
)
$downloader = New-Object System.Net.WebClient
# Download the setup package if it is an http/https url
if($SetupPkgPath -match "^https?://")
{
$setupPkgUrl = $SetupPkgPath
$SetupPkgPath = Join-Path "$env:windir\Temp" $($setupPkgUrl -split '/')[-1]
DownloadFile -Downloader $downloader -SourceUrl $setupPkgUrl -DestPath $SetupPkgPath
}
if((Test-Path -Path $SetupPkgPath -PathType Leaf) -and [IO.Path]::GetExtension($SetupPkgPath) -eq ".zip")
{
$basetgtdir = $SetupPkgPath.Substring(0, $SetupPkgPath.LastIndexOf('.')) + '_HPC'
$tgtdir = $basetgtdir
$index = 0
while(Test-Path -Path $tgtdir -PathType Container)
{
try
{
Remove-Item -Path $tgtdir -Recurse -Force -ErrorAction Stop
break
}
catch
{
$tgtdir = "$basetgtdir" + "_$index"
}
}
[System.Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') | Out-Null
[System.IO.Compression.ZipFile]::ExtractToDirectory($SetupPkgPath, $tgtdir) | Out-Null
}
else
{
$tgtdir = $SetupPkgPath
}
$pfxCert = Get-Item Cert:\LocalMachine\My\$SSLThumbprint -ErrorAction SilentlyContinue
if($pfxCert -eq $null)
{
throw "The certificate with thumbprint '$SSLThumbprint' doesn't exist under Cert:\LocalMachine\My"
}
if($pfxCert.Subject -eq $pfxCert.Issuer)
{
if(-not (Test-Path Cert:\LocalMachine\Root\$SSLThumbprint))
{
Write-Verbose "Installing certificate to Cert:\LocalMachine\Root"
$cerFileName = "$env:Temp\HpcPackComm.cer"
Export-Certificate -Cert "Cert:\LocalMachine\My\$SSLThumbprint" -FilePath $cerFileName | Out-Null
Import-Certificate -FilePath $cerFileName -CertStoreLocation Cert:\LocalMachine\Root | Out-Null
Remove-Item $cerFileName -Force -ErrorAction SilentlyContinue
}
}
$setupArg = "-unattend -Quiet -${NodeType}:`"$HeadNodeList`" -SSLThumbprint:$SSLThumbprint"
$retry = 0
while($true)
{
Write-Verbose "Installing HPC $NodeType"
$p = Start-Process -FilePath "$tgtdir\setup.exe" -ArgumentList $setupArg -PassThru -Wait
if($p.ExitCode -eq 0)
{
Write-Verbose "Succeed to Install HPC $NodeType"
break
}
if($p.ExitCode -eq 3010)
{
Write-Verbose "Succeed to Install HPC $NodeType, a reboot is required."
$global:DSCMachineStatus = 1
break
}
if($p.ExitCode -eq 13818)
{
throw "Failed to Install HPC $NodeType (errCode=$($p.ExitCode)): the certificate doesn't meet the requirements."
}
if($retry++ -lt 5)
{
Write-Warning "Failed to Install HPC $NodeType (errCode=$($p.ExitCode)), retry later..."
Clear-DnsClientCache
Start-Sleep -Seconds ($retry * 10)
}
else
{
throw "Failed to Install HPC $NodeType (ErrCode=$($p.ExitCode))"
}
}
}
function Test-TargetResource
{
param
(
[parameter(Mandatory = $true)]
[ValidateSet("ComputeNode", "BrokerNode", "HeadNodePreReq", "PassiveHeadNode")]
[string] $NodeType,
[parameter(Mandatory = $true)]
[string] $HeadNodeList,
[parameter(Mandatory = $true)]
[string] $SetupPkgPath,
[parameter(Mandatory = $true)]
[string] $SSLThumbprint
)
$serverGuid = "02985CCE-D7D5-40FF-9C81-6334523210F9"
if($null -eq (Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | ?{$_.UninstallString -and $_.UninstallString -match $serverGuid}))
{
return $false
}
$hpcRegKey = Get-Item HKLM:\SOFTWARE\Microsoft\HPC -ErrorAction SilentlyContinue
if($hpcRegKey)
{
if($NodeType -eq 'ComputeNode')
{
$desiredRole = 'CN'
}
elseif($NodeType -eq 'BrokerNode')
{
$desiredRole = 'BN'
}
elseif($NodeType -eq 'HeadNodePreReq')
{
$desiredRole = 'HN'
}
$roles = $hpcRegKey | Get-ItemProperty | Select -Property InstalledRole
if($roles -and ($roles.InstalledRole -contains $desiredRole))
{
return $true
}
}
return $false
}
function DownloadFile
{
param(
[parameter(Mandatory = $false)]
[System.Net.WebClient] $Downloader = $null,
[parameter(Mandatory = $true)]
[string] $SourceUrl,
[parameter(Mandatory = $true)]
[string] $DestPath
)
if($Downloader -eq $null)
{
$Downloader = New-Object System.Net.WebClient
}
$fileName = $($SourceUrl -split '/')[-1]
if(Test-Path -Path $DestPath -PathType Container)
{
$DestPath = [IO.Path]::Combine($DestPath, $fileName)
}
$downloadRetry = 0
while($true)
{
try
{
if(Test-Path -Path $DestPath)
{
Remove-Item -Path $DestPath -Force -Confirm:$false -ErrorAction SilentlyContinue
}
Write-Verbose "Downloading $SourceUrl to $DestPath(Retry=$downloadRetry)."
$Downloader.DownloadFile($SourceUrl, $DestPath)
Write-Verbose "Downloaded $SourceUrl to $DestPath."
break
}
catch
{
if($downloadRetry -lt 10)
{
Write-Verbose ("Failed to download files, retry after 20 seconds:" + $_)
Clear-DnsClientCache
Start-Sleep -Seconds 20
$downloadRetry++
}
else
{
throw "Failed to download files after 10 retries"
}
}
}
}
Export-ModuleMember -Function *-TargetResource