From d982c180c4bf5fb2413b11b84002283d5825afb4 Mon Sep 17 00:00:00 2001 From: ansao-aci Date: Wed, 23 Sep 2020 22:33:13 +0530 Subject: [PATCH] Endpoint level qos changes. Get_endpoint_details rpc is modified to return qos config for an ep. Change-Id: I7ac94ad0140203d92c8834c84f40d6b28e8c753f (cherry picked from commit 8656bae4b4501342a3925a3c8307bdbb0076792d) --- .../plugins/ml2plus/drivers/apic_aim/rpc.py | 39 +++++++++++++++++++ .../unit/services/qos/test_aim_qos_driver.py | 21 +++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/gbpservice/neutron/plugins/ml2plus/drivers/apic_aim/rpc.py b/gbpservice/neutron/plugins/ml2plus/drivers/apic_aim/rpc.py index c3d5a0772..6e415110a 100644 --- a/gbpservice/neutron/plugins/ml2plus/drivers/apic_aim/rpc.py +++ b/gbpservice/neutron/plugins/ml2plus/drivers/apic_aim/rpc.py @@ -26,6 +26,7 @@ from neutron.db.models import securitygroup as sg_models from neutron.db.models import segment as segment_models from neutron.db import models_v2 from neutron.db.port_security import models as psec_models +from neutron.db.qos import models as qos_models from neutron.plugins.ml2 import models as ml2_models from neutron.services.trunk import models as trunk_models from neutron_lib.api.definitions import portbindings @@ -104,6 +105,11 @@ EndpointSecurityGroupInfo = namedtuple( ['sg_id', 'project_id']) +EndpointQosInfo = namedtuple( + 'EndpointQosInfo', + ['qos_id', + 'project_id']) + EndpointDhcpIpInfo = namedtuple( 'EndpointDhcpIpInfo', ['mac_address', @@ -151,6 +157,10 @@ EndpointTrunkInfo = namedtuple( 'segmentation_type', 'segmentation_id']) +NEUTRON_INTERNAL_PORTS = (n_constants.DEVICE_OWNER_DHCP, + n_constants.DEVICE_OWNER_ROUTER_INTF, + n_constants.DEVICE_OWNER_ROUTER_GW) + class TopologyRpcEndpoint(object): @@ -365,6 +375,12 @@ class ApicRpcHandlerMixin(object): info['sg_info'] = self._query_endpoint_sg_info( session, port_info.port_id) + # Query for port's qos policy + info['qos_info'] = [] + if port_info.device_owner not in NEUTRON_INTERNAL_PORTS: + info['qos_info'] = self._query_endpoint_qos_info( + session, port_info.port_id) + # Query for list of state associated with each # DHCP IP on the port's network. info['dhcp_ip_info'] = self._query_endpoint_dhcp_ip_info( @@ -608,6 +624,22 @@ class ApicRpcHandlerMixin(object): query(session).params( port_id=port_id)] + def _query_endpoint_qos_info(self, session, port_id): + query = BAKERY(lambda s: s.query( + qos_models.QosPolicy.id, + qos_models.QosPolicy.project_id, + )) + query += lambda q: q.join( + qos_models.QosPortPolicyBinding, + qos_models.QosPortPolicyBinding.policy_id == + qos_models.QosPolicy.id) + query += lambda q: q.filter( + qos_models.QosPortPolicyBinding.port_id == + sa.bindparam('port_id')) + return [EndpointQosInfo._make(row) for row in + query(session).params( + port_id=port_id)] + def _query_endpoint_dhcp_ip_info(self, session, network_id): query = BAKERY(lambda s: s.query( models_v2.Port.mac_address, @@ -938,6 +970,8 @@ class ApicRpcHandlerMixin(object): if not (vif_details and vif_details.get('port_filter') and vif_details.get('ovs_hybrid_plug')): details['security_group'] = self._build_sg_details(info) + if info['qos_info']: + details['qos_policy'] = self._build_qos_details(info) details['subnets'] = self._build_subnet_details(info) details['vm-name'] = (port_info.vm_name if port_info.device_owner.startswith('compute:') and @@ -1077,6 +1111,11 @@ class ApicRpcHandlerMixin(object): 'name': sg.sg_id} for sg in info['sg_info']] + [{'policy-space': 'common', 'name': self._default_sg_name}]) + def _build_qos_details(self, info): + return ( + [{'policy-space': self.name_mapper.project(None, qos.project_id), + 'name': qos.qos_id} for qos in info['qos_info']][0]) + def _build_subnet_details(self, info): ip_info = info['ip_info'] dhcp_ip_info = info['dhcp_ip_info'] diff --git a/gbpservice/neutron/tests/unit/services/qos/test_aim_qos_driver.py b/gbpservice/neutron/tests/unit/services/qos/test_aim_qos_driver.py index e8efec1b1..9f27adbd3 100644 --- a/gbpservice/neutron/tests/unit/services/qos/test_aim_qos_driver.py +++ b/gbpservice/neutron/tests/unit/services/qos/test_aim_qos_driver.py @@ -15,9 +15,10 @@ import mock # from aim.api import infra as aim_infra from aim.api import resource as aim_res +from gbpservice.neutron.tests.unit.plugins.ml2plus import ( + test_apic_aim as test_aim_md) from gbpservice.neutron.tests.unit.services.grouppolicy import ( test_aim_mapping_driver as test_aim_base) - from neutron.objects.qos import policy as policy_object from neutron.objects.qos import rule as rule_object from neutron_lib import context @@ -46,6 +47,7 @@ class TestAIMQosBase(test_aim_base.AIMBaseTestCase): super(TestAIMQosBase, self).setUp( *args, ml2_options=ml2_options, qos_plugin='qos', **kwargs) self._plugin = directory.get_plugin() + self.plugin = self._plugin self._plugin.remove_networks_from_down_agents = mock.Mock() self._plugin.is_agent_down = mock.Mock(return_value=False) self._ctx = context.get_admin_context() @@ -185,6 +187,23 @@ class TestQosPolicy(TestAIMQosBase): epg = self.aim_mgr.get(self._aim_context, epg) self.assertIsNone(epg.qos_name) + def test_port_qos_gbpDetailsForML2(self): + self._register_agent('host1', test_aim_md.AGENT_CONF_OPFLEX) + net = self._make_network(self.fmt, 'net1', True) + self._make_subnet(self.fmt, net, '10.0.1.1', '10.0.1.0/24') + qosPolicy = self._make_qos_policy() + qosPort = self._make_port(self.fmt, + net['network']['id'], + None, arg_list=('qos_policy_id',), + qos_policy_id=qosPolicy.id) + self._bind_port_to_host(qosPort['port']['id'], 'host1') + + mapping = self.aim_mech.get_gbp_details( + self._neutron_admin_context, + device='tap%s' % qosPort['port']['id'], + host='host1') + self.assertEqual(qosPolicy.id, mapping['qos_policy']['name']) + def _test_invalid_network_exception(self, kwargs): # Verify creating network with QoS fails net_qos_obj = self._make_qos_policy()