Skip to content

Commit

Permalink
Initial cut of updated monitoring script
Browse files Browse the repository at this point in the history
  • Loading branch information
sthapa committed Apr 1, 2015
1 parent 3ed8e40 commit 8bf20fc
Show file tree
Hide file tree
Showing 3 changed files with 322 additions and 112 deletions.
340 changes: 228 additions & 112 deletions check.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,128 +3,244 @@
import hashlib
import sys
import os
import time
import subprocess
import socket
import argparse
import json

import jinja2
import requests
import paramiko

ADMIN_MESG_LOCATION = "/tmp/admin_message"

def test_login(service, host, user ):
result = { 'service' : service,
'status' : "OK",
'message' : '' }
client = paramiko.client.SSHClient()
try:
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname=host, port=22, username=user)
except paramiko.AuthenticationException:
result['status'] = 'FAILED'
result['message'] = "Can't authenticate to %s" % host
except paramiko.SSHException:
result['status'] = 'FAILED'
result['message'] = "Can't establish ssh connection to %s" % host
except socket.error:
result['status'] = 'FAILED'
result['message'] = "Socket error connecting to %s" % host
return result

def test_login(service, host, user):
result = {'service': service,
'status': "green",
'notes': ''}
client = paramiko.client.SSHClient()
try:
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname=host, port=22, username=user)
except paramiko.AuthenticationException:
result['status'] = 'red'
result['notes'] = "Can't authenticate to %s" % host
except paramiko.SSHException:
result['status'] = 'red'
result['notes'] = "Can't establish ssh connection to %s" % host
except socket.error:
result['status'] = 'red'
result['notes'] = "Socket error connecting to %s" % host
return result


def test_download(service, url, sha1):
result = { 'service' : service,
'status' : "OK",
'message' : '' }
try:
r = requests.get(url, timeout=60)
if r.status_code != requests.codes.ok:
result['status'] = "FAILED"
result['message'] = "HTTP Status code: %s" % r.status_code
return result
if hashlib.sha1(r.text).hexdigest() != sha1:
result['status'] = "FAILED"
result['message'] = "File content doesn't match"
except requests.exceptions.Timeout:
result['status'] = "FAILED"
result['message'] = "Connection to server timed out"
except requests.exceptions.ConnectionError:
result['status'] = "FAILED"
result['message'] = "Connection error"
except requests.exceptions.HTTPError:
result['status'] = "FAILED"
result['message'] = "Invalid HTTP Response"
except requests.exceptions:
result['status'] = "FAILED"
result['message'] = "Invalid HTTP Response"

return result
result = {'service': service,
'status': "green",
'notes': ''}
try:
r = requests.get(url, timeout=60)
if r.status_code != requests.codes.ok:
result['status'] = "red"
result['notes'] = "HTTP Status code: %s" % r.status_code
return result
if hashlib.sha1(r.text).hexdigest() != sha1:
result['status'] = "red"
result['notes'] = "File content doesn't match"
except requests.exceptions.Timeout:
result['status'] = "red"
result['notes'] = "Connection to server timed out"
except requests.exceptions.ConnectionError:
result['status'] = "red"
result['notes'] = "Connection error"
except requests.exceptions.HTTPError:
result['status'] = "red"
result['notes'] = "Invalid HTTP Response"
except requests.exceptions:
result['status'] = "red"
result['notes'] = "Invalid HTTP Response"

return result


def test_xrootd(service, uri, sha1):
result = { 'service' : service,
'status' : "OK",
'message' : '' }
try:
print "run_xrdcp.sh %s /tmp/xrdcp.test" % uri
status = subprocess.call("./run_xrdcp.sh %s /tmp/xrdcp.test" % uri, shell=True)
except OSError:
result['status'] = "FAILED"
result['message'] = "xrdcp did not succeed"
result = {'service': service,
'status': "green",
'notes': ''}
try:
print "run_xrdcp.sh %s /tmp/xrdcp.test" % uri
status = subprocess.call("./run_xrdcp.sh %s /tmp/xrdcp.test" % uri, shell=True)
except OSError:
result['status'] = "red"
result['notes'] = "xrdcp did not succeed"
return result
if status != 0:
result['status'] = "red"
result['notes'] = "xrdcp did not succeed"
return result
if hashlib.sha1(open("/tmp/xrdcp.test").read()).hexdigest() != sha1:
result['status'] = "red"
result['notes'] = "SHA1 hash does not match"
os.unlink("/tmp/xrdcp.test")

return result
if status != 0 :
result['status'] = "FAILED"
result['message'] = "xrdcp did not succeed"
return result
if hashlib.sha1(open("/tmp/xrdcp.test").read()).hexdigest() != sha1:
result['status'] = "FAILED"
result['message'] = "SHA1 hash does not match"
os.unlink("/tmp/xrdcp.test")

return result


def run_tests(output_file):
test_sites = []
osg_tests = { 'anchor' : 'OSG',
'set_name' : 'OSG Connect',
'tests' : { 'http' : ['Stash',
'http://stash.osgconnect.net/keys/cern.ch.pub',
'5b83bedef4c7ba38520d7e1b764f0cbc28527fb9'],
'login' : ['SSH Login',
'login.osgconnect.net',
'sthapa']
}}
test_sites.append(osg_tests)
atlas_tests = { 'anchor' : 'ATLAS',
'set_name' : 'ATLAS Connect',
'tests' : { 'http' : ['Faxbox',
'http://faxbox.usatlas.org/keys/cern.ch.pub',
'5b83bedef4c7ba38520d7e1b764f0cbc28527fb9'],
'login' : ['SSH Login',
'login.usatlas.org',
'sthapa'],
'xrootd' : ['Xrootd',
'root://faxbox.usatlas.org//user/sthapa/filelist',
'f5127d99e4c75967e1bb992cd7d275554b111d75']}}
test_sites.append(atlas_tests)

