From ad9f46284461233f4334e7518f10259ece8117ec Mon Sep 17 00:00:00 2001 From: Anton Vazhnetsov Date: Tue, 26 Oct 2021 16:29:59 +0300 Subject: [PATCH] nb: add support for lrp's gateway chassis API This change adds functions and commands to add, delete and list gateway chassis of logical router port. Closes-Bug: #1948974 Change-Id: I1361673719a67a053b30d8852777ac20f4429ddd --- ovsdbapp/schema/ovn_northbound/api.py | 37 ++++++++++++++ ovsdbapp/schema/ovn_northbound/commands.py | 47 ++++++++++++++++++ ovsdbapp/schema/ovn_northbound/impl_idl.py | 11 +++++ .../schema/ovn_northbound/test_impl_idl.py | 49 +++++++++++++++++++ ...-gateway-chassis-api-14e2948183f60cfa.yaml | 4 ++ 5 files changed, 148 insertions(+) create mode 100644 releasenotes/notes/provide-lrp-gateway-chassis-api-14e2948183f60cfa.yaml diff --git a/ovsdbapp/schema/ovn_northbound/api.py b/ovsdbapp/schema/ovn_northbound/api.py index 6a6f4b6b..5f74b191 100644 --- a/ovsdbapp/schema/ovn_northbound/api.py +++ b/ovsdbapp/schema/ovn_northbound/api.py @@ -587,6 +587,43 @@ class API(api.API, metaclass=abc.ABCMeta): :returns: :class:`Command` with dict result """ + @abc.abstractmethod + def lrp_set_gateway_chassis(self, port, gateway_chassis, priority=0): + """Set gateway chassis for 'port' + + :param port: The name or uuid of the port + :type port: string or uuid.UUID + :param gateway_chassis: The name of the gateway chassis + :type gateway_chassis: string + :param priority: The priority of the gateway chassis + :type priority: int + :returns: :class:`Command` with no result + """ + + @abc.abstractmethod + def lrp_get_gateway_chassis(self, port): + """Get the names of all gateway chassis on 'port' + + :param port: The name or uuid of the port + :type port: string or uuid.UUID + :type port: int + :returns: :class:`Command` with RowView list result + """ + + @abc.abstractmethod + def lrp_del_gateway_chassis(self, port, gateway_chassis, if_exists=False): + """Delete gateway chassis from 'port' + + :param port: The name or uuid of the port + :type port: string or uuid.UUID + :param gateway_chassis: The name of the gateway chassis + :type gateway_chassis: string + :param if_exists: If True, don't fail if the gateway chassis + 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 979c593d..05e6e965 100644 --- a/ovsdbapp/schema/ovn_northbound/commands.py +++ b/ovsdbapp/schema/ovn_northbound/commands.py @@ -845,6 +845,53 @@ class LrpGetOptionsCommand(LspGetOptionsCommand): table = 'Logical_Router_Port' +class LrpSetGatewayChassisCommand(cmd.BaseCommand): + table = 'Logical_Router_Port' + + def __init__(self, api, port, gateway_chassis, priority): + super().__init__(api) + self.port = port + self.gateway_chassis = gateway_chassis + self.priority = priority + + def run_idl(self, txn): + lrp = self.api.lookup(self.table, self.port) + gwc_name = '%s_%s' % (lrp.name, self.gateway_chassis) + cmd = GatewayChassisAddCommand(self.api, gwc_name, + self.gateway_chassis, + self.priority, may_exist=True) + cmd.run_idl(txn) + lrp.addvalue('gateway_chassis', cmd.result) + + +class LrpGetGatewayChassisCommand(LrpGetOptionsCommand): + def run_idl(self, txn): + lrp = self.api.lookup(self.table, self.port) + self.result = [rowview.RowView(d) for d in lrp.gateway_chassis] + + +class LrpDelGatewayChassisCommand(cmd.BaseCommand): + table = 'Logical_Router_Port' + + def __init__(self, api, port, gateway_chassis, if_exists=False): + super().__init__(api) + self.port = port + self.gateway_chassis = gateway_chassis + self.if_exists = if_exists + + def run_idl(self, txn): + lrp = self.api.lookup(self.table, self.port) + for gwc in lrp.gateway_chassis: + if gwc.chassis_name == self.gateway_chassis: + lrp.delvalue('gateway_chassis', gwc) + return + + if not self.if_exists: + msg = "Gateway chassis '%s' on port %s does not exist" % ( + self.gateway_chassis, self.port) + raise RuntimeError(msg) + + 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 1254df5f..b8a8ab3e 100644 --- a/ovsdbapp/schema/ovn_northbound/impl_idl.py +++ b/ovsdbapp/schema/ovn_northbound/impl_idl.py @@ -192,6 +192,17 @@ class OvnNbApiIdlImpl(ovs_idl.Backend, api.API): def lrp_get_options(self, port): return cmd.LrpGetOptionsCommand(self, port) + def lrp_set_gateway_chassis(self, port, gateway_chassis, priority=0): + return cmd.LrpSetGatewayChassisCommand(self, + port, gateway_chassis, priority) + + def lrp_get_gateway_chassis(self, port): + return cmd.LrpGetGatewayChassisCommand(self, port) + + def lrp_del_gateway_chassis(self, port, gateway_chassis, if_exists=False): + return cmd.LrpDelGatewayChassisCommand(self, port, + gateway_chassis, 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 d4562a40..fe6ffd0b 100644 --- a/ovsdbapp/tests/functional/schema/ovn_northbound/test_impl_idl.py +++ b/ovsdbapp/tests/functional/schema/ovn_northbound/test_impl_idl.py @@ -1292,6 +1292,55 @@ class TestLogicalRouterPortOps(OvnNorthboundTest): self.assertEqual(options, self.api.lrp_get_options(lrp.uuid).execute( check_error=True)) + def test_lrp_get_set_gateway_chassis(self): + lrp = self._lrp_add(None) + c1_name = utils.get_rand_device_name() + self.api.lrp_set_gateway_chassis(lrp.uuid, c1_name).execute( + check_error=True) + c1 = self.api.lookup('Gateway_Chassis', "%s_%s" % (lrp.name, c1_name)) + lrp_gwcs = self.api.lrp_get_gateway_chassis(lrp.uuid).execute( + check_error=True) + self.assertIn(c1, lrp_gwcs) + self.assertEqual(c1.name, "%s_%s" % (lrp.name, c1_name)) + self.assertEqual(c1.chassis_name, c1_name) + self.assertEqual(c1.priority, 0) + + def test_lrp_set_multiple_gwc(self): + lrp = self._lrp_add(None) + c1_name, c2_name = [utils.get_rand_device_name() for _ in range(2)] + for gwc in [c1_name, c2_name]: + self.api.lrp_set_gateway_chassis(lrp.uuid, gwc).execute( + check_error=True) + c1 = self.api.lookup('Gateway_Chassis', "%s_%s" % (lrp.name, c1_name)) + c2 = self.api.lookup('Gateway_Chassis', "%s_%s" % (lrp.name, c2_name)) + lrp_gwcs = self.api.lrp_get_gateway_chassis(lrp.uuid).execute( + check_error=True) + self.assertIn(c1, lrp_gwcs) + self.assertIn(c2, lrp_gwcs) + + def test_lrp_del_gateway_chassis(self): + c1_name = utils.get_rand_device_name() + lrp = self._lrp_add(None, gateway_chassis=[c1_name]) + c1 = self.api.lookup('Gateway_Chassis', "%s_%s" % (lrp.name, c1_name)) + self.assertEqual(lrp.gateway_chassis, [c1]) + self.api.lrp_del_gateway_chassis(lrp.uuid, c1_name).execute( + check_error=True) + self.assertEqual(lrp.gateway_chassis, []) + self.assertRaises(idlutils.RowNotFound, + self.api.lookup, + 'Gateway_Chassis', "%s_%s" % (lrp.name, c1_name)) + + def test_lrp_del_gateway_chassis_wrong_chassis(self): + lrp = self._lrp_add(None) + cmd = self.api.lrp_del_gateway_chassis(lrp.uuid, "fake_chassis") + self.assertRaises(RuntimeError, cmd.execute, check_error=True) + + def test_lrp_del_gateway_chassis_if_exist(self): + lrp = self._lrp_add(None) + self.api.lrp_del_gateway_chassis( + lrp.uuid, "fake_chassis", if_exists=True + ).execute(check_error=True) + class TestLoadBalancerOps(OvnNorthboundTest): diff --git a/releasenotes/notes/provide-lrp-gateway-chassis-api-14e2948183f60cfa.yaml b/releasenotes/notes/provide-lrp-gateway-chassis-api-14e2948183f60cfa.yaml new file mode 100644 index 00000000..fefb60fe --- /dev/null +++ b/releasenotes/notes/provide-lrp-gateway-chassis-api-14e2948183f60cfa.yaml @@ -0,0 +1,4 @@ +--- +features: + - | + Added functions and commands to add, delete and list gateway chassis of logical router port.