| #!/usr/bin/env python2 |
| # encoding: utf-8 |
| |
| # Copyright © 2018 Amdocs |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| import sys |
| import os |
| import json |
| import requests |
| from datetime import datetime |
| |
| consul_server = "consul-server:8500" |
| message_router = "message-router:3904" |
| topic = '{{.Values.config.messageRouterTopic}}' |
| log_file='/app/monitor.log' |
| status_file='/app/.health' |
| logEnabled=False |
| |
| siteName='sdnc01' |
| if os.environ.get('SDNC_IS_PRIMARY_CLUSTER', 'true') == 'false': |
| siteName='sdnc02' |
| |
| debug=False |
| if len(sys.argv) > 1 and sys.argv[1] == '--debug': |
| debug=True |
| |
| def get_state(healthcheck): |
| response = requests.get("http://" + consul_server + "/v1/health/checks/" + healthcheck) |
| if response.status_code != 200: |
| raise RuntimeError("HTTP " + str(response.status_code)) |
| data = response.json() |
| if len(data) == 0: |
| raise RuntimeError(healthcheck + " not found") |
| if len(data) > 1: |
| raise RuntimeError("Multiple states for " + healthcheck + " found") |
| |
| return data[0] |
| |
| |
| def log(message): |
| if logEnabled: |
| with open(log_file, 'a') as f: |
| f.write(str(datetime.now()) + " " + message + "\n") |
| |
| def healthcheck(checks, failFirst=True): |
| if len(checks) == 0: |
| return True |
| |
| for check in checks: |
| if type(check) is list: |
| passing = healthcheck(check, False) |
| else: |
| state = get_state(check) |
| status = state['Status'] |
| passing = status == "passing" or status == "warning" |
| log(check + " " + status) |
| if debug: |
| if status == "passing": |
| color = "\033[32m" # green |
| elif status == "warning": |
| color = "\033[33m" # yellow |
| else: |
| color = "\033[31m" # red |
| print check, color + status + "\033[0m" |
| if not passing: |
| print "\tCause:", state['Output'] |
| |
| |
| if passing: |
| if not failFirst: |
| # found a passing check so can stop here |
| return True |
| else: |
| if failFirst: |
| # found a failing check so can stop here |
| return False |
| |
| return failFirst |
| |
| |
| try: |
| with open("/app/config/healthchecks.json") as f: |
| checks = json.load(f) |
| |
| try: |
| with open(status_file) as f: |
| previous_result = f.read() |
| except IOError: |
| # file doesn't exist |
| previous_result = 'unknown' |
| |
| if healthcheck(checks): |
| result = "healthy" |
| else: |
| result = "unhealthy" |
| |
| print result |
| |
| # save current result to file |
| with open(status_file, 'w') as f: |
| f.write(result) |
| |
| if previous_result != 'unknown' and result != previous_result: |
| payload = { 'type' : 'health-change', 'status': result, 'site': siteName, 'deployment': '{{.Values.config.deployment}}', 'timestamp': str(datetime.now()) } |
| log("Posting event " + str(payload)) |
| try: |
| requests.post("http://" + message_router + "/events/" + topic, data=json.dumps(payload), headers={ 'Content-Type' : 'application/json' } ) |
| except Exception: |
| # events are best-effort |
| pass |
| |
| except Exception as e: |
| sys.exit(str(e)) |