#
# PRTG Pause
#
# Simple HTTP Listener to accept HTTP-GET from
#
# Must run as Administrator to create a HTTP Web Listener
# http(s)://prtg_server_address/api/function?Username=uid&passhash=hash¶ms
#
# 20140611 Ver 1.0 Initiale public Version
# 20140612 Ver 1.1 Sonderfall trailing? und favicon.ico
# 20140612 Ver 1.2 Erweiterung um Template und Alert, Bugfix StatUsermittlung
# Added ScanNow, errors in Red, Hyperlink to DeviceID
# Errorausgabe im HTML addiert
# 20140718 Ver 1.3 Abschalten der DNS Abfragen,da diese bei "nichtauflösbarkeit" zu lange brauchen.
# Systeme müssen in PRTG über die IP-Adresse gepflegt werden
# Funktioniert nicht sicher, wenn mehrere Systeme die gleiche IP-Adresse haben (z.B. mehrere Kunden)
# Exclude von abruf des /favicon.ico addiert
# 20140718 Ver 1.4 Try to match Hostname based on ReverseDNS
# Additional Errorhandling if Lisatener Listener not bound
param (
[string]$prtgserveruri="https://prtg.netatwork.de", # URL of PRTG Web Frontend
[string]$prtgUsername="prtgpause", # Username
[string]$prtgpasshash="2039135208" , # hash instead of password
[string]$listenport = "81",
[string]$htmltemplatefile = "./prtgpause-template.htm",
[int]$devicecacheage = 10 # age of Device List Cache in seconds
)
set-psdebug -strict # make sure that e throw an error für uninitialize variables etc
[string]$script:lasterror=""
# Emulate function on PowerShell 2.0 Systems
function Invoke-WebRequest ([string]$uri) {
$webclient = new-object System.Net.WebClient
try {
$webclient.downloadstring($uri)
}
catch {
$script:lasterror = $_.Exception.Message
write-host ("ERROR" + $script:lasterror)
}
}
write-host "PRTGPause: Start"
write-host "PRTGPause: Check HTML-Template"
try {
[string]$htmltemplate=get-content $htmltemplatefile
}
catch {
write-error "Unable to load THML-Template: $htmltemplatefile "
exit
}
write-host "PRTGPause: Check HTML-Template - SUCCESS"
write-host "PRTGPause: Check PRTG Connectivity by reading Status"
try {
[xml]$data=Invoke-WebRequest -Uri ($prtgserveruri+"/api/getstatus.xml?id=0&Username="+$prtgUsername+"&passhash="+$prtgpasshash)
write-host ("PRTG-Version:"+ $data.status.Version)
write-host ("PRTG-Clock :"+ $data.status.Clock)
}
catch {
write-error "Unable to load sensortree. Check PRTG URL, Username and Hash"
exit
}
write-host "PRTGPause: Check PRTG Connectivity - SUCCESS"
write-host "PRTGPause: Start HTTP listener on Port: $listenport"
$listener = New-Object System.Net.HttpListener
$listener.Prefixes.Add('http://+:'+$listenport+'/') # Must GENAU mit der Angabe in NETSH übereinstimmen
$listener.Start()
write-host "PRTGPause: Start HTTP listener on Port: $listenport SUCCESS"
if ($error) {
write-host "Error on starting Listener"
exit
}
#$Host.UI.RawUI.FlushInputBuffer()
#[console]::TreatControlCAsInput = $true
#write-host "CTRL-C ist disabled"
[datetime]$devicelistage = get-date "01.01.2014" # initialze Age
[hashtable]$devicelist = @{}
[bool]$quit=$false
while ((!($quit))) {
[string]$script:lasterror=""
write-host ("Listening on " + $listener.Prefixes )
$context = $listener.GetContext() # Warte auf eingehende Anfragen
write-host "------- New Request arrived ------------"
$request = $context.Request
write-host (" URL.AbsoluteUri:" + $request.URL.AbsoluteUri)
write-host (" HttpMethod :" + $request.HttpMethod)
[string]$remoteip = $Request.RemoteEndPoint.Address.IPAddressToString
write-host (" RemoteIP :" + $remoteip)
write-host (" Method :" + $Request.HttpMethod)
write-host (" RAWURL :" + $Request.RawURL)
#[System.Net.Dns]::GetHostByAddress($request.RemoteEndPoint.address).hostname
if ($Request.RawURL -eq ("/")) {
write-host "Statuspage Request found, Check für Cache Update"
write-host ("Last Cache Update:" + $devicelistage.tostring())
write-host ("Now " + (Get-date).tostring())
if (((get-date) - $devicelistage).totalseconds -ge $devicecacheage) {
write-host "---------- DeviceList to old. start Update --------------"
[hashtable]$devicelist.clear()
write-host " Loading Device XML"
[xml]$data= Invoke-WebRequest -Uri ($prtgserveruri+"/api/table.xml?content=devices&output=xml&columns=device,host,objid&Username="+$prtgUsername+"&passhash="+$prtgpasshash)
foreach ($device in ($data.devices.item)){
write-host ("found Device:"+$device.name+" Host:"+$device.host) -nonewline
if ($device.host -eq "127.0.0.1") {
write-host " Host is 127.0.0.1: SKIP"
}
elseif ($device.host -match "^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$") {
write-host (" Host is IP-Address. Adding IP:" + $device.host)
$devicelist.add($device.host,$device.objid)
# DNS Queries take too long if name not resolvable. so i had to disable that
# $hostname=[System.Net.Dns]::GetHostByAddress($device.host).hostname
}
else {
write-host " Host is a DNS-Name. Adding Host " $device.host
$devicelist.add($device.host,$device.objid)
# foreach ($dnsanswer in ([System.Net.Dns]::GetHostAddresses($device.host))){
# write-host (" Resolved to IP-Address:" + $dnsanswer.IPAddressToString)
# try {
# $devicelist.add(($dnsanswer.IPAddressToString),$device.objid)
# }
# catch {
# write-host (" Problem adding:" + $dnsanswer.IPAddressToString + " Maybe duplicate IP")
# }
# }
}
}
[datetime]$devicelistage = get-date # Update DeviceList Age
}
else {
write-host "Reusing existing device table"
}
}
#$devicelist
write-host "Loading HTMLTemplate"
[string]$htmltemplate = get-content $htmltemplatefile # enable that to load template für every request
[string]$htmlpage = $htmltemplate # use the templated loaded during startup
$htmlpage = $htmlpage.replace("%IPADDRESS%",$remoteip)
$htmlpage = $htmlpage.replace("%TIMESTAMP%",(get-date))
$deviceobjid=""
write-host ("Searching für device in List: " + $remoteip) -nonewline
if ($devicelist.containskey($remoteip)){
write-host " Found by IP" -nonewline
$deviceobjid = $devicelist.item($remoteip)
}
else {
try {
$devicename = ""
$devicename = [System.Net.Dns]::GetHostByAddress($remoteip).hostname
}
catch {
$script:lasterror = $_.Exception.Message
write-host ("ERROR Resolving Reverse DNS" + $script:lasterror)
}
if ($devicelist.containskey($devicename)){
write-host " Found by ReverseDNS" -nonewline
$deviceobjid = $devicelist.item($devicename)
}
}
if ($deviceobjid -ne ""){
write-host ".. Found System in Device List"
if ($Request.RawURL.startswith("/pause")) {
write-host "Pausing Device"
$result = Invoke-WebRequest -Uri ($prtgserveruri+"/api/pauseobjectfor.htm?id="+$deviceobjid+"&action=0&pausemsg=PausedbyPRTG-Pause&duration=15&Username="+$prtgUsername+"&passhash="+$prtgpasshash)
}
elseif ($Request.RawURL.startswith("/resume")) {
write-host "Pausing Device"
$result = Invoke-WebRequest -Uri ($prtgserveruri+"/api/pause.htm?id="+$deviceobjid+"&action=1&Username="+$prtgUsername+"&passhash="+$prtgpasshash)
}
elseif ($Request.RawURL.startswith("/ackalarm")) {
write-host "AckAlarm 15 Min"
$result = Invoke-WebRequest -Uri ($prtgserveruri+"/api/acknowledgealarm.htm?id="+$deviceobjid+"&ackmsg=AckAlarmByPRTGPause&duration=15&Username="+$prtgUsername+"&passhash="+$prtgpasshash)
}
elseif ($Request.RawURL.startswith("/scannow")) {
write-host "AckAlarm 15 Min"
$result = Invoke-WebRequest -Uri ($prtgserveruri+"/api/scannow.htm?id="+$deviceobjid+"&Username="+$prtgUsername+"&passhash="+$prtgpasshash)
}
elseif ($Request.RawURL.startswith("/quit")) {
write-host "Quit received"
$quit = $true
}
else {
write-host "No Special Command"
}
if ($true -or ($Request.RawURL -eq "/") -or ($Request.RawURL -eq "/?")) {
write-host "------- Generating Response Page ------------"
$htmlpage = $htmlpage.replace("%DEVICEID%",(""+$deviceobjid+""))
[xml]$status = Invoke-WebRequest -Uri ($prtgserveruri+"/api/getsensordetails.xml?columns=datetime,name,status,message&id="+$deviceobjid+"&Username="+$prtgUsername+"&passhash="+$prtgpasshash)
if ($status.sensordata.statusid.'#cdata-section' -eq "12") {
write-host " Found Status: 12"
$htmlpage = $htmlpage.replace("%STATUS%",($status.sensordata.statustext.'#cdata-section'))
$htmlpage = $htmlpage.replace("%BUTTON%","ResumeAckAlarm 15MinScanNow")
}
elseif ($status.sensordata.statusid.'#cdata-section' -eq "3") {
write-host " Found Status: Ok"
$htmlpage = $htmlpage.replace("%STATUS%","OK")
$htmlpage = $htmlpage.replace("%BUTTON%","Pause 15MinAckAlarm 15MinScanNow")
}
else {
write-host (" Found Status: unknown" + $status.sensordata.statustext.'#cdata-section')
$htmlpage = $htmlpage.replace("%STATUS%",("unknown:"+$status.sensordata.statustext.'#cdata-section' + "XX"))
$htmlpage = $htmlpage.replace("%BUTTON%","ScanNow")
}
[xml]$result = Invoke-WebRequest -Uri ($prtgserveruri+"/api/table.xml?content=sensors&columns=objid,group,device,sensor,status,message,lastvalue,priority,favorite&id="+$deviceobjid+"&count=10&Username="+$prtgUsername+"&passhash="+$prtgpasshash)
$htmlpage = $htmlpage.replace("%SENSORTABLE%",($result.sensors.item | select sensor,status,lastvalue | convertto-html -Fragment ))
[xml]$result = Invoke-WebRequest -Uri ($prtgserveruri+"/api/table.xml?content=messages&count=10&output=xml&columns=datetime,name,status,message&id="+$deviceobjid+"&count=10&Username="+$prtgUsername+"&passhash="+$prtgpasshash)
$htmlpage = $htmlpage.replace("%MESAGETABLE%",($result.messages.item | select datetime,name,status,message_raw | convertto-html -Fragment ))
}
}
else {
write-host " NOT System in Device List"
$htmlpage = $htmlpage.replace("%STATUS%","NOT IN DEVICE LIST")
$htmlpage = $htmlpage.replace("%BUTTON%","")
$htmlpage = $htmlpage.replace("%SENSORTABLE%","Device not found in List")
$htmlpage = $htmlpage.replace("%MESAGETABLE%","Device not found in List")
}
write-host "Sending HTML Response"
$response = $context.Response
$response.ContentType = 'text/html'
$response.ContentEncoding = [System.Text.Encoding]::UTF8;
$htmlpage = $htmlpage.replace("%LASTERROR%",$script:lasterror.tostring())
[byte[]] $buffer = [System.Text.Encoding]::UTF8.GetBytes($htmlpage)
$response.ContentLength64 = $buffer.length
$response.OutputStream.Write($buffer, 0, $buffer.length)
$response.OutputStream.close()
write-host "--- DONE ---"
}
$listener.Stop()
write-host "--- Normal End ---"