Commit b6b2b331 authored by Peter Müller's avatar Peter Müller Committed by Michael Tremer

location-importer.in: track original countries as well

This helps us to determine how many network objects have more than one
country set, and what their original country code set looked like.

The third version of this patch uses ALTER TABLE to add the column for
original countries, preventing existing SQL setups from breaking, and is
correctly based against the current "master" branch.
Signed-off-by: default avatarPeter Müller <peter.mueller@ipfire.org>
Signed-off-by: default avatarMichael Tremer <michael.tremer@ipfire.org>
parent 509f98b1
...@@ -166,6 +166,7 @@ class CLI(object): ...@@ -166,6 +166,7 @@ class CLI(object):
-- networks -- networks
CREATE TABLE IF NOT EXISTS networks(network inet, country text); CREATE TABLE IF NOT EXISTS networks(network inet, country text);
ALTER TABLE networks ADD COLUMN IF NOT EXISTS original_countries text[];
ALTER TABLE networks ADD COLUMN IF NOT EXISTS source text NOT NULL; ALTER TABLE networks ADD COLUMN IF NOT EXISTS source text NOT NULL;
CREATE UNIQUE INDEX IF NOT EXISTS networks_network ON networks(network); CREATE UNIQUE INDEX IF NOT EXISTS networks_network ON networks(network);
CREATE INDEX IF NOT EXISTS networks_family ON networks USING BTREE(family(network)); CREATE INDEX IF NOT EXISTS networks_family ON networks USING BTREE(family(network));
...@@ -379,7 +380,7 @@ class CLI(object): ...@@ -379,7 +380,7 @@ class CLI(object):
ON COMMIT DROP; ON COMMIT DROP;
CREATE UNIQUE INDEX _organizations_handle ON _organizations(handle); CREATE UNIQUE INDEX _organizations_handle ON _organizations(handle);
CREATE TEMPORARY TABLE _rirdata(network inet NOT NULL, country text NOT NULL, source text NOT NULL) CREATE TEMPORARY TABLE _rirdata(network inet NOT NULL, country text NOT NULL, original_countries text[] NOT NULL, source text NOT NULL)
ON COMMIT DROP; ON COMMIT DROP;
CREATE INDEX _rirdata_search ON _rirdata USING BTREE(family(network), masklen(network)); CREATE INDEX _rirdata_search ON _rirdata USING BTREE(family(network), masklen(network));
CREATE UNIQUE INDEX _rirdata_network ON _rirdata(network); CREATE UNIQUE INDEX _rirdata_network ON _rirdata(network);
...@@ -410,8 +411,8 @@ class CLI(object): ...@@ -410,8 +411,8 @@ class CLI(object):
for family in (row.family for row in families): for family in (row.family for row in families):
smallest = self.db.get("SELECT MIN(masklen(network)) AS prefix FROM _rirdata WHERE family(network) = %s", family) smallest = self.db.get("SELECT MIN(masklen(network)) AS prefix FROM _rirdata WHERE family(network) = %s", family)
self.db.execute("INSERT INTO networks(network, country, source) \ self.db.execute("INSERT INTO networks(network, country, original_countries, source) \
SELECT network, country, source FROM _rirdata WHERE masklen(network) = %s AND family(network) = %s", smallest.prefix, family) SELECT network, country, original_countries, source FROM _rirdata WHERE masklen(network) = %s AND family(network) = %s", smallest.prefix, family)
# ... determine any other prefixes for this network family, ... # ... determine any other prefixes for this network family, ...
prefixes = self.db.query("SELECT DISTINCT masklen(network) AS prefix FROM _rirdata \ prefixes = self.db.query("SELECT DISTINCT masklen(network) AS prefix FROM _rirdata \
...@@ -425,6 +426,7 @@ class CLI(object): ...@@ -425,6 +426,7 @@ class CLI(object):
SELECT SELECT
_rirdata.network, _rirdata.network,
_rirdata.country, _rirdata.country,
_rirdata.original_countries,
_rirdata.source _rirdata.source
FROM FROM
_rirdata _rirdata
...@@ -438,6 +440,7 @@ class CLI(object): ...@@ -438,6 +440,7 @@ class CLI(object):
DISTINCT ON (c.network) DISTINCT ON (c.network)
c.network, c.network,
c.country, c.country,
c.original_countries,
c.source, c.source,
masklen(networks.network), masklen(networks.network),
networks.country AS parent_country networks.country AS parent_country
...@@ -452,10 +455,11 @@ class CLI(object): ...@@ -452,10 +455,11 @@ class CLI(object):
masklen(networks.network) DESC NULLS LAST masklen(networks.network) DESC NULLS LAST
) )
INSERT INTO INSERT INTO
networks(network, country, source) networks(network, country, original_countries, source)
SELECT SELECT
network, network,
country, country,
original_countries,
source source
FROM FROM
filtered filtered
...@@ -624,28 +628,37 @@ class CLI(object): ...@@ -624,28 +628,37 @@ class CLI(object):
inetnum[key] = [ipaddress.ip_network(val, strict=False)] inetnum[key] = [ipaddress.ip_network(val, strict=False)]
elif key == "country": elif key == "country":
inetnum[key] = val.upper() # Catch RIR data objects with more than one country code...
if not key in inetnum.keys():
inetnum[key] = []
else:
if val.upper() in inetnum.get("country"):
# ... but keep this list distinct...
continue
inetnum[key].append(val.upper())
# Skip empty objects # Skip empty objects
if not inetnum or not "country" in inetnum: if not inetnum or not "country" in inetnum:
return return
# Prepare skipping objects with unknown country codes...
invalidcountries = [singlecountry for singlecountry in inetnum.get("country") if singlecountry not in validcountries]
# Iterate through all networks enumerated from above, check them for plausibility and insert # Iterate through all networks enumerated from above, check them for plausibility and insert
# them into the database, if _check_parsed_network() succeeded # them into the database, if _check_parsed_network() succeeded
for single_network in inetnum.get("inet6num") or inetnum.get("inetnum"): for single_network in inetnum.get("inet6num") or inetnum.get("inetnum"):
if self._check_parsed_network(single_network): if self._check_parsed_network(single_network):
# Skip objects with unknown country codes - to avoid log spam for invalid or too small # Skip objects with unknown country codes if they are valid to avoid log spam...
# networks, this check is - kinda ugly - done at this point if validcountries and invalidcountries:
if validcountries and inetnum.get("country") not in validcountries: log.warning("Skipping network with bogus countr(y|ies) %s (original countries: %s): %s" % \
log.warning("Skipping network with bogus country '%s': %s" % \ (invalidcountries, inetnum.get("country"), inetnum.get("inet6num") or inetnum.get("inetnum")))
(inetnum.get("country"), inetnum.get("inet6num") or inetnum.get("inetnum")))
break
# Everything is fine here, run INSERT statement... # Everything is fine here, run INSERT statement...
self.db.execute("INSERT INTO _rirdata(network, country, source) \ self.db.execute("INSERT INTO _rirdata(network, country, original_countries, source) \
VALUES(%s, %s, %s) ON CONFLICT (network) DO UPDATE SET country = excluded.country", VALUES(%s, %s, %s, %s) ON CONFLICT (network) DO UPDATE SET country = excluded.country",
"%s" % single_network, inetnum.get("country"), source_key, "%s" % single_network, inetnum.get("country")[0], inetnum.get("country"), source_key,
) )
def _parse_org_block(self, block, source_key): def _parse_org_block(self, block, source_key):
...@@ -736,10 +749,10 @@ class CLI(object): ...@@ -736,10 +749,10 @@ class CLI(object):
if not self._check_parsed_network(network): if not self._check_parsed_network(network):
return return
self.db.execute("INSERT INTO networks(network, country, source) \ self.db.execute("INSERT INTO networks(network, country, original_countries, source) \
VALUES(%s, %s, %s) ON CONFLICT (network) DO \ VALUES(%s, %s, %s, %s) ON CONFLICT (network) DO \
UPDATE SET country = excluded.country", UPDATE SET country = excluded.country",
"%s" % network, country, source_key, "%s" % network, country, [country], source_key,
) )
def handle_update_announcements(self, ns): def handle_update_announcements(self, ns):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment