#!/usr/bin/env python # Copyright (C) 2012, 2013 SPARTA, Inc. a Parsons Company # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND SPARTA DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL SPARTA BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. __version__ = '$Id$' import optparse import logging import time import random import signal import errno import atexit import fcntl import sys import os # configure django ORM from rpki.gui.script_util import setup setup() from rpki.gui.routeview.util import import_routeviews_dump class BadArgument(Exception): pass def timed_out(*ignored): logging.error('timed out') sys.exit(1) if __name__ == '__main__': parser = optparse.OptionParser( usage='%prog [options] [PATH]', description="""This tool is used to import the IPv4/6 BGP table dumps from routeviews.org into the RPKI Web Portal database. If the input file is a bzip2 compressed file, it will be decompressed automatically.""") parser.add_option('-t', '--type', dest='filetype', metavar='TYPE', help='Specify the input file type (text, mrt) [Default: %default]') parser.add_option('-l', '--level', dest='log_level', default='ERROR', help='Set logging level [Default: %default]') parser.add_option('-b', '--bgpdump', dest='bgpdump', metavar='PROG', help='Specify path to bgdump binary') parser.add_option('-j', '--jitter', dest='jitter', type='int', help='Specify upper bound of startup delay, in seconds [Default: %default]') parser.add_option('--lockfile', dest='lockfile', help='Set name of lock file; empty string disables locking [Default: %default]') parser.add_option('--timeout', dest='timeout', type='int', help='Specify timeout for download and import, in seconds [Default: %default]') parser.set_defaults(debug=False, verbose=False, filetype='text', jitter=0, lockfile='/tmp/rpkigui-import-routes.lock', timeout=90*60) options, args = parser.parse_args() v = getattr(logging, options.log_level.upper()) logging.basicConfig(level=v) atexit.register(logging.shutdown) logging.info('logging level set to ' + logging.getLevelName(v)) if options.bgpdump: BGPDUMP = os.path.expanduser(options.bgpdump) if options.jitter > 0: try: delay = random.SystemRandom().randint(0, options.jitter) except NotImplementedError: delay = random.randint(0, options.jitter) logging.info('jitter active, delaying startup for %d seconds', delay) time.sleep(delay) if options.lockfile: try: lock = os.open(options.lockfile, os.O_RDONLY | os.O_CREAT | os.O_NONBLOCK, 0666) fcntl.flock(lock, fcntl.LOCK_EX | fcntl.LOCK_NB) except (IOError, OSError), e: if e.errno == errno.EAGAIN: logging.info('lock held by another process') sys.exit(0) else: logging.exception(e) sys.exit(1) try: if len(args) > 1: raise BadArgument('more than one filename specified') if options.timeout > 0: signal.signal(signal.SIGALRM, timed_out) signal.setitimer(signal.ITIMER_REAL, options.timeout) import_routeviews_dump(*args, filetype=options.filetype) if options.timeout > 0: signal.setitimer(signal.ITIMER_REAL, 0) except Exception as e: logging.exception(e) sys.exit(1)