|
|
47b589 |
From c3a924203e8f0d3d6d6fc7882f006d60e7d8d985 Mon Sep 17 00:00:00 2001
|
|
|
47b589 |
From: Gris Ge <fge@redhat.com>
|
|
|
47b589 |
Date: Fri, 19 Jun 2020 10:14:25 +0800
|
|
|
47b589 |
Subject: [PATCH] ip: canonicalize IP address
|
|
|
47b589 |
|
|
|
47b589 |
Canonicalize these IP addresses:
|
|
|
47b589 |
* `InterfaceIP.ADDRESS_IP`
|
|
|
47b589 |
* `Route.DESTINATION`
|
|
|
47b589 |
* `Route.NEXT_HOP_ADDRESS`
|
|
|
47b589 |
* `RouteRule.IP_FROM`
|
|
|
47b589 |
* `RouteRule.IP_TO`
|
|
|
47b589 |
|
|
|
47b589 |
Introduced two functions to `libnmstate/iplib.py`:
|
|
|
47b589 |
* `canonicalize_ip_network()` returns address with prefix
|
|
|
47b589 |
* `canonicalize_ip_address()` returns address without prefix
|
|
|
47b589 |
|
|
|
47b589 |
Unit test cases added.
|
|
|
47b589 |
|
|
|
47b589 |
Signed-off-by: Gris Ge <fge@redhat.com>
|
|
|
47b589 |
---
|
|
|
47b589 |
libnmstate/ifaces/base_iface.py | 19 +++++++------------
|
|
|
47b589 |
libnmstate/iplib.py | 14 ++++++++++++++
|
|
|
47b589 |
libnmstate/route.py | 12 ++++++++++++
|
|
|
47b589 |
libnmstate/route_rule.py | 14 +++++++-------
|
|
|
47b589 |
4 files changed, 40 insertions(+), 19 deletions(-)
|
|
|
47b589 |
|
|
|
47b589 |
diff --git a/libnmstate/ifaces/base_iface.py b/libnmstate/ifaces/base_iface.py
|
|
|
47b589 |
index 33da69d..56a1115 100644
|
|
|
47b589 |
--- a/libnmstate/ifaces/base_iface.py
|
|
|
47b589 |
+++ b/libnmstate/ifaces/base_iface.py
|
|
|
47b589 |
@@ -20,13 +20,12 @@
|
|
|
47b589 |
from collections.abc import Mapping
|
|
|
47b589 |
from copy import deepcopy
|
|
|
47b589 |
import logging
|
|
|
47b589 |
-from ipaddress import ip_address
|
|
|
47b589 |
from operator import itemgetter
|
|
|
47b589 |
|
|
|
47b589 |
from libnmstate.error import NmstateInternalError
|
|
|
47b589 |
from libnmstate.error import NmstateValueError
|
|
|
47b589 |
-from libnmstate.iplib import is_ipv6_address
|
|
|
47b589 |
from libnmstate.iplib import is_ipv6_link_local_addr
|
|
|
47b589 |
+from libnmstate.iplib import canonicalize_ip_address
|
|
|
47b589 |
from libnmstate.schema import Interface
|
|
|
47b589 |
from libnmstate.schema import InterfaceIP
|
|
|
47b589 |
from libnmstate.schema import InterfaceIPv6
|
|
|
47b589 |
@@ -44,7 +43,7 @@ class IPState:
|
|
|
47b589 |
self._info = info
|
|
|
47b589 |
self._remove_stack_if_disabled()
|
|
|
47b589 |
self._sort_addresses()
|
|
|
47b589 |
- self._canonicalize_ipv6_addr()
|
|
|
47b589 |
+ self._canonicalize_ip_addr()
|
|
|
47b589 |
self._canonicalize_dynamic()
|
|
|
47b589 |
|
|
|
47b589 |
def _canonicalize_dynamic(self):
|
|
|
47b589 |
@@ -61,15 +60,11 @@ class IPState:
|
|
|
47b589 |
):
|
|
|
47b589 |
self._info.pop(dhcp_option, None)
|
|
|
47b589 |
|
|
|
47b589 |
- def _canonicalize_ipv6_addr(self):
|
|
|
47b589 |
- """
|
|
|
47b589 |
- Convert full IPv6 address to abbreviated address.
|
|
|
47b589 |
- """
|
|
|
47b589 |
- if self._family == Interface.IPV6:
|
|
|
47b589 |
- for addr in self.addresses:
|
|
|
47b589 |
- address = addr[InterfaceIP.ADDRESS_IP]
|
|
|
47b589 |
- if is_ipv6_address(address):
|
|
|
47b589 |
- addr[InterfaceIP.ADDRESS_IP] = str(ip_address(address))
|
|
|
47b589 |
+ def _canonicalize_ip_addr(self):
|
|
|
47b589 |
+ for addr in self.addresses:
|
|
|
47b589 |
+ addr[InterfaceIP.ADDRESS_IP] = canonicalize_ip_address(
|
|
|
47b589 |
+ addr[InterfaceIP.ADDRESS_IP]
|
|
|
47b589 |
+ )
|
|
|
47b589 |
|
|
|
47b589 |
def _sort_addresses(self):
|
|
|
47b589 |
self.addresses.sort(key=itemgetter(InterfaceIP.ADDRESS_IP))
|
|
|
47b589 |
diff --git a/libnmstate/iplib.py b/libnmstate/iplib.py
|
|
|
47b589 |
index 57fffd7..183b81b 100644
|
|
|
47b589 |
--- a/libnmstate/iplib.py
|
|
|
47b589 |
+++ b/libnmstate/iplib.py
|
|
|
47b589 |
@@ -52,3 +52,17 @@ def ip_address_full_to_tuple(addr):
|
|
|
47b589 |
raise NmstateValueError(f"Invalid IP address, error: {err}")
|
|
|
47b589 |
|
|
|
47b589 |
return f"{net.network_address}", net.prefixlen
|
|
|
47b589 |
+
|
|
|
47b589 |
+
|
|
|
47b589 |
+def canonicalize_ip_network(address):
|
|
|
47b589 |
+ try:
|
|
|
47b589 |
+ return ipaddress.ip_network(address, strict=False).with_prefixlen
|
|
|
47b589 |
+ except ValueError as e:
|
|
|
47b589 |
+ raise NmstateValueError(f"Invalid IP network address: {e}")
|
|
|
47b589 |
+
|
|
|
47b589 |
+
|
|
|
47b589 |
+def canonicalize_ip_address(address):
|
|
|
47b589 |
+ try:
|
|
|
47b589 |
+ return ipaddress.ip_address(address).compressed
|
|
|
47b589 |
+ except ValueError as e:
|
|
|
47b589 |
+ raise NmstateValueError(f"Invalid IP address: {e}")
|
|
|
47b589 |
diff --git a/libnmstate/route.py b/libnmstate/route.py
|
|
|
47b589 |
index 6534182..a182f99 100644
|
|
|
47b589 |
--- a/libnmstate/route.py
|
|
|
47b589 |
+++ b/libnmstate/route.py
|
|
|
47b589 |
@@ -22,6 +22,8 @@ from collections import defaultdict
|
|
|
47b589 |
from libnmstate.error import NmstateValueError
|
|
|
47b589 |
from libnmstate.error import NmstateVerificationError
|
|
|
47b589 |
from libnmstate.iplib import is_ipv6_address
|
|
|
47b589 |
+from libnmstate.iplib import canonicalize_ip_network
|
|
|
47b589 |
+from libnmstate.iplib import canonicalize_ip_address
|
|
|
47b589 |
from libnmstate.prettystate import format_desired_current_state_diff
|
|
|
47b589 |
from libnmstate.schema import Interface
|
|
|
47b589 |
from libnmstate.schema import Route
|
|
|
47b589 |
@@ -44,6 +46,7 @@ class RouteEntry(StateEntry):
|
|
|
47b589 |
# TODO: Convert IPv6 full address to abbreviated address
|
|
|
47b589 |
self.complement_defaults()
|
|
|
47b589 |
self._invalid_reason = None
|
|
|
47b589 |
+ self._canonicalize_ip_address()
|
|
|
47b589 |
|
|
|
47b589 |
@property
|
|
|
47b589 |
def is_ipv6(self):
|
|
|
47b589 |
@@ -148,6 +151,15 @@ class RouteEntry(StateEntry):
|
|
|
47b589 |
return False
|
|
|
47b589 |
return True
|
|
|
47b589 |
|
|
|
47b589 |
+ def _canonicalize_ip_address(self):
|
|
|
47b589 |
+ if not self.absent:
|
|
|
47b589 |
+ if self.destination:
|
|
|
47b589 |
+ self.destination = canonicalize_ip_network(self.destination)
|
|
|
47b589 |
+ if self.next_hop_address:
|
|
|
47b589 |
+ self.next_hop_address = canonicalize_ip_address(
|
|
|
47b589 |
+ self.next_hop_address
|
|
|
47b589 |
+ )
|
|
|
47b589 |
+
|
|
|
47b589 |
|
|
|
47b589 |
class RouteState:
|
|
|
47b589 |
def __init__(self, ifaces, des_route_state, cur_route_state):
|
|
|
47b589 |
diff --git a/libnmstate/route_rule.py b/libnmstate/route_rule.py
|
|
|
47b589 |
index 8b45367..f35d59c 100644
|
|
|
47b589 |
--- a/libnmstate/route_rule.py
|
|
|
47b589 |
+++ b/libnmstate/route_rule.py
|
|
|
47b589 |
@@ -6,7 +6,7 @@ from libnmstate.error import NmstateVerificationError
|
|
|
47b589 |
from libnmstate.error import NmstateValueError
|
|
|
47b589 |
from libnmstate.iplib import KERNEL_MAIN_ROUTE_TABLE_ID
|
|
|
47b589 |
from libnmstate.iplib import is_ipv6_address
|
|
|
47b589 |
-from libnmstate.iplib import to_ip_address_full
|
|
|
47b589 |
+from libnmstate.iplib import canonicalize_ip_network
|
|
|
47b589 |
from libnmstate.prettystate import format_desired_current_state_diff
|
|
|
47b589 |
from libnmstate.schema import Interface
|
|
|
47b589 |
from libnmstate.schema import RouteRule
|
|
|
47b589 |
@@ -23,7 +23,7 @@ class RouteRuleEntry(StateEntry):
|
|
|
47b589 |
self.priority = route_rule.get(RouteRule.PRIORITY)
|
|
|
47b589 |
self.route_table = route_rule.get(RouteRule.ROUTE_TABLE)
|
|
|
47b589 |
self._complement_defaults()
|
|
|
47b589 |
- self._append_prefix_length_for_host_only_ip()
|
|
|
47b589 |
+ self._canonicalize_ip_network()
|
|
|
47b589 |
|
|
|
47b589 |
def _complement_defaults(self):
|
|
|
47b589 |
if self.ip_from is None:
|
|
|
47b589 |
@@ -38,11 +38,11 @@ class RouteRuleEntry(StateEntry):
|
|
|
47b589 |
):
|
|
|
47b589 |
self.route_table = KERNEL_MAIN_ROUTE_TABLE_ID
|
|
|
47b589 |
|
|
|
47b589 |
- def _append_prefix_length_for_host_only_ip(self):
|
|
|
47b589 |
- if self.ip_from and "/" not in self.ip_from:
|
|
|
47b589 |
- self.ip_from = to_ip_address_full(self.ip_from)
|
|
|
47b589 |
- if self.ip_to and "/" not in self.ip_to:
|
|
|
47b589 |
- self.ip_to = to_ip_address_full(self.ip_to)
|
|
|
47b589 |
+ def _canonicalize_ip_network(self):
|
|
|
47b589 |
+ if self.ip_from:
|
|
|
47b589 |
+ self.ip_from = canonicalize_ip_network(self.ip_from)
|
|
|
47b589 |
+ if self.ip_to:
|
|
|
47b589 |
+ self.ip_to = canonicalize_ip_network(self.ip_to)
|
|
|
47b589 |
|
|
|
47b589 |
def _keys(self):
|
|
|
47b589 |
return (self.ip_from, self.ip_to, self.priority, self.route_table)
|
|
|
47b589 |
--
|
|
|
47b589 |
2.27.0
|
|
|
47b589 |
|