aboutsummaryrefslogtreecommitdiff
path: root/rpkid/rpki/gui/scripts/load_csv.py
diff options
context:
space:
mode:
Diffstat (limited to 'rpkid/rpki/gui/scripts/load_csv.py')
-rwxr-xr-xrpkid/rpki/gui/scripts/load_csv.py145
1 files changed, 145 insertions, 0 deletions
diff --git a/rpkid/rpki/gui/scripts/load_csv.py b/rpkid/rpki/gui/scripts/load_csv.py
new file mode 100755
index 00000000..0ef49cce
--- /dev/null
+++ b/rpkid/rpki/gui/scripts/load_csv.py
@@ -0,0 +1,145 @@
+# $Id$
+#
+# Copyright (C) 2010 SPARTA, Inc. dba Cobham Analytic Solutions
+#
+# 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.
+#
+#
+# Helper script to load existing data from csv into the Django DB.
+# Primarly useful for the initial load, as the GUI does not sync changes
+# made directly to the csv files back into the database.
+#
+# This script should be run from the directory containing the rpki.conf
+# for the handle you are loading data
+#
+
+import sys, os
+os.environ['DJANGO_SETTINGS_MODULE'] = 'rpki.gui.settings'
+
+import csv
+import socket # for socket.error
+
+import rpki
+import rpki.resource_set
+import rpki.ipaddrs
+from rpki.myrpki import csv_reader
+
+from rpki.gui.app import models
+from rpki.gui.app.views import add_roa_requests
+
+cfg_file = os.getenv("RPKI_CONF", "rpki.conf")
+cfg = rpki.config.parser(cfg_file, "myrpki")
+handle = cfg.get('handle')
+asn_csv = cfg.get('asn_csv')
+prefix_csv = cfg.get('prefix_csv')
+roa_csv = cfg.get('roa_csv')
+
+print 'processing csv files for resource handle', handle
+
+conf = models.Conf.objects.get(handle=handle)
+
+# every parent has a favorite
+def best_child(address_range, parent, parent_range):
+ '''Return the child address range that is the closest match, or
+ returns the arguments if no children.'''
+ if address_range == parent_range:
+ return (parent, parent_range)
+ for q in list(parent.children.all()): # force strict evaluation
+ t = q.as_resource_range()
+ if t.min <= address_range.min and t.max >= address_range.max:
+ return best_child(address_range, q, t)
+ # check for overlap
+ if t.min <= address_range.min <= t.max or t.min <= address_range.max <= t.max:
+ raise RuntimeError, \
+ 'can not handle overlapping ranges: %s and %s' % (address_range, t)
+ return parent, parent_range
+
+def get_or_create_prefix(address_range):
+ '''Returns a AddressRange object for the resource_range_ip specified
+ as an argument. If no match is found, a new AddressRange object is
+ created as a child of the best matching received resource.'''
+
+ # get all resources from our parents
+ prefix_set = models.AddressRange.objects.filter(
+ from_cert__parent__in=conf.parents.all())
+
+ # gross, since we store the address ranges as strings in the django
+ # db, we can't use the normal __lte and __gte filters, so we get to
+ # do it in python instead.
+ for prefix in prefix_set:
+ prefix_range = prefix.as_resource_range()
+ if (prefix_range.min <= address_range.min and
+ prefix_range.max >= address_range.max):
+ # there should only ever be a single matching prefix
+ break
+ else:
+ raise RuntimeError, '%s does not match any received address range.' % (
+ address_range,)
+
+ # find the best match among the children + grandchildren
+ prefix, prefix_range = best_child(address_range, prefix, prefix_range)
+
+ print 'best match for %s is %s' % (address_range, prefix)
+ if prefix_range.min != address_range.min or prefix_range.max != address_range.max:
+ # create suballocation
+ print 'creating new range'
+ prefix = models.AddressRange.objects.create(lo=str(address_range.min),
+ hi=str(address_range.max), parent=prefix)
+ return prefix
+
+def get_or_create_asn(asn):
+ asn_set = models.Asn.objects.filter(lo__lte=asn.min, hi__gte=asn.max,
+ from_cert__parent__in=conf.parents.all())
+ if not asn_set:
+ raise RuntimeError, '%s does not match any received AS range' % (asn,)
+ best = best_child(asn, asn_set[0], asn_set[0].as_resource_range())[0]
+ print 'best match for %s is %s' % (asn, best)
+ if best.lo != asn.min or best.hi != asn.max:
+ best = models.Asn.objects.create(lo=asn.min, hi=asn.max, parent=best)
+ return best
+
+def do_asns():
+ print 'processing', asn_csv
+ for child_handle, asn in csv_reader(asn_csv, columns=2):
+ asn_range = rpki.resource_set.resource_range_as.parse_str(asn)
+ child = conf.children.get(handle=child_handle)
+ asn = get_or_create_asn(asn_range)
+ child.asn.add(asn)
+
+def do_prefixes():
+ print 'processing', prefix_csv
+ for child_handle, prefix in csv_reader(prefix_csv, columns=2):
+ child = conf.children.get(handle=child_handle)
+ try:
+ rs = rpki.resource_set.resource_range_ipv4.parse_str(prefix)
+ except ValueError, err:
+ rs = rpki.resource_set.resource_range_ipv6.parse_str(prefix)
+ obj = get_or_create_prefix(rs)
+ obj.allocated = child
+ obj.save()
+
+def do_roas():
+ print 'processing', roa_csv
+ for prefix, asn, group in csv_reader(roa_csv, columns=3):
+ try:
+ rs = rpki.resource_set.roa_prefix_ipv4.parse_str(prefix)
+ except ValueError, err:
+ rs = rpki.resource_set.roa_prefix_ipv6.parse_str(prefix)
+
+ print str(rs.min()), str(rs.max()), rs.max_prefixlen
+ obj = get_or_create_prefix(rs.to_resource_range())
+ add_roa_requests(conf, obj, [int(asn)], rs.max_prefixlen)
+
+do_asns()
+do_prefixes()
+do_roas()