for site in test_sites:
site['results'] = []
for test in site['tests']:
if test == 'http':
site['results'].append(test_download(*site['tests'][test]))
elif test == 'login':
site['results'].append(test_login(*site['tests'][test]))
elif test == 'xrootd':
site['results'].append(test_xrootd(*site['tests'][test]))

env = jinja2.Environment(loader=jinja2.FileSystemLoader( searchpath="." ))
template = env.get_template('templates/status.html')
admin_mesg = None
if os.path.isfile(ADMIN_MESG_LOCATION):
admin_mesg = open(ADMIN_MESG_LOCATION).read()
open(output_file, 'w').write(template.render(test_sets = test_sites,
admin_mesg = admin_mesg,
time = time.asctime()))


def run_tests(config={}, site_messages={}):
"""
Run tests on various services and return a dictionary based on
test results
:param config: dictionary with test configuration
:param site_messages: dictionary with messages/status overrides
for sites
:return: a dictionary with test results
"""
test_results = []
if not config:
return []
for service, config in config:
result = {'service': service}
if service in site_messages:
# if service is in site messages use this instead of
# test results
if 'status' in site_messages['service']:
result['status'] = site_messages['service']['status']
if 'note' in site_messages['service']:
result['note'] = site_messages['service']['notes']
test_results.append(result)
continue
if config['type'] == 'ssh':
result.update(test_login(service,
config['host'],
config['user']))
elif config['type'] == 'http':
result.update(test_download(service,
config['url'],
config['sha1sum']))
elif config['type'] == 'xrootd':
result.update(test_download(service,
config['uri'],
config['sha1sum']))
test_results.append(result)
return test_results


def parse_messages(mesg_file=None):
"""
Read a set of JSON formatted messages and store as dictionary
:param mesg_file: location of file with JSON formatted messages
:return: dictionary with messages/statuses
"""
site_mesg = {}
if not mesg_file:
return site_mesg
buf = open(mesg_file).read()
site_mesg = json.loads(buf)
return site_mesg


def parse_group_info(group_file=None):
"""
Read a set of JSON formatted info on groups for CI Connect
:param group_file: location of file with JSON formatted messages
:return: dictionary with messages/statuses
"""
info = {}
if not group_file:
return info
buf = open(group_file).read()
info = json.loads(buf)
return info


def parse_config(config_file=None):
"""
Read a set of JSON formatted configs and store as dictionary
:param config_file: location of file with JSON formatted config
:return: dictionary with messages/statuses
"""
config = {}
if not config_file:
return config
buf = open(config_file).read()
config = json.loads(buf)
return config


def write_output(output_file=None, results=[], group_info=""):
"""
Combine test results and group information and
output JSON to stdout or a file
:param output_file: path to output file, if None use stdout
:param results: list with test results
:param group_info: dictionary with group information
:return: None
"""
combined_output = "{\n"
combined_output += '"services": {' + "\n"
for result in results:
result_str = "\"{0}\": {\n".format(result['service'])
result_str += "\"status\": \"{1}\",\n".format(result['status'])
result_str += "\"notes\": \"{2}\"\n},\n".format(result['notes'])
combined_output += result_str
combined_output = combined_output[:-2] + "\n"
combined_output += "},\n"
combined_output += json.dumps(group_info)
combined_output += "}"
if output_file is None:
sys.stdout.write("{0}\n".format(combined_output))
else:
try:
output = open(output_file, 'w')
output.write(combined_output + "\n")
output.close()
except IOError:
sys.stderr.write("Can't write output to {0}".format(output_file))
sys.exit(1)
return None


if __name__ == "__main__":
run_tests(sys.argv[1])
sys.exit(0)
parser = argparse.ArgumentParser(description='Test a set of services and ' +
'write test output to a file')
parser.add_argument('--output',
dest='output',
default=None,
help='Specifies path to the output file')
parser.add_argument('--group-file',
dest='group_file',
default=None,
required=True,
help='Specifies path to the file with' +
' group information in JSON')
parser.add_argument('--admin-mesg-file',
dest='mesg_file',
default=None,
help='Specifies path to the file with admin messages' +
' in JSON')
parser.add_argument('--test-config',
dest='test_config',
default=None,
required=True,
help='Specifies path to the file with test configuration' +
' in JSON')
args = parser.parse_args(sys.argv[1:])
if not os.path.isfile(args.group_file):
sys.stderr.write("file specified in --group-file must exist " +
"got {0}".format(args.group_file))
sys.exit(1)
if args.mesg_file and not os.path.isfile(args.mesg_file):
sys.stderr.write("file specified in --mesg-file must exist " +
"got {0}".format(args.group_file))
sys.exit(1)
group_info = parse_group_info(args.group_file)
messages = parse_messages(args.mesg_file)
test_config = parse_config(args.test_config)
results = run_tests(test_config, messages)
write_output(args.output, results, group_info)
sys.exit(0)
Loading

0 comments on commit 8bf20fc

Please sign in to comment.