Untitled
unknown
powershell
3 years ago
11 kB
6
Indexable
#Take input from XML file
[xml]$configInformation = (Get-Content -Path C:\Users\a0334614\Desktop\Maintenance\MaintenanceConfig.xml)
[string]$url = $configInformation.Settings.apiHostname
[string]$username = $configInformation.Settings.Username
[array]$tags = $configInformation.Settings.Tags.Tag
[string]$passwordFromFile = $configInformation.Settings.PasswordEncryptedString
$SecureStringPassword = $passwordFromFile | ConvertTo-SecureString
$Password = (New-Object PSCredential "user",$SecureStringPassword).GetNetworkCredential().Password
<#
.Synopsis
This function will send credentials to api and in exchange for an auth token
.Outputs
Response.token: A token that can be used to authenticate future requests
#>
function Get-AuthToken
{
Write-Verbose "Requesting auth token from api..."
#$password = Get-Content $passwordFileLocation
$payload = @{
client_id = 'clientID'
grant_type = 'password'
username = "$username"
password = "$password"
} | ConvertTo-Json
$response = Invoke-RestMethod -Uri ($Url + "/api/api/v1/auth") -Method POST -Body $payload -ContentType application/json
return $response.token
}
<#
.Synopsis
This function will get machines from api associated with a given tag
.Outputs
Machines: an array of machine objects
#>
function Get-Machine
{
param (
$Token,
$Tag,
$Url
)
$machines = Invoke-RestMethod -Method GET -Uri ($Url + "/api/api/v1/servers/?tag=$Tag") -ContentType application/json -Headers $Header
return $machines
}
<#
.Synopsis
This function will PATCH a given machine in api by adjusting its maintenance status
.Parameter
InOrOut a string representing the maintenance status to set the machine to
#>
function Update-MachineStatus
{
param (
$machine,
$header
)
$body = @{
attributes = @{
name = $machine.attributes.name
serverType = $machine.attributes.serverType
maintenanceMode = $machine.attributes.maintenanceMode
tags = $machine.attributes.tags
associatedApplications = $machine.attributes.associatedApplications
}
} | ConvertTo-Json -depth 4
$id = $machine.id
Invoke-RestMethod -Method PATCH -Uri ($url + "/api/api/v1/servers/$id") -ContentType application/json -Body $Body -Headers $header > $null
}
<#
.Synopsis
This function will call the other functions for input. Then it will take the appropriate machines out and poll them until they are drained.
Once they transition out of service, any maintenance actions can be performed without end user impact. After that completes, machines are
brought back into service and the next tag is taken down.
Status updates are given along the way for troubleshooting but user interaction is not required.
#>
function Main
{
foreach ($tag in $tags)
{
$AuthToken = Get-AuthToken
[array]$deadcomputerNames = @()
[array]$aliveMachines = @()
[array]$aliveMachineNames = @()
[array]$jobs = @()
$body = ""
$header = @{
'Content-Type' = 'application/json'
'Authorization' = "Bearer $AuthToken"
}
$machines = Get-Machine -token $AuthToken -tag $tag -Url $URL
#$machines
foreach ($machine in $machines.data)
{
$machineID = $machine.ID
$MachineName = $machine.attributes.Name
if (Test-Connection $machineName -Count 2 -Quiet)
{
$aliveMachines += $machine
$machine.attributes.maintenanceMode = "TransitioningOutofService"
#Update-MachineStatus -machine $machine -header $header > $null
$aliveMachineNames += $MachineName
}
else
{
Write-Host "fail"
$deadcomputerNames += $machine.attributes.name
}
}
$deadcomputerNames
$aliveMachines
foreach ($machine in $aliveMachines)
{
$machineID = $machine.ID
$j = Start-Job -Name $('OutofServicePoller' + $machine.attributes.name) -ScriptBlock {
param(
$header,
$machineID,
$url
)
$machineStatus = "default"
while ($machinestatus -ne "Out of service")
{
Write-Host $machinestatus
Start-Sleep -Seconds 10
$machineStatus = (Invoke-RestMethod -Method GET -Uri ($url + "/api/api/v1/servers/$machineid") -ContentType application/json -Headers $header).data.attributes.maintenanceMode
Write-Host $machinestatus
}
} -ArgumentList $header, $machineID, $url
$jobs += $j.id
}
Write-Host "Waiting for $tag servers to go out of service..."
Wait-Job -Id $jobs > $null
Write-Host "All $tag servers are out of service"
<#
Do some maintenance stuff
#>
<#$aliveMachineNames.ForEach({"$_" | Out-File "C:\EpicSource\UltimateMaintenance\Servers.txt" -Append})
$scriptPath = "C:\EpicSource\UltimateMaintenance\Deploy-Package.ps1"
$params = "-ServerListFile 'c:\epicSource\UltimateMaintenance\servers.txt' -InstallerPath 'C:\EpicSource\UltimateMaintenance\ECSMMSApplicationRequestRouting3.msi'"
Invoke-Expression -Command "$scriptPath $params"#>
#& "C:\EpicSource\UltimateMaintenance\Deploy-Package.ps1" -Servers $aliveMachines -InstallerPath "C:\EpicSource\UltimateMaintenance\ECSMMSApplicationRequestRouting3.msi"
Write-Host $aliveMachines.attributes.name
#Example 1: Reboot machines
Write-Host "Rebooting machines with tag $tag"
Get-Job -Name "*restart-computer*" | Remove-Job
#Invoke-CimMethod -ComputerName $aliveMachines.attributes.name -ClassName 'Win32_OperatingSystem' -MethodName 'Reboot'
$aliveMachines.attributes.name | Restart-Computer -AsJob -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Out-Null
(get-job | Where-Object {$_.Command -match "^Restart-Computer.*"}) | Wait-Job | Out-Null
Write-Host "Completed Rebooting machines with tag $tag"
<#>
Example 2: Rotate through installing a prerequisite that requires a reboot
$scriptPath = "C:\EpicSource\UltimateMaintenance\Deploy-Package.ps1"
$params = "-ServerListFile $aliveMachinesPath -InstallerPath 'C:\EpicSource\UltimateMaintenance\ECSMMSApplicationRequestRouting3.msi'"
Invoke-Expression -Command "$scriptPath $params"
#>
#Example 3: Install Windows Updates
#Source for Module https://www.powershellgallery.com/packages/PSWindowsUpdate/2.2.0.2
$AlexsPassword = Get-Content 'C:\Users\a0334614\Desktop\Powershell-maintenance\password.txt'
$AlexsUsername = "insel\a033461"
$User = $AlexsUsername
$PWord = ConvertTo-SecureString -String $AlexsPassword -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $PWord
foreach($machine in $aliveMachines)
{
$s = New-PSSession -ComputerName $machine -Credential $Credential
$i = Invoke-Command -Session $s -ScriptBlock{
if(!(Test-Path -Path "C:\Windows\System32\WindowsPowerShell\v1.0\Modules\PSWindowsUpdates"))
{
New-Item -ItemType Directory -Path "C:\Windows\System32\WindowsPowerShell\v1.0\Modules" -Name "PSWindowsUpdate" -ErrorAction SilentlyContinue
}
[bool]$doesPsd1Exist = Test-Path -Path "C:\Windows\System32\WindowsPowerShell\v1.0\Modules\PSWindowsUpdate\PSWindowsUpdate.psd1"
return $doesPsd1Exist
}
if(!$i)
{
Start-Sleep -Seconds 2
Copy-Item -ToSession $s -Path "C:\Users\bharriso\Downloads\pswindowsupdate.2.2.0.2.zip" -Destination "C:\Windows\System32\WindowsPowerShell\v1.0\Modules\PSWindowsUpdate"
Invoke-Command -Session $s -ScriptBlock{
Unblock-File -Path "C:\Windows\System32\WindowsPowerShell\v1.0\Modules\PSWindowsUpdate\pswindowsupdate.2.2.0.2.zip"
Expand-Archive -Path "C:\Windows\System32\WindowsPowerShell\v1.0\Modules\PSWindowsUpdate\pswindowsupdate.2.2.0.2.zip" -DestinationPath "C:\Windows\System32\WindowsPowerShell\v1.0\Modules\PSWindowsUpdate"
Remove-Item -Path "C:\Windows\System32\WindowsPowerShell\v1.0\Modules\PSWindowsUpdate\pswindowsupdate.2.2.0.2.zip"
Import-Module -Name PSWindowsUpdate
}
}
}
foreach($machine in $aliveMachines)
{
$machineName = $machine.attributes.name
#Invoke-WUJob -ComputerName $machineName -Script { ipmo PSWindowsUpdate; Install-WindowsUpdate -AcceptAll -AutoReboot | Out-File "C:\Windows\PSWindowsUpdate.log"} -RunNow -Confirm:$false -Verbose -ErrorAction Ignore
Download-WindowsUpdate -ForceDownload -ForceInstall
}
foreach ($machine in $aliveMachines)
{
$machineID = $machine.ID
$machine.attributes.maintenanceMode = "InService"
update-machinestatus -machine $machine -header $header > $null
}
#send email to admin with info on what just ran and what machines are "dead'"
if($aliveMachineNames.Count -ge 1)
{
$Body += ("The following machine(s) have had maintenance actions taken on them successfully: " + "<br />" + $aliveMachineNames + "<br />" + "<br />")
}
if($deadcomputerNames.Count -ge 1)
{
$Body += ("The following machine(s) were not able to be connected to: " + "<br />" + $deadcomputerNames + "<br />" + "<br />")
}
$body += "Have an Epic day"
# If we're sending email alerts import settings from EmailAlertsConfig.xml
$emailSettings = @{ }
if ($EmailAlerts)
{
[xml] $emailXML = (Get-Content -Path .\EmailAlertConfig.xml)
$emailSettings = @{
To = $emailXML.Settings.MailTo
From = $emailXML.Settings.MailFrom
Subject = "MaintenanceActions Taken"
SmtpServer = $emailXML.Settings.SmtpServer
Port = $emailXML.Settings.SmtpPort
}
}
function _sendEmailAlert
{
param (
[Parameter(Mandatory = $true)]
[string] $Body,
# Hashtable of parameters for the Send-MailMessage function
# Passed using @settings
[Parameter(Mandatory = $true)]
[hashtable] $Settings
)
if ($EmailAlerts.IsPresent)
{
Send-MailMessage @Settings -Body $Body -BodyAsHtml
}
}
#send email to admin with info on what just moved
_sendEmailAlert -Settings $emailSettings -Body $Body
}
}
Main
Editor is loading...