Skip to content

Commit

Permalink
Big update of input parameter handling.
Browse files Browse the repository at this point in the history
  • Loading branch information
weiher committed Jul 27, 2017
1 parent 91d79e4 commit 666cbd9
Show file tree
Hide file tree
Showing 10 changed files with 532 additions and 196 deletions.
16 changes: 15 additions & 1 deletion Email.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText


def sendEmail (address, alarmDate, alarmLocation, alarmMessage, alarmSource):

msg = MIMEMultipart()
Expand All @@ -19,4 +20,17 @@ def sendEmail (address, alarmDate, alarmLocation, alarmMessage, alarmSource):

s = smtplib.SMTP('mail.fhi-berlin.mpg.de')
s.sendmail(address, address, msg.as_string())
s.quit()
s.quit()


def getMailAddress(currentHour, mailAddresses, timePeriods):

periods = timePeriods.split(',')

for n, period in enumerate(periods):
times = period.split('-')
if int(times[0]) <= currentHour < int(times[1]):
break

addresses = mailAddresses.replace(' ','').split(',')
return addresses[n]
17 changes: 17 additions & 0 deletions Environment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

def readSettings(file):

f = open(file, 'r')
settings = {}

for line in f:
if line.startswith('WC_'):
parts = line.replace(' ', '').replace('\n','').replace("'", "").split('=')
key = parts[0]
value = parts[1]
settings[key] = value

f.close()
return settings
4 changes: 4 additions & 0 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,7 @@ To be able to import the wc_* tools append to the PYTHONPATH the webctrl directo
2) Set the python path inside the python script before the import statement:
sys.path.append('/path/to/webctrl')


Alle Argumente können via Kommandozeile UND via Env. Var. angegeben werden. Es werden KEINE Defaults gesetzt.
Die URL ist nur über die Env. Var. setzbar.
Das Passwort ist nur via Kommandozeile setzbar.
16 changes: 16 additions & 0 deletions SETTINGS
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
WC_USERNAME = 'wsdl'
#WC_NODE = '/trees/geographic'
WC_NODE = '/trees/geographic/#geb_e/#kaltw_erzeuger_fel/#km_speicher_fel'
WC_URL = 'https://webctrl.rz-berlin.mpg.de'
# wc_checkAlarms
WC_ALARMS_ALERT_EMAIL = 'weiher@fhi-berlin.mpg.de,weiher@fhi-berlin.mpg.de,weiher@fhi-berlin.mpg.de'
WC_ALARMS_ALERT_PERIODS = '8-16,16-22,22-8'
WC_ALARMS_INTERVAL = 1
WC_ALARMS_TAKEACTION = 1
# wc_getReport
WC_REPORT_TYPE = '~point-list-report'
# wc_getTrend
WC_TREND_STIME = ''
WC_TREND_ETIME = ''
WC_TREND_LIMIT = ''
WC_TREND_MAXREC = ''
160 changes: 106 additions & 54 deletions wc_checkAlarms.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,76 +8,126 @@
from alarm import alarm
from time import sleep
import datetime
from Email import sendEmail
from Email import sendEmail,getMailAddress
from Environment import readSettings


def main(args):
# Check all arguments

####################################################################################################################
### Check all arguments
####################################################################################################################

errorMessage = "No path to SETTINGS file specified. Provide one via '-f my_settingsFile' or {..., 'settingsFile':'my_settingsFile', ...}"
try:
if args['username'] is None:
print 'No username specified. Login to WebCTRL needs a username and a password. Check all options for this command via -h'
if args['settingsFile'] is None or not args['settingsFile']:
print(errorMessage)
sys.exit(1)
else:
username = args['username']
settingsFile = args['settingsFile']
except KeyError:
print(errorMessage)
sys.exit(1)
settings = readSettings(settingsFile)

errorMessage = "No username specified. Provide one via '-u my_username' or {..., 'username':'my_username', ...} or WC_USERNAME=my_username"
try:
if args['username'] is None or not args['username']:
if not settings['WC_USERNAME']:
print(errorMessage)
sys.exit(1)
else:
username = settings['WC_USERNAME']
else:
username = str(args['username'])
except KeyError:
print 'No "username" key specified. Please provide the key-value pair: \'username\':\'myUsername\''
print(errorMessage)
sys.exit(1)

# The password cannot be given via environment variable
errorMessage = "No password specified. Provide one via '-p my_password' or {..., 'password':'my_password', ...}"
try:
if args['password'] is None:
print 'No password specified. Login to WebCTRL needs a username and a password. Check all options for this command via -h'
if args['password'] is None or not args['password']:
print(errorMessage)
sys.exit(1)
else:
password = args['password']
except KeyError:
print 'No "password" key specified. Please provide the key-value pair: \'password\':\'myPassword\''
print(errorMessage)
sys.exit(1)

