#!/usr/bin/python3
#
# Copyright 2018 Red Hat 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 argparse
import logging
import os
import six
import socket
import sys
import time


from keystoneauth1 import loading
from keystoneauth1 import session

from novaclient import client

# In python3 SafeConfigParser was renamed to ConfigParser and the default
# for duplicate options default to true. In case of nova it is valid to
# have duplicate option lines, e.g. passthrough_whitelist which leads to
# issues reading the nova.conf
# https://bugs.launchpad.net/tripleo/+bug/1827775
if six.PY3:
    from six.moves.configparser import ConfigParser
    config = ConfigParser(strict=False)
else:
    from six.moves.configparser import SafeConfigParser
    config = SafeConfigParser()

debug = os.getenv('__OS_DEBUG', 'false')

if debug.lower() == 'true':
    loglevel = logging.DEBUG
else:
    loglevel = logging.INFO

logging.basicConfig(stream=sys.stdout, level=loglevel)
LOG = logging.getLogger('nova_wait_for_compute_service')

iterations = 60
timeout = 10
nova_cfg = '/etc/nova/nova.conf'

if __name__ == '__main__':
    parser = argparse.ArgumentParser(usage='%(prog)s [options]')
    parser.add_argument('-k', '--insecure',
                        action="store_false",
                        dest='insecure',
                        default=True,
                        help='Allow insecure connection when using SSL')

    args = parser.parse_args()
    LOG.debug('Running with parameter insecure = %s',
              args.insecure)

    if os.path.isfile(nova_cfg):
        try:
            config.read(nova_cfg)
        except Exception:
            LOG.exception('Error while reading nova.conf:')
    else:
        LOG.error('Nova configuration file %s does not exist', nova_cfg)
        sys.exit(1)

    my_host = config.get('DEFAULT', 'host')
    if not my_host:
        # If host isn't set nova defaults to this
        my_host = socket.gethostname()

    loader = loading.get_plugin_loader('password')
    auth = loader.load_from_options(
        auth_url=config.get('neutron',
                            'auth_url'),
        username=config.get('neutron',
                            'username'),
        password=config.get('neutron',
                            'password'),
        project_name=config.get('neutron',
                                'project_name'),
        project_domain_name=config.get('neutron',
                                       'project_domain_name'),
        user_domain_name=config.get('neutron',
                                    'user_domain_name'))
    sess = session.Session(auth=auth, verify=args.insecure)
    nova = client.Client('2.11', session=sess, endpoint_type='internal',
                         region_name=config.get('neutron', 'region_name'))

    # Wait until this host is listed in the service list
    for i in range(iterations):
        try:
            service_list = nova.services.list(binary='nova-compute')
            for entry in service_list:
                host = getattr(entry, 'host', '')
                zone = getattr(entry, 'zone', '')
                if host == my_host and zone != 'internal':
                    LOG.info('Nova-compute service registered')
                    sys.exit(0)
            LOG.info('Waiting for nova-compute service to register')
        except Exception:
            LOG.exception(
                'Error while waiting for nova-compute service to register')
        time.sleep(timeout)
sys.exit(1)

# vim: set et ts=4 sw=4 :
