#!/usr/bin/python3
#
# Copyright (c) 2014 Stephen Gran <sgran@debian.org>
#
# Run ud-replicate on a trigger
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

import json
import logging
import logging.handlers
import optparse
import os
import stat
import subprocess
import sys
import time

from dsa_mq.connection import Connection
from dsa_mq.config import Config

parser = optparse.OptionParser()
parser.add_option("-D", "--dryrun",
                  action="store_true", default=False,
                  help="Dry run mode")

parser.add_option("-d", "--debug",
                  action="store_true", default=False,
                  help="Enable debug output")

(options, args) = parser.parse_args()
options.section = 'dsa-udreplicate'
options.config = '/etc/dsa/pubsub.conf'
config = Config(options)
mq_conf = {
    'rabbit_userid': config.username,
    'rabbit_password': config.password,
    'rabbit_virtual_host': config.vhost,
    'rabbit_hosts': ['pubsub02.debian.org', 'pubsub01.debian.org'],
    'use_ssl': True,
    'ssl_ca_certs': '/etc/ssl/debian/certs/ca.crt',
}

lvl = logging.INFO
if config.debug:
    lvl = logging.DEBUG

FORMAT = '%(asctime)s ud-replicated: %(levelname)s %(message)s'
SFORMAT = 'ud-replicated[%(process)s]: %(message)s'
logging.basicConfig(format=FORMAT, level=lvl)
LOG = logging.getLogger(__name__)
logsock = '/dev/log'
if os.path.exists('/var/run/log') and stat.S_ISSOCK(os.stat('/var/run/log').st_mode):  # Kfreebsd randomly different
    logsock = '/var/run/log'
syslog_handler = logging.handlers.SysLogHandler(address=logsock)
formatter = logging.Formatter(SFORMAT)
syslog_handler.setFormatter(formatter)
LOG.addHandler(syslog_handler)

last_run = 0


def do_replicate(message):
    global last_run
    last_update = int(time.time())
    timestamp = last_update
    try:
        message = json.loads(message)
    except ValueError:
        pass

    if isinstance(message, dict):
        timestamp = message.get('timestamp', last_update)
        message = message.get('message', 'update required')
    LOG.debug("Got message at %s: %s" % (last_update, message))
    if last_run > timestamp:
        return

    command = ['/usr/bin/ud-replicate']
    if options.dryrun:
        LOG.debug("Would have run %s" % command)
    else:
        old_term = os.environ.get('TERM')
        os.environ['TERM'] = 'dumb'
        try:
            subprocess.check_call(command)
        except Exception:
            LOG.error('%s failed:', ' '.join(command))
        else:
            LOG.debug('%s finished with ret: 0' % ' '.join(command))
        finally:
            if old_term is not None:
                os.environ['TERM'] = old_term
    last_run = last_update


def main():
    conn = Connection(conf=mq_conf)
    conn.declare_topic_consumer(config.topic,
                                callback=do_replicate,
                                queue_name=config.queue,
                                exchange_name=config.exchange,
                                ack_on_error=False)

    try:
        conn.consume()
    except KeyboardInterrupt:
        pass
    except Exception as e:
        LOG.error(e)
    finally:
        conn.close()
        sys.exit(0)


if __name__ == '__main__':
    do_replicate(json.dumps(
        {'timestamp': time.time(),
         'message': 'startup complete'}))
    main()