errorMessage = "No node specified. Provide one via '-n my_node' or {..., 'node':'my_node', ...} or WC_NODE=my_node"
try:
if args['node'] is None:
print 'No path to a node specified. Check all options for this command via -h'
sys.exit(1)
if args['node'] is None or not args['node']:
if not settings['WC_NODE']:
print(errorMessage)
sys.exit(1)
else:
node = settings['WC_NODE']
else:
node = str(args['node'])
except KeyError:
print 'No "node" key specified. Please provide the key-value pair: \'node\':\'/my/node\''
print(errorMessage)
sys.exit(1)

errorMessage = "No URL specified. Provide one via WC_URL=my_url"
url = settings['WC_URL']
try:
if args['url'] is None:
print 'No URL given. Specify the URL to the WebCTRL server analogous to http://google.de'
if not url:
print(errorMessage)
sys.exit(1)
else:
wsdlFile = args['url'] + '/_common/webservices/Report?wsdl'
wsdlFile = url + '/_common/webservices/Report?wsdl'
except KeyError:
print 'No "url" key specified. Please provide the key-value pair: \'url\':\'http://myURL.de\''
print(errorMessage)
sys.exit(1)

errorMessage = "No interval specified. Provide one via '-i my_interval' or {..., 'interval':'my_interval', ...} or WC_ALARMS_INTERVAL=my_interval"
try:
if args['interval'] is None:
print 'No interval (in minutes) for checking for new alarms specified. Using a default.'
checkForNewAlarmsInterval = 1
if args['interval'] is None or not args['interval']:
if float(settings['WC_ALARMS_INTERVAL']) is None:
print(errorMessage)
sys.exit(1)
else:
interval = float(settings['WC_ALARMS_INTERVAL'])
else:
checkForNewAlarmsInterval = args['interval']
interval = args['interval']
except KeyError:
print 'No "interval" key specified. Please provide the key-value pair: \'interval\':\'time in minutes\''
print(errorMessage)
sys.exit(1)
if interval <= 0.0:
print 'The interval must be bigger than 0.0.'
sys.exit(1)
checkForNewAlarmsInterval = interval

errorMessage = "No time to take action specified. Provide one via '-a my_takeAction' or {..., 'takeAction':'my_takeAction', ...} or WC_ALARMS_TAKEACTION=my_takeAction"
try:
if args['takeAction'] is None:
print 'No time (in minutes) specified after which an action is taken in case an alarm is not acknowledged. Using a default.'
takeActionTime = 5
if args['takeAction'] is None or not args['takeAction']:
if float(settings['WC_ALARMS_TAKEACTION']) is None:
print(errorMessage)
sys.exit(1)
else:
takeAction = float(settings['WC_ALARMS_TAKEACTION'])
else:
takeActionTime = args['takeAction']
takeAction = args['takeAction']
except KeyError:
print 'No "takeAction" key specified. Please provide the key-value pair: \'takeAction\':\'time in minutes\''
print(errorMessage)
sys.exit(1)
if takeAction <= 0.0:
print 'The time to take action must be bigger than 0.0.'
sys.exit(1)
takeActionTime = takeAction

if takeActionTime < checkForNewAlarmsInterval:
print 'The time after which action is taken for not acknowledged alarms is smaller than the interval for checking' + \
'for new alarms: ' + str(takeActionTime) + ' < ' + str(checkForNewAlarmsInterval)
print 'The take action time should be bigger or equal to the checking for new alarms time. Exiting now...'
sys.exit(1)

####################################################################################################################
### Connect to the webCTRL server
####################################################################################################################

# Connect to the webCTRL server
try:
client = suds.client.Client(wsdlFile, username=username, password=password)
except AttributeError:
Expand All @@ -87,12 +137,15 @@ def main(args):
sys.exit(1)
except:
print("Unexpected error:", sys.exc_info()[0])
print('Perhaps your URL to the WSDL file is not correct.')
print('Perhaps your URL to the WSDL file, ' + wsdlFile + ', is not correct.')
sys.exit(1)

####################################################################################################################
### Get the alarms and process them for as long as this script runs
####################################################################################################################

alarmsActive = [] # running alarms waiting to be checked/acknowledged and, eventually, switched off
alarmsChecked = [] # alarms that are already acknowloedged or switched off
alarmsActive = [] # active alarms waiting to be checked/acknowledged and, eventually, switched off
alarmsChecked = [] # alarms that are already acknowledged or switched off

# As long as this script runs get a report about all current alarms and their status every X seconds. The alarms are
# managed in objects that will be deleted once the status of an alarm has switched to "Normal". It will be checked
Expand All @@ -101,17 +154,15 @@ def main(args):
while True:
# Get a report about all current alarms in the network or in parts of the network (depending on the node setting)
try:
report = client.service.runReport(args['node'], '~alarms', 'csv')
report = client.service.runReport(node, '~alarms', 'csv')
except suds.WebFault as fault:
print fault
sys.exit(1)

