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
This commit is contained in:
LIU Yulong 2018-07-18 15:28:51 +08:00 committed by Dean Troyer
parent 8be53a50e5
commit fd23025227
3 changed files with 217 additions and 1 deletions

View File

@ -579,6 +579,17 @@ class SetRouter(command.Command):
action='store_true',
help=_("Disable Source NAT on external gateway")
)
qos_policy_group = parser.add_mutually_exclusive_group()
qos_policy_group.add_argument(
'--qos-policy',
metavar='<qos-policy>',
help=_("Attach QoS policy to router gateway IPs")
)
qos_policy_group.add_argument(
'--no-qos-policy',
action='store_true',
help=_("Remove QoS policy from router gateway IPs")
)
_tag.add_tag_option_to_parser_for_set(parser, _('router'))
return parser
@ -638,6 +649,27 @@ class SetRouter(command.Command):
ips.append(ip_spec)
gateway_info['external_fixed_ips'] = ips
attrs['external_gateway_info'] = gateway_info
if ((parsed_args.qos_policy or parsed_args.no_qos_policy) and
not parsed_args.external_gateway):
try:
original_net_id = obj.external_gateway_info['network_id']
except (KeyError, TypeError):
msg = (_("You must specify '--external-gateway' or the router "
"must already have an external network in order to "
"set router gateway IP QoS"))
raise exceptions.CommandError(msg)
else:
if not attrs.get('external_gateway_info'):
attrs['external_gateway_info'] = {}
attrs['external_gateway_info']['network_id'] = original_net_id
if parsed_args.qos_policy:
check_qos_id = client.find_qos_policy(
parsed_args.qos_policy, ignore_missing=False).id
attrs['external_gateway_info']['qos_policy_id'] = check_qos_id
if 'no_qos_policy' in parsed_args and parsed_args.no_qos_policy:
attrs['external_gateway_info']['qos_policy_id'] = None
if attrs:
client.update_router(obj, **attrs)
# tags is a subresource and it needs to be updated separately.
@ -701,6 +733,12 @@ class UnsetRouter(command.Command):
action='store_true',
default=False,
help=_("Remove external gateway information from the router"))
parser.add_argument(
'--qos-policy',
action='store_true',
default=False,
help=_("Remove QoS policy from router gateway IPs")
)
parser.add_argument(
'router',
metavar="<router>",
@ -713,6 +751,7 @@ class UnsetRouter(command.Command):
client = self.app.client_manager.network
obj = client.find_router(parsed_args.router, ignore_missing=False)
tmp_routes = copy.deepcopy(obj.routes)
tmp_external_gateway_info = copy.deepcopy(obj.external_gateway_info)
attrs = {}
if parsed_args.routes:
try:
@ -723,6 +762,20 @@ class UnsetRouter(command.Command):
msg = (_("Router does not contain route %s") % route)
raise exceptions.CommandError(msg)
attrs['routes'] = tmp_routes
if parsed_args.qos_policy:
try:
if (tmp_external_gateway_info['network_id'] and
tmp_external_gateway_info['qos_policy_id']):
pass
except (KeyError, TypeError):
msg = _("Router does not have external network or qos policy")
raise exceptions.CommandError(msg)
else:
attrs['external_gateway_info'] = {
'network_id': tmp_external_gateway_info['network_id'],
'qos_policy_id': None
}
if parsed_args.external_gateway:
attrs['external_gateway_info'] = {}
if attrs:

View File

@ -1113,6 +1113,102 @@ class TestSetRouter(TestRouter):
def test_set_with_no_tag(self):
self._test_set_tags(with_tags=False)
def test_set_gateway_ip_qos(self):
qos_policy = network_fakes.FakeNetworkQosPolicy.create_one_qos_policy()
self.network.find_qos_policy = mock.Mock(return_value=qos_policy)
arglist = [
"--external-gateway", self._network.id,
"--qos-policy", qos_policy.id,
self._router.id,
]
verifylist = [
('router', self._router.id),
('external_gateway', self._network.id),
('qos_policy', qos_policy.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.network.update_router.assert_called_with(
self._router, **{'external_gateway_info': {
'network_id': self._network.id,
'qos_policy_id': qos_policy.id, }})
self.assertIsNone(result)
def test_unset_gateway_ip_qos(self):
arglist = [
"--external-gateway", self._network.id,
"--no-qos-policy",
self._router.id,
]
verifylist = [
('router', self._router.id),
('external_gateway', self._network.id),
('no_qos_policy', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.network.update_router.assert_called_with(
self._router, **{'external_gateway_info': {
'network_id': self._network.id,
'qos_policy_id': None, }})
self.assertIsNone(result)
def test_set_unset_gateway_ip_qos(self):
qos_policy = network_fakes.FakeNetworkQosPolicy.create_one_qos_policy()
self.network.find_qos_policy = mock.Mock(return_value=qos_policy)
arglist = [
"--external-gateway", self._network.id,
"--qos-policy", qos_policy.id,
"--no-qos-policy",
self._router.id,
]
verifylist = [
('router', self._router.id),
('external_gateway', self._network.id),
('qos_policy', qos_policy.id),
('no_qos_policy', True),
]
self.assertRaises(tests_utils.ParserException, self.check_parser,
self.cmd, arglist, verifylist)
def test_set_gateway_ip_qos_no_gateway(self):
qos_policy = network_fakes.FakeNetworkQosPolicy.create_one_qos_policy()
self.network.find_qos_policy = mock.Mock(return_value=qos_policy)
router = network_fakes.FakeRouter.create_one_router()
self.network.find_router = mock.Mock(return_value=router)
arglist = [
"--qos-policy", qos_policy.id,
router.id,
]
verifylist = [
('router', router.id),
('qos_policy', qos_policy.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(exceptions.CommandError,
self.cmd.take_action, parsed_args)
def test_unset_gateway_ip_qos_no_gateway(self):
qos_policy = network_fakes.FakeNetworkQosPolicy.create_one_qos_policy()
self.network.find_qos_policy = mock.Mock(return_value=qos_policy)
router = network_fakes.FakeRouter.create_one_router()
self.network.find_router = mock.Mock(return_value=router)
arglist = [
"--no-qos-policy",
router.id,
]
verifylist = [
('router', router.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(exceptions.CommandError,
self.cmd.take_action, parsed_args)
class TestShowRouter(TestRouter):
@ -1201,12 +1297,19 @@ class TestUnsetRouter(TestRouter):
def setUp(self):
super(TestUnsetRouter, self).setUp()
self.fake_network = network_fakes.FakeNetwork.create_one_network()
self.fake_qos_policy = (
network_fakes.FakeNetworkQosPolicy.create_one_qos_policy())
self._testrouter = network_fakes.FakeRouter.create_one_router(
{'routes': [{"destination": "192.168.101.1/24",
"nexthop": "172.24.4.3"},
{"destination": "192.168.101.2/24",
"nexthop": "172.24.4.3"}],
'tags': ['green', 'red'], })
'tags': ['green', 'red'],
'external_gateway_info': {
'network_id': self.fake_network.id,
'qos_policy_id': self.fake_qos_policy.id
}})
self.fake_subnet = network_fakes.FakeSubnet.create_one_subnet()
self.network.find_router = mock.Mock(return_value=self._testrouter)
self.network.update_router = mock.Mock(return_value=None)
@ -1289,3 +1392,54 @@ class TestUnsetRouter(TestRouter):
def test_unset_with_all_tag(self):
self._test_unset_tags(with_tags=False)
def test_unset_router_qos_policy(self):
arglist = [
'--qos-policy',
self._testrouter.name,
]
verifylist = [
('qos_policy', True)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
attrs = {'external_gateway_info': {"network_id": self.fake_network.id,
"qos_policy_id": None}}
self.network.update_router.assert_called_once_with(
self._testrouter, **attrs)
self.assertIsNone(result)
def test_unset_gateway_ip_qos_no_network(self):
qos_policy = network_fakes.FakeNetworkQosPolicy.create_one_qos_policy()
self.network.find_qos_policy = mock.Mock(return_value=qos_policy)
router = network_fakes.FakeRouter.create_one_router()
self.network.find_router = mock.Mock(return_value=router)
arglist = [
"--qos-policy",
router.id,
]
verifylist = [
('router', router.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(exceptions.CommandError,
self.cmd.take_action, parsed_args)
def test_unset_gateway_ip_qos_no_qos(self):
qos_policy = network_fakes.FakeNetworkQosPolicy.create_one_qos_policy()
self.network.find_qos_policy = mock.Mock(return_value=qos_policy)
router = network_fakes.FakeRouter.create_one_router(
{"external_gateway_info": {"network_id": "fake-id"}})
self.network.find_router = mock.Mock(return_value=router)
arglist = [
"--qos-policy",
router.id,
]
verifylist = [
('router', router.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(exceptions.CommandError,
self.cmd.take_action, parsed_args)

View File

@ -0,0 +1,9 @@
---
features:
- |
Add support for attaching and removing qos policy to router gateway IPs.
Add ``--qos-policy`` and ``--no-qos-policy`` options to the
``router set`` command.
Add ``--qos-policy`` option to the ``router unset`` command.