aboutsummaryrefslogtreecommitdiff
path: root/portal-gui/scripts/load_csv.py
blob: eff34b14412636bf468221252149f238b45b0ef5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/env python
# $Id$
#
# 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 myrpki.conf
# for the handle you are loading data
#

import os
import csv
import socket # for socket.error

import rpki
import rpki.resource_set
import rpki.ipaddrs
from rpki.myrpki import csv_reader

from rpkigui.myrpki import models
from rpkigui.myrpki.views import add_roa_requests

cfg_file = os.getenv("MYRPKI_CONF", "myrpki.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(parent, parent_range):
    '''Return the child address range that is the closest match, or
    returns the arguments if no children.'''
    best = None
    best_range = None
    for q in parent.children.all():
        if best is None:
            best = q
            best_range = q.as_resource_range()
        else:
            t = q.as_resource_range()
            if t.min >= best_range.min and t.max <= best_range.max:
                best = q
                best_range = t
    if best:
        if best.children.all():
            best, best_range = best_child(best, best_range)
        return (best, best_range)

    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(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 = None
    for a in asn_set:
        if best is None:
            best = a
        elif a.lo >= best.lo and a.hi <= best.hi:
            best = a
    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():
    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():
    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():
    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()