Skip to content

Commit fd23025

Browse files
gotostackDean Troyer
authored andcommitted
Supports router gateway IP QoS
Adds --qos-policy and --no-qos-policy to `openstack router set`: --qos-policy <qos-policy> Attach QoS policy to router gateway IPs --no-qos-policy Remove QoS policy from router gateway IPs Adds --qos-policy to `openstack router unset`: --qos-policy Remove QoS policy from router gateway IPs Partially-Implements blueprint: router-gateway-ip-qos Closes-Bug: #1757044 Change-Id: Ifec3b2cf9bdb59513c8bcd7bd60305506a071192
1 parent 8be53a5 commit fd23025

3 files changed

Lines changed: 217 additions & 1 deletion

File tree

openstackclient/network/v2/router.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,17 @@ def get_parser(self, prog_name):
579579
action='store_true',
580580
help=_("Disable Source NAT on external gateway")
581581
)
582+
qos_policy_group = parser.add_mutually_exclusive_group()
583+
qos_policy_group.add_argument(
584+
'--qos-policy',
585+
metavar='<qos-policy>',
586+
help=_("Attach QoS policy to router gateway IPs")
587+
)
588+
qos_policy_group.add_argument(
589+
'--no-qos-policy',
590+
action='store_true',
591+
help=_("Remove QoS policy from router gateway IPs")
592+
)
582593
_tag.add_tag_option_to_parser_for_set(parser, _('router'))
583594
return parser
584595