#print report

#lines = report.split("\n")
#lines = lines[1:]
file = open("testAlarms.txt", "r")
lines = file.read().split("\n")
lines = report.split("\n")
lines = lines[1:]
#file = open("testAlarms.txt", "r")
#lines = file.read().split("\n")

# Go through the report and create alarm objects distinguishing by their current alarm status.
# Start looping from the last line in order to process the oldest alarms first.
Expand Down Expand Up @@ -170,11 +221,6 @@ def main(args):
# Ignore the alarms that have a 'Normal' status without another matching alarm with 'Unnormal'
# status because it's already solved
pass
## This should actually not happen: to have an alarm with status 'Normal' but to not find an
## appropriate alarm with status 'Unnormal'
##age = 0
##alarmsChecked.append(alarm(date, age, standort, message, quelle, bestaetigtVon, kategorie, status))
##print "This shouldn't have happened..."
else:
# Before appending the current alarm to the list of alarms check if this alarm is already contained
# in the list:
Expand All @@ -187,7 +233,7 @@ def main(args):
a.age += checkForNewAlarmsInterval
if not alarmAlreadyKnown:
print('Appending alarm ' + str(date) + ' ' + quelle + ' to alarmsActive')
age = 0
age = 0.0
alarmsActive.append(alarm(date, age, standort, message, quelle, bestaetigtVon, kategorie, status))

if alarmsChecked:
Expand All @@ -199,32 +245,38 @@ def main(args):
if alarmsActive:
for a in alarmsActive:
print(a.date, a.standort, a.message, a.quelle, a.bestaetigtVon, a.kategorie, a.status)
# Check the age of the still running alarms and take action in case of, for example, the age is greater than e.g. 20 min
# Check the age of the still active alarms and take action in case of, for example, the age is greater than e.g. 20 min
print 'Age: ' + str(a.age)
if a.age >= takeActionTime:
mailAddress = 'weiher@fhi-berlin.mpg.de'
currentHour = datetime.datetime.now().hour
mailAddress = getMailAddress(currentHour, settings['WC_ALARMS_ALERT_EMAIL'], settings['WC_ALARMS_ALERT_PERIODS'])
print 'Sending an e-mail to ' + mailAddress
sendEmail(mailAddress, a.date, a.standort, a.message, a.quelle)
else:
print('No alarms in list alarmsActive')

# sleep for n minutes
sleep(checkForNewAlarmsInterval*60)


if __name__=='__main__':
# The argument parser is only called if this script is called as a script/executable (via command line) but not when
# imported by another script
if __name__ == '__main__':
if len(sys.argv) < 2:
print "You haven't specified any arguments. Use -h to get more details on how to use this command."
sys.exit(1)

parser = argparse.ArgumentParser()
parser.add_argument('--username', '-u', type=str, default=None, help='Username for the login to the WebCTRL server')
parser.add_argument('--password', '-p', type=str, default=None, help='Password for the login to the WebCTRL server')
parser.add_argument('--node', '-n', type=str, default='trees/geographic',
parser._action_groups.pop()
required = parser.add_argument_group('required arguments')
optional = parser.add_argument_group('optional arguments (can also be specified via SETTINGS file)')
required.add_argument('--password', '-p', type=str, default=None, help='Password for the login to the WebCTRL server')
required.add_argument('--settingsFile', '-f', type=str, default=None, help='File name of settings containing WC_* variables')
optional.add_argument('--username', '-u', type=str, default=None, help='Username for the login to the WebCTRL server')
optional.add_argument('--node', '-n', type=str, default=None,
help='Path to the point or node whose children you want to retrieve. Start querying at the lowest level with "-n /trees/geographic"')
parser.add_argument('-url', type=str, default='https://webctrl.rz-berlin.mpg.de',
help="URL of the WebCTRL server as e.g. http://google.de")
parser.add_argument('-interval', '-i', type=int, default=1, help="Interval in MINUTES in which the script checks for new alarms")
parser.add_argument('-takeAction', '-a', type=int, default=1, help="Time in MINUTES after which an action is taken if an alarm still hasn't been acknowledged")
optional.add_argument('-interval', '-i', type=int, default=None, help="Interval in MINUTES in which the script checks for new alarms")
optional.add_argument('-takeAction', '-a', type=int, default=None, help="Time in MINUTES after which an action is taken if an alarm still hasn't been acknowledged")
args = parser.parse_args()

# Get the password if it hasn't been passed as argument
Expand Down
Loading

0 comments on commit 666cbd9

Please sign in to comment.