From 72c9434b65d037858cf319064d519db3e578fd52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89douard=20Thuleau?= Date: Fri, 5 Aug 2016 17:34:13 +0200 Subject: [PATCH] [VNC OpenStack] In port list, apply filters even device_ids filter is defined Divide the port list in two cases: - if device_ids filter: list vmis filtered by ids and [back-]referenced by device_ids then filter that list with project if necessary - if no device_ids filter: list vmis filtered by ids and project owner. After that, the list of vnc vmi objects is transformed to a list of neutron port dicts where last filters (network, device_owner, name and fixed_ips) are applied. Change-Id: I840361304da4a69b819216ceda892519f1b4fddc Closes-Bug: #1607584 --- .../vnc_openstack/neutron_plugin_db.py | 144 ++++++++---------- 1 file changed, 62 insertions(+), 82 deletions(-) diff --git a/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py b/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py index 18cc2f2f09d..8b4e02f10d5 100644 --- a/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py +++ b/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py @@ -102,12 +102,12 @@ def _relay_request(self, request): request.body, {'Content-type': request.environ['CONTENT_TYPE']}) #end _relay_request - def _validate_project_ids(self, context, project_ids): + def _validate_project_ids(self, context=None, project_ids=None): if context and not context['is_admin']: return [context['tenant']] return_project_ids = [] - for project_id in project_ids: + for project_id in project_ids or []: try: return_project_ids.append(str(uuid.UUID(project_id))) except ValueError: @@ -3762,95 +3762,75 @@ def _port_fixed_ips_is_present(self, check, against): @wait_for_api_server_connection def port_list(self, context=None, filters=None): - project_obj = None - ret_q_ports = [] - all_project_ids = [] if not context: context = {'is_admin': True} - # TODO used to find dhcp server field. support later... if (filters.get('device_owner') == 'network:dhcp' or 'network:dhcp' in filters.get('device_owner', [])): - return ret_q_ports - - if not context['is_admin']: - project_id = str(uuid.UUID(context['tenant'])) - else: - project_id = None - - if not 'device_id' in filters: - # Listing from back references - # TODO once vmi is linked to project in schema, use project_id - # to limit scope of list - if 'tenant_id' in filters: - all_project_ids = self._validate_project_ids(context, - filters['tenant_id']) - elif 'name' in filters or 'device_owner' in filters: - all_project_ids = [str(uuid.UUID(context['tenant']))] - elif 'id' in filters: - # TODO optimize - for port_id in filters['id']: - try: - port_obj = self._virtual_machine_interface_read( - port_id=port_id) - port_info = self._port_vnc_to_neutron(port_obj) - except NoIdError: - continue - ret_q_ports.append(port_info) + return [] + + project_ids = self._validate_project_ids(context, + filters.get('tenant_id')) + if not project_ids: + project_ids = None + + port_objs = [] + if filters.get('device_id'): + # Get all VM port + port_objs_filtered_by_device_id =\ + self._virtual_machine_interface_list( + obj_uuids=filters.get('id'), + back_ref_id=filters.get('device_id')) + + # Filter it with project ids if there are. + if project_ids: + port_objs.extend([p for p in port_objs_filtered_by_device_id + if p.parent_uuid in project_ids]) else: - ret_q_ports = self._port_list_project(project_id, - is_admin=context['is_admin']) - - if all_project_ids: - ret_q_ports = [] - for proj_id in all_project_ids: - # Get data from filter tenant-ids - ret_q_ports.extend(self._port_list_project(proj_id)) - - # prune phase - ret_list = [] - for port_obj in ret_q_ports: - if not self._filters_is_present(filters, 'name', - port_obj['name']): - continue - if not self._filters_is_present(filters, 'device_owner', - port_obj["device_owner"]): - continue - if ('fixed_ips' in filters and - not self._port_fixed_ips_is_present(filters['fixed_ips'], - port_obj['fixed_ips'])): - continue - if not self._filters_is_present(filters,'network_id', - port_obj['network_id']): - continue - - ret_list.append(port_obj) - return ret_list - - # Listing from parent to children - - # port has a back_ref to LR, so need to read in LRs based on device id - device_ids = filters['device_id'] - router_objs = self._logical_router_list(obj_uuids=device_ids) - more_ports = [] - for router_obj in router_objs: - intfs = router_obj.get_virtual_machine_interface_refs() - for intf in (intfs or []): - more_ports.append(intf['uuid']) - - # gather all ports from an anchor of virtual-machine (backref in - # current schema and parent in < 1.06 schema) - port_objs = self._virtual_machine_interface_list(parent_id=device_ids, - back_ref_id=device_ids) + port_objs.extend(port_objs_filtered_by_device_id) + + # Port has a back_ref to logical router, so need to read in + # logical routers based on device ids + router_objs = self._logical_router_list( + obj_uuids=filters.get('device_id'), + parent_id=project_ids, + fields=['virtual_machine_interface_back_refs']) + router_port_ids = [ + vmi_ref['uuid'] + for router_obj in router_objs + for vmi_ref in + router_obj.get_virtual_machine_interface_refs() or [] + ] + # Read all logical router ports and add it to the list + if router_port_ids: + port_objs.extend(self._virtual_machine_interface_list( + obj_uuids=router_port_ids, + parent_id=project_ids)) + else: + port_objs = self._virtual_machine_interface_list( + obj_uuids=filters.get('id'), + parent_id=project_ids) - if len(more_ports): - rtr_port_objs = self._virtual_machine_interface_list(obj_uuids=more_ports) - port_objs.extend(rtr_port_objs) + neutron_ports = self._port_list(port_objs) - ret_q_ports = self._port_list(port_objs) + ret_list = [] + for neutron_port in neutron_ports: + if not self._filters_is_present(filters, 'name', + neutron_port['name']): + continue + if not self._filters_is_present(filters, 'device_owner', + neutron_port["device_owner"]): + continue + if ('fixed_ips' in filters and + not self._port_fixed_ips_is_present(filters['fixed_ips'], + neutron_port['fixed_ips'])): + continue + if not self._filters_is_present(filters,'network_id', + neutron_port['network_id']): + continue - return ret_q_ports - #end port_list + ret_list.append(neutron_port) + return ret_list @wait_for_api_server_connection def port_count(self, filters=None):