@@ -638,6 +649,27 @@ def take_action(self, parsed_args):
638649
ips.append(ip_spec)
639650
gateway_info['external_fixed_ips'] = ips
640651
attrs['external_gateway_info'] = gateway_info
652+
653+
if ((parsed_args.qos_policy or parsed_args.no_qos_policy) and
654+
not parsed_args.external_gateway):
655+
try:
656+
original_net_id = obj.external_gateway_info['network_id']
657+
except (KeyError, TypeError):
658+
msg = (_("You must specify '--external-gateway' or the router "
659+
"must already have an external network in order to "
660+
"set router gateway IP QoS"))
661+
raise exceptions.CommandError(msg)
662+
else:
663+
if not attrs.get('external_gateway_info'):
664+
attrs['external_gateway_info'] = {}
665+
attrs['external_gateway_info']['network_id'] = original_net_id
666+
if parsed_args.qos_policy:
667+
check_qos_id = client.find_qos_policy(
668+
parsed_args.qos_policy, ignore_missing=False).id
669+
attrs['external_gateway_info']['qos_policy_id'] = check_qos_id
670+
671+
if 'no_qos_policy' in parsed_args and parsed_args.no_qos_policy:
672+
attrs['external_gateway_info']['qos_policy_id'] = None
641673
if attrs:
642674
client.update_router(obj, **attrs)
643675
# tags is a subresource and it needs to be updated separately.
@@ -701,6 +733,12 @@ def get_parser(self, prog_name):
701733
action='store_true',
702734
default=False,
703735
help=_("Remove external gateway information from the router"))
736+
parser.add_argument(
737+
'--qos-policy',
738+
action='store_true',
739+
default=False,
740+
help=_("Remove QoS policy from router gateway IPs")
741+
)
704742
parser.add_argument(
705743
'router',
706744
metavar="<router>",
@@ -713,6 +751,7 @@ def take_action(self, parsed_args):
713751
client = self.app.client_manager.network
714752
obj = client.find_router(parsed_args.router, ignore_missing=False)
715753
tmp_routes = copy.deepcopy(obj.routes)
754+
tmp_external_gateway_info = copy.deepcopy(obj.external_gateway_info)
716755
attrs = {}
717756
if parsed_args.routes:
718757
try:
@@ -723,6 +762,20 @@ def take_action(self, parsed_args):
723762
msg = (_("Router does not contain route %s") % route)
724763
raise exceptions.CommandError(msg)
725764
attrs['routes'] = tmp_routes
765+
if parsed_args.qos_policy:
766+
try:
767+
if (tmp_external_gateway_info['network_id'] and
768+
tmp_external_gateway_info['qos_policy_id']):
769+
pass
770+
except (KeyError, TypeError):
771+
msg = _("Router does not have external network or qos policy")
772+
raise exceptions.CommandError(msg)
773+
else:
774+
attrs['external_gateway_info'] = {
775+
'network_id': tmp_external_gateway_info['network_id'],
776+
'qos_policy_id': None
777+
}
778+
726779
if parsed_args.external_gateway:
727780
attrs['external_gateway_info'] = {}
728781
if attrs:

openstackclient/tests/unit/network/v2/test_router.py

Lines changed: 155 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,102 @@ def test_set_with_tags(self):
11131113
def test_set_with_no_tag(self):
11141114
self._test_set_tags(with_tags=False)
11151115

1116+
def test_set_gateway_ip_qos(self):
1117+
qos_policy = network_fakes.FakeNetworkQosPolicy.create_one_qos_policy()
1118+
self.network.find_qos_policy = mock.Mock(return_value=qos_policy)
1119+
arglist = [
1120+
"--external-gateway", self._network.id,
1121+
"--qos-policy", qos_policy.id,
1122+
self._router.id,
1123+
]
1124+
verifylist = [
1125+
('router', self._router.id),
1126+
('external_gateway', self._network.id),
1127+
('qos_policy', qos_policy.id),
1128+
]
1129+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
1130+
1131+
result = self.cmd.take_action(parsed_args)
1132+
self.network.update_router.assert_called_with(
1133+
self._router, **{'external_gateway_info': {
1134+
'network_id': self._network.id,
1135+
'qos_policy_id': qos_policy.id, }})
1136+
self.assertIsNone(result)
1137+
1138+
def test_unset_gateway_ip_qos(self):
1139+
arglist = [
1140+
"--external-gateway", self._network.id,
1141+
"--no-qos-policy",
1142+
self._router.id,
1143+
]
1144+
verifylist = [
1145+
('router', self._router.id),
1146+
('external_gateway', self._network.id),
1147+
('no_qos_policy', True),
1148+
]
1149+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
1150+
1151+
result = self.cmd.take_action(parsed_args)
1152+
self.network.update_router.assert_called_with(
1153+
self._router, **{'external_gateway_info': {
1154+
'network_id': self._network.id,
1155+
'qos_policy_id': None, }})
1156+
self.assertIsNone(result)
1157+
1158+
def test_set_unset_gateway_ip_qos(self):
1159+
qos_policy = network_fakes.FakeNetworkQosPolicy.create_one_qos_policy()
1160+
self.network.find_qos_policy = mock.Mock(return_value=qos_policy)
1161+
arglist = [
1162+
"--external-gateway", self._network.id,
1163+
"--qos-policy", qos_policy.id,
1164+
"--no-qos-policy",
1165+
self._router.id,
1166+
]
1167+
verifylist = [
1168+
('router', self._router.id),
1169+
('external_gateway', self._network.id),
1170+
('qos_policy', qos_policy.id),
1171+
('no_qos_policy', True),
1172+
]
1173+
1174+
self.assertRaises(tests_utils.ParserException, self.check_parser,
1175+
self.cmd, arglist, verifylist)
1176+
1177+
def test_set_gateway_ip_qos_no_gateway(self):
1178+
qos_policy = network_fakes.FakeNetworkQosPolicy.create_one_qos_policy()
1179+
self.network.find_qos_policy = mock.Mock(return_value=qos_policy)
1180+
router = network_fakes.FakeRouter.create_one_router()
1181+
self.network.find_router = mock.Mock(return_value=router)
1182+
arglist = [
1183+
"--qos-policy", qos_policy.id,
1184+
router.id,
1185+
]
1186+
verifylist = [
1187+
('router', router.id),
1188+
('qos_policy', qos_policy.id),
1189+
]
1190+
1191+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
1192+
self.assertRaises(exceptions.CommandError,
1193+
self.cmd.take_action, parsed_args)
1194+
1195+
def test_unset_gateway_ip_qos_no_gateway(self):
1196+
qos_policy = network_fakes.FakeNetworkQosPolicy.create_one_qos_policy()
1197+
self.network.find_qos_policy = mock.Mock(return_value=qos_policy)
1198+
router = network_fakes.FakeRouter.create_one_router()
1199+
self.network.find_router = mock.Mock(return_value=router)
1200+
arglist = [
1201+
"--no-qos-policy",
1202+
router.id,
1203+
]
1204+
verifylist = [
1205+
('router', router.id),
1206+
]
1207+
1208+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
1209+
self.assertRaises(exceptions.CommandError,
1210+
self.cmd.take_action, parsed_args)
1211+
11161212

11171213
class TestShowRouter(TestRouter):
11181214

@@ -1201,12 +1297,19 @@ class TestUnsetRouter(TestRouter):
12011297

12021298
def setUp(self):
12031299
super(TestUnsetRouter, self).setUp()
1300+
self.fake_network = network_fakes.FakeNetwork.create_one_network()
1301+
self.fake_qos_policy = (
1302+
network_fakes.FakeNetworkQosPolicy.create_one_qos_policy())
12041303
self._testrouter = network_fakes.FakeRouter.create_one_router(
12051304
{'routes': [{"destination": "192.168.101.1/24",
12061305
"nexthop": "172.24.4.3"},
12071306
{"destination": "192.168.101.2/24",
12081307
"nexthop": "172.24.4.3"}],
1209-
'tags': ['green', 'red'], })
1308+
'tags': ['green', 'red'],
1309+
'external_gateway_info': {
1310+
'network_id': self.fake_network.id,
1311+
'qos_policy_id': self.fake_qos_policy.id
1312+
}})
12101313
self.fake_subnet = network_fakes.FakeSubnet.create_one_subnet()
12111314
self.network.find_router = mock.Mock(return_value=self._testrouter)
12121315
self.network.update_router = mock.Mock(return_value=None)
@@ -1289,3 +1392,54 @@ def test_unset_with_tags(self):
12891392

