#!/usr/bin/python # # Copyright (c) 2014 Stephen Gran # # 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. from dsa_mq.connection import Connection from dsa_mq.config import Config import json import logging import logging.handlers import optparse import os import platform import stat import subprocess import sys import time 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': False } 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: 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()