From e1cbe84fa0b80086a999fdcf5d76621221356308 Mon Sep 17 00:00:00 2001 From: Anton Vazhnetsov Date: Fri, 4 Mar 2022 16:38:23 +0300 Subject: [PATCH] nb: add methods to modify the lrp.networks This change adds functions and commands to modify the 'lrp.networks' column. Closes-Bug: 1963700 Change-Id: I91d8be623dc51d332738728b569bbe4efd65de8d --- ovsdbapp/schema/ovn_northbound/api.py | 27 +++++++++++ ovsdbapp/schema/ovn_northbound/commands.py | 35 ++++++++++++++ ovsdbapp/schema/ovn_northbound/impl_idl.py | 6 +++ .../schema/ovn_northbound/test_impl_idl.py | 46 +++++++++++++++++++ ...p-networks-modifying-1af13589064c12c6.yaml | 4 ++ 5 files changed, 118 insertions(+) create mode 100644 releasenotes/notes/provide-lrp-networks-modifying-1af13589064c12c6.yaml diff --git a/ovsdbapp/schema/ovn_northbound/api.py b/ovsdbapp/schema/ovn_northbound/api.py index 90a9f290..aeb30b79 100644 --- a/ovsdbapp/schema/ovn_northbound/api.py +++ b/ovsdbapp/schema/ovn_northbound/api.py @@ -695,6 +695,33 @@ class API(api.API, metaclass=abc.ABCMeta): :returns: :class:`Command` with no result """ + @abc.abstractmethod + def lrp_add_networks(self, port, networks, may_exist=False): + """Add a network to 'port' + + :param port: The name or uuid of the port + :type port: string or uuid.UUID + :param networks: One or more IP address/netmask to assign to the port + :type networks: list or string + :param may_exist: If True, don't fail if the networks already exists + :type may_exist: boolean + :returns: :class:`Command` with no result + """ + + @abc.abstractmethod + def lrp_del_networks(self, port, networks, if_exists=False): + """Remove a network from 'port' + + :param port: The name or uuid of the port + :type port: string or uuid.UUID + :param networks: One or more IP address/netmask to remove from + the port + :type networks: list or string + :param if_exists: If True, don't fail if the networks doesn't exist + :type if_exists: boolean + :returns: :class:`Command` with no result + """ + @abc.abstractmethod def lr_route_add(self, router, prefix, nexthop, port=None, policy='dst-ip', may_exist=False): diff --git a/ovsdbapp/schema/ovn_northbound/commands.py b/ovsdbapp/schema/ovn_northbound/commands.py index 6c5f32bd..3da12b41 100644 --- a/ovsdbapp/schema/ovn_northbound/commands.py +++ b/ovsdbapp/schema/ovn_northbound/commands.py @@ -1012,6 +1012,41 @@ class LrpDelGatewayChassisCommand(cmd.BaseCommand): raise RuntimeError(msg) +class _LrpNetworksCommand(cmd.BaseCommand): + table = 'Logical_Router_Port' + + def __init__(self, api, port, networks, exists): + super().__init__(api) + self.port = port + self.exists = exists + if isinstance(networks, (str, bytes)): + networks = [networks] + self.networks = [str(netaddr.IPNetwork(network)) + for network in networks] + + +class LrpAddNetworksCommand(_LrpNetworksCommand): + def run_idl(self, txn): + lrp = self.api.lookup(self.table, self.port) + for network in self.networks: + if network in lrp.networks and not self.exists: + msg = "Network '%s' already exist in networks of port %s" % ( + network, lrp.uuid) + raise RuntimeError(msg) + lrp.addvalue('networks', network) + + +class LrpDelNetworksCommand(_LrpNetworksCommand): + def run_idl(self, txn): + lrp = self.api.lookup(self.table, self.port) + for network in self.networks: + if network not in lrp.networks and not self.exists: + msg = "Network '%s' does not exist in networks of port %s" % ( + network, lrp.uuid) + raise RuntimeError(msg) + lrp.delvalue('networks', network) + + class LrRouteAddCommand(cmd.BaseCommand): def __init__(self, api, router, prefix, nexthop, port=None, policy='dst-ip', may_exist=False): diff --git a/ovsdbapp/schema/ovn_northbound/impl_idl.py b/ovsdbapp/schema/ovn_northbound/impl_idl.py index 980ced64..3f958545 100644 --- a/ovsdbapp/schema/ovn_northbound/impl_idl.py +++ b/ovsdbapp/schema/ovn_northbound/impl_idl.py @@ -226,6 +226,12 @@ class OvnNbApiIdlImpl(ovs_idl.Backend, api.API): return cmd.LrpDelGatewayChassisCommand(self, port, gateway_chassis, if_exists) + def lrp_add_networks(self, port, networks, may_exist=False): + return cmd.LrpAddNetworksCommand(self, port, networks, may_exist) + + def lrp_del_networks(self, port, networks, if_exists=False): + return cmd.LrpDelNetworksCommand(self, port, networks, if_exists) + def lr_route_add(self, router, prefix, nexthop, port=None, policy='dst-ip', may_exist=False): return cmd.LrRouteAddCommand(self, router, prefix, nexthop, port, diff --git a/ovsdbapp/tests/functional/schema/ovn_northbound/test_impl_idl.py b/ovsdbapp/tests/functional/schema/ovn_northbound/test_impl_idl.py index 820b5e40..1890f28d 100644 --- a/ovsdbapp/tests/functional/schema/ovn_northbound/test_impl_idl.py +++ b/ovsdbapp/tests/functional/schema/ovn_northbound/test_impl_idl.py @@ -1551,6 +1551,52 @@ class TestLogicalRouterPortOps(OvnNorthboundTest): lrp.uuid, "fake_chassis", if_exists=True ).execute(check_error=True) + def test_lrp_add_del_network(self): + networks = ['10.0.0.0/24'] + new_networks = ['172.31.0.0/24', '172.31.1.0/24'] + lrp = self._lrp_add(None, networks=networks) + + self.api.lrp_add_networks(lrp.name, + new_networks).execute(check_error=True) + self.assertEqual(lrp.networks, networks + new_networks) + + self.api.lrp_del_networks(lrp.name, + new_networks).execute(check_error=True) + self.assertEqual(lrp.networks, networks) + + def test_lrp_add_del_network_by_str(self): + networks = ['10.0.0.0/24'] + new_network = '172.31.0.0/24' + lrp = self._lrp_add(None, networks=networks) + + self.api.lrp_add_networks(lrp.name, + new_network).execute(check_error=True) + self.assertEqual(lrp.networks, networks + [new_network]) + + self.api.lrp_del_networks(lrp.name, + new_network).execute(check_error=True) + self.assertEqual(lrp.networks, networks) + + def test_lrp_add_del_network_negative(self): + networks = ['10.0.0.0/24'] + no_existing_network = '192.168.0.0/24' + lrp = self._lrp_add(None, networks=networks) + + cmd = self.api.lrp_add_networks(lrp.name, networks) + self.assertRaises(RuntimeError, cmd.execute, check_error=True) + + cmd = self.api.lrp_del_networks(lrp.name, no_existing_network) + self.assertRaises(RuntimeError, cmd.execute, check_error=True) + + for new_net in ["fake", ["10.0.1.0/24", "fake"]]: + self.assertRaises(netaddr.AddrFormatError, + self.api.lrp_add_networks, lrp.name, new_net) + self.assertEqual(lrp.networks, networks) + + self.assertRaises(netaddr.AddrFormatError, + self.api.lrp_del_networks, lrp.name, new_net) + self.assertEqual(lrp.networks, networks) + class TestLoadBalancerOps(OvnNorthboundTest): diff --git a/releasenotes/notes/provide-lrp-networks-modifying-1af13589064c12c6.yaml b/releasenotes/notes/provide-lrp-networks-modifying-1af13589064c12c6.yaml new file mode 100644 index 00000000..a97f8aa6 --- /dev/null +++ b/releasenotes/notes/provide-lrp-networks-modifying-1af13589064c12c6.yaml @@ -0,0 +1,4 @@ +--- +features: + - | + Added functions and commands to modify the 'lrp.networks' column.