12901393
def test_unset_with_all_tag(self):
12911394
self._test_unset_tags(with_tags=False)
1395+
1396+
def test_unset_router_qos_policy(self):
1397+
arglist = [
1398+
'--qos-policy',
1399+
self._testrouter.name,
1400+
]
1401+
verifylist = [
1402+
('qos_policy', True)
1403+
]
1404+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
1405+
result = self.cmd.take_action(parsed_args)
1406+
attrs = {'external_gateway_info': {"network_id": self.fake_network.id,
1407+
"qos_policy_id": None}}
1408+
self.network.update_router.assert_called_once_with(
1409+
self._testrouter, **attrs)
1410+
self.assertIsNone(result)
1411+
1412+
def test_unset_gateway_ip_qos_no_network(self):
1413+
qos_policy = network_fakes.FakeNetworkQosPolicy.create_one_qos_policy()
1414+
self.network.find_qos_policy = mock.Mock(return_value=qos_policy)
1415+
router = network_fakes.FakeRouter.create_one_router()
1416+
self.network.find_router = mock.Mock(return_value=router)
1417+
arglist = [
1418+
"--qos-policy",
1419+
router.id,
1420+
]
1421+
verifylist = [
1422+
('router', router.id),
1423+
]
1424+
1425+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
1426+
self.assertRaises(exceptions.CommandError,
1427+
self.cmd.take_action, parsed_args)
1428+
1429+
def test_unset_gateway_ip_qos_no_qos(self):
1430+
qos_policy = network_fakes.FakeNetworkQosPolicy.create_one_qos_policy()
1431+
self.network.find_qos_policy = mock.Mock(return_value=qos_policy)
1432+
router = network_fakes.FakeRouter.create_one_router(
1433+
{"external_gateway_info": {"network_id": "fake-id"}})
1434+
self.network.find_router = mock.Mock(return_value=router)
1435+
arglist = [
1436+
"--qos-policy",
1437+
router.id,
1438+
]
1439+
verifylist = [
1440+
('router', router.id),
1441+
]
1442+
1443+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
1444+
self.assertRaises(exceptions.CommandError,
1445+
self.cmd.take_action, parsed_args)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
features:
3+
- |
4+
Add support for attaching and removing qos policy to router gateway IPs.
5+
6+
Add ``--qos-policy`` and ``--no-qos-policy`` options to the
7+
``router set`` command.
8+
9+
Add ``--qos-policy`` option to the ``router unset`` command.

0 commit comments

Comments
 (0)