From bfdc3d37a9020fabafdd089341ce39aa6bfe20f0 Mon Sep 17 00:00:00 2001 From: Michael Elkins Date: Wed, 25 May 2016 21:54:56 +0000 Subject: Make rpkigui-import-routes use logging settings from /etc/rpki.conf instead of rpki.django_settings.gui Create new rpki.django_settings.gui_script Django settings file with a minimal subset required to use the ORM, to be used in auxillary scripts Add [rpkigui-import-routes] section to rpki.conf Change log level of warning about AS value errors in routeviews dumps to DEBUG svn path=/branches/tk705/; revision=6439 --- ca/rpkigui-import-routes | 92 ++++++++++++++++--------------------- rp/config/rpki-confgen.xml | 94 ++++++++++++++++++++++++++++++++++++++ rpki/django_settings/gui_script.py | 47 +++++++++++++++++++ rpki/gui/routeview/util.py | 17 ++++--- rpki/gui/script_util.py | 2 +- 5 files changed, 192 insertions(+), 60 deletions(-) create mode 100644 rpki/django_settings/gui_script.py diff --git a/ca/rpkigui-import-routes b/ca/rpkigui-import-routes index fb8e381e..aeecea6e 100755 --- a/ca/rpkigui-import-routes +++ b/ca/rpkigui-import-routes @@ -14,6 +14,11 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. +"""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.""" + __version__ = '$Id$' import optparse @@ -27,12 +32,15 @@ import fcntl import sys import os +import rpki.config + # configure django ORM from rpki.gui.script_util import setup setup() from rpki.gui.routeview.util import import_routeviews_dump +default_url = 'http://archive.routeviews.org/oix-route-views/oix-full-snapshot-latest.dat.bz2' class BadArgument(Exception): pass @@ -44,67 +52,47 @@ def timed_out(*ignored): 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: + myname = 'rpkigui-import-routes' + + cfg = rpki.config.argparser(section=myname, doc=__doc__) + cfg.add_logging_arguments() + args = cfg.argparser.parse_args() + cfg.configure_logging(ident=myname, args=args) + + jitter = cfg.getint('jitter', section=myname, default=600) + if jitter > 0: try: - delay = random.SystemRandom().randint(0, options.jitter) + delay = random.SystemRandom().randint(0, jitter) except NotImplementedError: - delay = random.randint(0, options.jitter) + delay = random.randint(0, 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) - + lockfile = cfg.get('lockfile', section=myname, default='/tmp/rpkigui-import-routes.lock') try: - if len(args) > 1: - raise BadArgument('more than one filename specified') - - if options.timeout > 0: + lock = os.open(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) + + filename = cfg.get('filename', section=myname, default=default_url) + filetype = cfg.get('filetype', section=myname, default='text') + download_dir = cfg.get('download-directory', section=myname, default='/var/tmp') + + timeout = cfg.getint('timeout', section=myname, default=5400) + try: + if timeout > 0: signal.signal(signal.SIGALRM, timed_out) - signal.setitimer(signal.ITIMER_REAL, options.timeout) + signal.setitimer(signal.ITIMER_REAL, timeout) - import_routeviews_dump(*args, filetype=options.filetype) + import_routeviews_dump(filename=filename, filetype=filetype, download_dir=download_dir) - if options.timeout > 0: + if timeout > 0: signal.setitimer(signal.ITIMER_REAL, 0) except Exception as e: diff --git a/rp/config/rpki-confgen.xml b/rp/config/rpki-confgen.xml index bc1458ea..a8533815 100644 --- a/rp/config/rpki-confgen.xml +++ b/rp/config/rpki-confgen.xml @@ -1028,6 +1028,100 @@ +
+ + + Configuration for the rpkigui-import-routes auxillary script. + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
diff --git a/rpki/django_settings/gui_script.py b/rpki/django_settings/gui_script.py new file mode 100644 index 00000000..4aa18e2c --- /dev/null +++ b/rpki/django_settings/gui_script.py @@ -0,0 +1,47 @@ +# $Id: gui.py 6427 2016-05-07 04:14:02Z sra $ + +# Copyright (C) 2015-2016 Parsons Government Services ("PARSONS") +# Portions copyright (C) 2014 Dragon Research Labs ("DRL") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notices and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND PARSONS AND DRL DISCLAIM ALL +# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +# PARSONS OR DRL 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. + +""" +This module contains settings for the GUI's auxillary scripts which just need +enough configuration to use the ORM. +""" + +# Pull in the irdb configuration, which in turn pulls in the common configuration. + +from .irdb import * # pylint: disable=W0401,W0614 + +__version__ = "$Id: gui.py 6427 2016-05-07 04:14:02Z sra $" + +INSTALLED_APPS.extend(( + #"django.contrib.contenttypes", # not sure if required for aux scripts? + "rpki.gui.app", + "rpki.gui.gui_rpki_cache", + "rpki.gui.routeview", + "rpki.rcynicdb" +)) + +LOGGING_CONFIG = None # we handle logging configuration ourself via rpki.conf + +# Allow local site to override any setting above -- but if there's +# anything that local sites routinely need to modify, please consider +# putting that configuration into rpki.conf and just adding code here +# to read that configuration. +try: + from local_settings import * # pylint: disable=W0401,F0401 +except ImportError: + pass diff --git a/rpki/gui/routeview/util.py b/rpki/gui/routeview/util.py index 14ac3cf9..1e2a9906 100644 --- a/rpki/gui/routeview/util.py +++ b/rpki/gui/routeview/util.py @@ -25,7 +25,6 @@ import bz2 from urllib import urlretrieve, unquote from django.db import transaction -from django.conf import settings from rpki.resource_set import resource_range_ipv4, resource_range_ipv6 from rpki.exceptions import BadIPResource @@ -35,9 +34,6 @@ from rpki.gui.routeview.models import RouteOrigin # globals logger = logging.getLogger(__name__) -# Eventually this can be retrived from rpki.conf -DEFAULT_URL = 'http://archive.routeviews.org/oix-route-views/oix-full-snapshot-latest.dat.bz2' - class ParseError(Exception): pass class RouteDumpParser(object): @@ -63,6 +59,9 @@ class RouteDumpParser(object): logger.warning('error while parsing line: {} ({})'.format(line, str(e))) continue + if prefix is None: # used when encountering AS sets that we skip over + continue + # the output may contain multiple paths to the same origin. # if this is the same prefix as the last entry, we don't need # to validate it again. @@ -121,6 +120,9 @@ class TextDumpParser(RouteDumpParser): # index -1 is i/e/? for igp/egp try: + if cols[-2][0] == '{' and cols[-2][-1] == '}': + # skip AS sets + return None, None origin_as = int(cols[-2]) except IndexError: raise ParseError('unexpected format') @@ -129,7 +131,8 @@ class TextDumpParser(RouteDumpParser): # FIXME Django doesn't have a field for positive integers up to 2^32-1 if origin_as < 0 or origin_as > 2147483647: - raise ParseError('AS value out of supported database range') + logger.debug('AS value out of range: %d', origin_as) + return None, None prefix = cols[1] @@ -186,7 +189,7 @@ class PipeFailed(ProgException): pass -def import_routeviews_dump(filename=DEFAULT_URL, filetype='text'): +def import_routeviews_dump(filename, filetype='text', download_dir='/var/tmp'): """Load the oix-full-snapshot-latest.bz2 from routeview.org into the rpki.gui.routeview database. @@ -205,7 +208,7 @@ def import_routeviews_dump(filename=DEFAULT_URL, filetype='text'): #get filename from the basename of the URL u = urlparse.urlparse(filename) bname = os.path.basename(unquote(u.path)) - tmpname = os.path.join(settings.DOWNLOAD_DIRECTORY, bname) + tmpname = os.path.join(download_dir, bname) logger.info("Downloading %s to %s", filename, tmpname) if os.path.exists(tmpname): diff --git a/rpki/gui/script_util.py b/rpki/gui/script_util.py index 289dbbb7..d0159840 100644 --- a/rpki/gui/script_util.py +++ b/rpki/gui/script_util.py @@ -26,7 +26,7 @@ def setup(): import os - os.environ.update(DJANGO_SETTINGS_MODULE = "rpki.django_settings.gui") + os.environ.update(DJANGO_SETTINGS_MODULE = "rpki.django_settings.gui_script") # Initialize Django. import django -- cgit v1.2.3