Last active
February 23, 2018 07:48
-
-
Save Siikakala/6f05242d6a285ccde419fb9fe753aebf to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Change production state of machine in Zenoss4 | |
.DESCRIPTION | |
This script takes array of machines and sets their production state to some other. Returns current | |
and previous states of machines as integer | |
.EXAMPLE | |
.\zenoss_productionstate.ps1 -Computers computer1.example.com -ProductionState Maintenance | |
Will set production state of computer1 to maintenance | |
.EXAMPLE | |
.\zenoss_productionstate.ps1 -Computers computer1.example.com,computer2.example.com,computer3.example.com -ProductionState Test | |
Will set production state of computer1, computer2 and computer3 to test | |
.PARAMETER Computers | |
Array of computers. Accepts pipeline input. Mandatory. | |
.PARAMETER ProductionState | |
State, to which computers will be set to. Possible values are Pre-Production, Production, Maintenance, Test and Decommissioned | |
.PARAMETER username | |
Username for using Zenoss | |
.PARAMETER password | |
Password for user | |
.PARAMETER zenossBaseUrl | |
FQDN of the zenoss without https://, eg. zenoss.example.com | |
.PARAMETER protocol | |
Which protocol should be used, https heavily recommended. | |
.NOTES | |
Version 1.0 | |
#> | |
#requires -version 4.0 | |
[CmdletBinding()] | |
param( | |
[parameter(Mandatory=$true,ValueFromPipeline=$true)] | |
[ValidateNotNullOrEmpty()] | |
[Array] | |
$Computers, | |
[parameter(Mandatory=$true)] | |
[ValidateSet("Maintenance","Pre-Production","Production","Test","Decommissioned")] | |
[String] | |
$ProductionState, | |
$username = "changeme", | |
$password = "changeme", | |
$zenossBaseUrl = "zenoss.example.com", | |
$protocol = "https" | |
) | |
try{ | |
# Initiate login to get session cookie | |
$login = Invoke-WebRequest -Uri "${protocol}://$zenossBaseUrl/zport/acl_users/cookieAuthHelper/login" -SessionVariable cookie | |
}catch [System.Net.WebException]{ | |
Write-Debug "Login form exception" | |
throw (New-Object -TypeName System.Net.WebException -ArgumentList "Zenoss threw error when requesting login form:`n$($error[0])") | |
} | |
$loginForm = $login.Forms[0] | |
$loginForm.Fields["__ac_name"]=$username | |
$loginForm.Fields["__ac_password"]=$password | |
try{ | |
# Do the actual logon | |
$logon = Invoke-WebRequest -Uri "${protocol}://$zenossBaseUrl/zport/acl_users/cookieAuthHelper/login" -WebSession $cookie -Method POST -Body $loginForm.Fields | |
}catch [System.Net.WebException]{ | |
Write-Debug "Logon exception" | |
throw (New-Object -TypeName System.Net.WebException -ArgumentList "Zenoss threw error when logging in:`n$($error[0])") | |
} | |
# Checking if there is login form in the page anymore. This is bit ":D" way to check if login was successful but powershell parses the data anyway so why not. | |
if($($logon.forms.GetEnumerator()|where{$_.id -eq "loginform"}) -eq $null){ | |
try{ | |
# You need to know the path of machine (eg. /Server/Windows) to be able to change production state. Only way to figure out what it is to query all the machines from zenoss | |
$allDevices = Invoke-RestMethod -uri "${protocol}://$zenossBaseUrl/zport/dmd/device_router" -WebSession $cookie -DisableKeepAlive -Method POST -ContentType "application/json" -Body $(ConvertTo-Json @{action="DeviceRouter";method="getDevices";data=@(@{uid='/zport/dmd/Devices';params=@{};limit=$null});type="rpc";tid=1} -depth 5) | |
}catch [System.Net.WebException]{ | |
Write-Debug "Querying all devices exception" | |
throw (New-Object -TypeName System.Net.WebException -ArgumentList "Zenoss threw error when querying all devices:`n$($error[0])") | |
} | |
# Query may fail.. Fortunately zenoss API will tell if it was successful or not | |
if($allDevices.result.success -eq $true){ | |
# As the querying of all devices is the most costful thing, now we can change production state for many machines at once. | |
foreach($computer in $Computers){ | |
# The computer name is value in hash table so we need to do reverse search. Powershell does this very efficiently | |
$com = $allDevices.result.devices.GetEnumerator()|where{$_.name -eq $computer} | |
# API returns full uri path to the machine as well in uid object, which is very helpful. Checking that if we actually found a machine. | |
if($com.uid -eq $null){ | |
Write-Debug "Machine not found exception" | |
throw (New-Object -TypeName System.ArgumentNullException -ArgumentList "uid empty in zenoss data, is computer in zenoss? computer $computer, zenoss data: $com") | |
} | |
# Production state is integer internally in zenoss so doing the mapping here | |
$state = switch ($ProductionState){ | |
"Decommissioned" { -1 } | |
"Maintenance" { 300 } | |
"Test" { 400 } | |
"Pre-Production" { 500 } | |
"Production" { 1000 } | |
default { 1000 } | |
} | |
try{ | |
# And finally actually changing the production state. | |
$proceed = Invoke-WebRequest -Uri "${protocol}://$zenossBaseUrl/zport/dmd/device_router" -WebSession $cookie -DisableKeepAlive -Method POST -ContentType "application/json" -Body $(ConvertTo-Json @{action="DeviceRouter";method="setInfo";data=@(@{uid=$($com.uid);productionState=$state});type="rpc";tid=5} -Depth 5) | |
Write-Verbose $proceed.Content | |
# Had problems with collector changing to localhost, so changed API call above and if it is still problem in the future, API call below will handle it. | |
#$proceed2 = Invoke-WebRequest -Uri "${protocol}://$zenossBaseUrl/zport/dmd/device_router" -WebSession $cookie -DisableKeepAlive -Method POST -ContentType "application/json" -Body $(ConvertTo-Json @{action="DeviceRouter";method="setCollector";data=@(@{asynchronous=$false;collector=$($com.collector);hashcheck=$null;moveData=$false;uids=@($($com.uid));});type="rpc";tid=10} -Depth 5) | |
#Write-Verbose $proceed2.Content | |
}catch [System.Net.WebException]{ | |
$errmessage = $Error[0].ErrorDetails.Message | |
$zenosserror = [regex]::match($errmessage,'(?si)View Error Details(.*)Traceback') | |
if($zenosserror -eq $null){ | |
$zenosserr = $error[0] | |
}else{ | |
$zenosserr = $zenosserror.value.Substring(18,$(($zenosserror.value.Length)-27)) | |
} | |
Write-Debug "Changing production state exception" | |
throw (New-Object -TypeName System.Net.WebException -ArgumentList "Zenoss threw error when changing production state:`n$($zenosserr)") | |
} | |
$oldstate = switch ($com.productionState){ | |
-1 { "Decommissioned" } | |
300 { "Maintenance" } | |
400 { "Test" } | |
500 { "Pre-Production" } | |
1000 { "Production" } | |
default { "Production" } | |
} | |
# Also returning the current and previous production states of the machine, this data can be used later, to change production state back to whatever it was. | |
[PSCustomObject]@{ | |
Computer = $computer | |
PreviousState = $oldstate | |
CurrentState = $ProductionState | |
} | |
} | |
}else{ | |
Write-Debug "Querying devices from zenoss was unsuccessful (but API call wasn't)" | |
throw (New-Object -TypeName System.Net.WebException -ArgumentList "Querying devices from zenoss was not successful") | |
} | |
}else{ | |
Write-Debug "Bad username or password? What zenoss is doing?!" | |
throw (New-Object -TypeName System.Security.Authentication.AuthenticationException -ArgumentList "Bad username or password") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment