| #!/usr/bin/python |
| # Copyright 2018 Mirantis, Inc. |
| # |
| # 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 logging |
| import os |
| import subprocess |
| import time |
| |
| # Import Salt Libs |
| import salt.utils.http |
| |
| |
| MODULE_NAME = 'contrail_health' |
| LOG = logging.getLogger(__name__) |
| |
| |
| def __virtual__(): |
| ''' |
| Only load this module if contrail-status or doctrail utility |
| (in case of containerized contrail version) is available. |
| ''' |
| if _is_cmd_available('contrail-status') or _is_cmd_available('doctrail'): |
| return MODULE_NAME |
| return False |
| |
| |
| def _is_cmd_available(cmd_name): |
| try: |
| with open(os.devnull) as devnull: |
| subprocess.Popen( |
| [cmd_name], stdout=devnull, stderr=devnull |
| ).communicate() |
| except OSError as e: |
| if e.errno == os.errno.ENOENT: |
| return False |
| return True |
| |
| |
| def get_services_status(): |
| cs_out = None |
| |
| if _is_cmd_available('contrail-status'): |
| LOG.info('Trying to get status of contrail services ' |
| 'using contrail-status utility on host ...') |
| try: |
| cs_out = str(subprocess.check_output(['contrail-status'])) |
| except subprocess.CalledProcessError as e: |
| LOG.warn('Status of contrail services cannot be checked ' |
| 'by contrail-status utility from host') |
| if cs_out is None and _is_cmd_available('doctrail'): |
| LOG.info('Trying to get status of contrail services inside containers ' |
| 'using doctrail utility ...') |
| try: |
| cs_out = str(subprocess.check_output( |
| ['doctrail', 'all', 'contrail-status']) |
| ) |
| except subprocess.CalledProcessError as e: |
| LOG.warn('Status of contrail services inside containers cannot ' |
| 'be checked by contrail-status utility via doctrail cmd') |
| |
| status_map = {} |
| |
| if cs_out: |
| for line in cs_out.split('\n'): |
| line_list = line.split() |
| if (not line.startswith("==") and "FOR NODE" not in line and |
| len(line_list) >= 2): |
| status_map[line_list[0].split(":")[0]] = line_list[1] |
| else: |
| LOG.error('Status of contrail services cannot be checked ' |
| 'by {0} module.'.format(MODULE_NAME)) |
| |
| return status_map |
| |
| ''' |
| Check status of Contail API service on Virtual IP which is defined by pillars. |
| |
| CLI Example: |
| |
| .. code-block:: bash |
| |
| salt 'ntw01*' contrail_health.get_api_status [wait_for=300] \\ |
| [tries=20] |
| |
| wait_for |
| Number of seconds how long to wait for API response. |
| |
| tries |
| Number of tries. After each unsuccessful try will sleep for \\ |
| (wait_for/tries). |
| ''' |
| |
| |
| def get_api_status(wait_for=180, tries=20): |
| api_host = __pillar__['opencontrail'].get('client', {}).get('api', {}).get('host', {}) |
| api_port = __pillar__['opencontrail']['client']['api']['port'] |
| |
| for t in range(0, tries): |
| try: |
| data = salt.utils.http.query("http://{0}:{1}".format(api_host, api_port), backend='requests', status=True) |
| if data['status'] == 200: |
| return True |
| except Exception as e: |
| LOG.error(e.message) |
| time.sleep(int(wait_for / tries)) |
| |
| return False |