Skip to content

Commit

Permalink
[VNC OpenStack] In port list, apply filters even device_ids filter is…
Browse files Browse the repository at this point in the history
… 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
  • Loading branch information
Édouard Thuleau committed Aug 11, 2016
1 parent 492e560 commit 72c9434
Showing 1 changed file with 62 additions and 82 deletions.
144 changes: 62 additions & 82 deletions src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py
Expand Up @@ -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:
Expand Down Expand Up @@ -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):
Expand Down

0 comments on commit 72c9434

Please sign in to comment.