Add neutron subnets and routers
Adds subnets and routers to supported neutron resources, in addition to the networks and ports already merged. Subnets are configured as a child plugin to networks; routers are independent. This adds a listener for router.interface events on the Ports handler because no separate notifications are received for those events. Change-Id: If8efa7033bc99bebbea4e5b7564fc9ed150dbb37 Implements: blueprint neutron-subnet-router
This commit is contained in:
parent
8adf00a64b
commit
5efb890ca4
|
@ -53,12 +53,26 @@ Plugin: OS::Neutron::Port
|
||||||
[resource_plugin:os_neutron_port]
|
[resource_plugin:os_neutron_port]
|
||||||
enabled = true
|
enabled = true
|
||||||
|
|
||||||
|
Plugin: OS::Neutron::Subnet
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
::
|
||||||
|
|
||||||
|
[resource_plugin:os_neutron_subnet]
|
||||||
|
enabled = true
|
||||||
|
|
||||||
|
Plugin: OS::Neutron::Router
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
::
|
||||||
|
|
||||||
|
[resource_plugin:os_neutron_router]
|
||||||
|
enabled = true
|
||||||
|
|
||||||
Neutron Configuration
|
Neutron Configuration
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
Neutron sends notifications on create/update/delete actions on the
|
Neutron sends notifications on create/update/delete actions on the
|
||||||
concepts that it implements. Currently Searchlight supports indexing
|
concepts that it implements. Currently Searchlight supports indexing
|
||||||
for networks and ports, with subnets and routers to follow.
|
for networks, subnets, ports and routers.
|
||||||
|
|
||||||
neutron.conf
|
neutron.conf
|
||||||
------------
|
------------
|
||||||
|
@ -92,6 +106,8 @@ Release Notes
|
||||||
|
|
||||||
All provider:* properties of networks are exposed to administrators only.
|
All provider:* properties of networks are exposed to administrators only.
|
||||||
All binding:* properties of ports are also visible only to administrators.
|
All binding:* properties of ports are also visible only to administrators.
|
||||||
|
The 'distributed' and 'ha' router properties are available only to
|
||||||
|
administrators.
|
||||||
|
|
||||||
Additional properties can be protected similarly with the `admin_only_fields`
|
Additional properties can be protected similarly with the `admin_only_fields`
|
||||||
under each plugin's configuration section. Glob-like patterns are supported.
|
under each plugin's configuration section. Glob-like patterns are supported.
|
||||||
|
@ -103,3 +119,4 @@ For instance::
|
||||||
See: ADMIN_ONLY_FIELDS in:
|
See: ADMIN_ONLY_FIELDS in:
|
||||||
* searchlight/elasticsearch/plugins/neutron/networks.py
|
* searchlight/elasticsearch/plugins/neutron/networks.py
|
||||||
* searchlight/elasticsearch/plugins/neutron/ports.py
|
* searchlight/elasticsearch/plugins/neutron/ports.py
|
||||||
|
* searchlight/elasticsearch/plugins/neutron/routers.py
|
||||||
|
|
|
@ -14,5 +14,7 @@
|
||||||
"resource:OS::Designate::Zone:allow": "",
|
"resource:OS::Designate::Zone:allow": "",
|
||||||
"resource:OS::Designate::RecordSet:allow": "",
|
"resource:OS::Designate::RecordSet:allow": "",
|
||||||
"resource:OS::Neutron::Net:allow": "",
|
"resource:OS::Neutron::Net:allow": "",
|
||||||
"resource:OS::Neutron::Port:allow": ""
|
"resource:OS::Neutron::Port:allow": "",
|
||||||
|
"resource:OS::Neutron::Subnet:allow": "",
|
||||||
|
"resource:OS::Neutron::Router:allow": ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
---
|
---
|
||||||
features:
|
features:
|
||||||
- Adds neutron plugins for networks and ports.
|
- Adds neutron plugins for networks, subnets, ports
|
||||||
|
and routers.
|
||||||
issues:
|
issues:
|
||||||
- Neutron resources do not provide dates (created_at
|
- Neutron resources do not provide dates (created_at
|
||||||
or updated_at). created_at is left empty; updated_at
|
or updated_at). created_at is left empty; updated_at
|
||||||
|
|
|
@ -18,6 +18,14 @@ import copy
|
||||||
from searchlight.elasticsearch.plugins import utils
|
from searchlight.elasticsearch.plugins import utils
|
||||||
|
|
||||||
|
|
||||||
|
def _add_dates(entity, updated_at=None):
|
||||||
|
"""Nothing in neutron appears to have any dates attached to it, or at
|
||||||
|
least not that we're able to get at.
|
||||||
|
"""
|
||||||
|
if not entity.get('updated_at'):
|
||||||
|
entity['updated_at'] = updated_at or utils.get_now_str()
|
||||||
|
|
||||||
|
|
||||||
def serialize_network(network, updated_at=None):
|
def serialize_network(network, updated_at=None):
|
||||||
serialized = copy.deepcopy(network)
|
serialized = copy.deepcopy(network)
|
||||||
# TODO(sjmc7): Once subnets are added, look at whether or not to
|
# TODO(sjmc7): Once subnets are added, look at whether or not to
|
||||||
|
@ -33,3 +41,16 @@ def serialize_port(port, updated_at=None):
|
||||||
serialized = copy.deepcopy(port)
|
serialized = copy.deepcopy(port)
|
||||||
serialized['updated_at'] = updated_at or utils.get_now_str()
|
serialized['updated_at'] = updated_at or utils.get_now_str()
|
||||||
return serialized
|
return serialized
|
||||||
|
|
||||||
|
|
||||||
|
def serialize_subnet(subnet):
|
||||||
|
serialized = copy.deepcopy(subnet)
|
||||||
|
serialized['project_id'] = serialized['tenant_id']
|
||||||
|
return serialized
|
||||||
|
|
||||||
|
|
||||||
|
def serialize_router(router, updated_at=None):
|
||||||
|
serialized = copy.deepcopy(router)
|
||||||
|
serialized['updated_at'] = updated_at or utils.get_now_str()
|
||||||
|
serialized['project_id'] = serialized['tenant_id']
|
||||||
|
return serialized
|
||||||
|
|
|
@ -18,7 +18,11 @@ from oslo_log import log as logging
|
||||||
from searchlight.elasticsearch.plugins import base
|
from searchlight.elasticsearch.plugins import base
|
||||||
from searchlight.elasticsearch.plugins.neutron import serialize_network
|
from searchlight.elasticsearch.plugins.neutron import serialize_network
|
||||||
from searchlight.elasticsearch.plugins.neutron import serialize_port
|
from searchlight.elasticsearch.plugins.neutron import serialize_port
|
||||||
|
from searchlight.elasticsearch.plugins.neutron import serialize_router
|
||||||
|
from searchlight.elasticsearch.plugins.neutron import serialize_subnet
|
||||||
|
from searchlight.elasticsearch.plugins import openstack_clients
|
||||||
from searchlight.elasticsearch.plugins import utils
|
from searchlight.elasticsearch.plugins import utils
|
||||||
|
|
||||||
from searchlight import i18n
|
from searchlight import i18n
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
@ -73,7 +77,10 @@ class PortHandler(base.NotificationBase):
|
||||||
return {
|
return {
|
||||||
'port.create.end': self.create_or_update,
|
'port.create.end': self.create_or_update,
|
||||||
'port.update.end': self.create_or_update,
|
'port.update.end': self.create_or_update,
|
||||||
'port.delete.end': self.delete
|
'port.delete.end': self.delete,
|
||||||
|
|
||||||
|
'router.interface.create': self.create_or_update_from_interface,
|
||||||
|
'router.interface.delete': self.delete_from_interface
|
||||||
}
|
}
|
||||||
|
|
||||||
def create_or_update(self, payload, timestamp):
|
def create_or_update(self, payload, timestamp):
|
||||||
|
@ -98,3 +105,90 @@ class PortHandler(base.NotificationBase):
|
||||||
'Error deleting port %(port_id)s '
|
'Error deleting port %(port_id)s '
|
||||||
'from index. Error: %(exc)s') %
|
'from index. Error: %(exc)s') %
|
||||||
{'port_id': port_id, 'exc': exc})
|
{'port_id': port_id, 'exc': exc})
|
||||||
|
|
||||||
|
def create_or_update_from_interface(self, payload, timestamp):
|
||||||
|
"""Unfortunately there seems to be no notification for ports created
|
||||||
|
as part of a router interface creation, nor for DHCP ports. This
|
||||||
|
means we need to go to the API.
|
||||||
|
"""
|
||||||
|
port_id = payload['router_interface']['port_id']
|
||||||
|
LOG.debug("Retrieving port %s from API", port_id)
|
||||||
|
nc = openstack_clients.get_neutronclient()
|
||||||
|
port = nc.show_port(port_id)['port']
|
||||||
|
serialized = serialize_port(
|
||||||
|
port, updated_at=utils.timestamp_to_isotime(timestamp))
|
||||||
|
version = self.get_version(serialized, timestamp)
|
||||||
|
self.index_helper.save_document(serialized, version=version)
|
||||||
|
|
||||||
|
def delete_from_interface(self, payload, timestamp):
|
||||||
|
"""The partner of create_or_update_from_interface. There's no separate
|
||||||
|
port deletion notification.
|
||||||
|
"""
|
||||||
|
port_id = payload['router_interface']['port_id']
|
||||||
|
delete_payload = {'port_id': port_id}
|
||||||
|
self.delete(delete_payload, timestamp)
|
||||||
|
|
||||||
|
|
||||||
|
class SubnetHandler(base.NotificationBase):
|
||||||
|
@classmethod
|
||||||
|
def _get_notification_exchanges(cls):
|
||||||
|
return ['neutron']
|
||||||
|
|
||||||
|
def get_event_handlers(self):
|
||||||
|
return {
|
||||||
|
'subnet.create.end': self.create_or_update,
|
||||||
|
'subnet.update.end': self.create_or_update,
|
||||||
|
'subnet.delete.end': self.delete
|
||||||
|
}
|
||||||
|
|
||||||
|
def create_or_update(self, payload, timestamp):
|
||||||
|
subnet_id = payload['subnet']['id']
|
||||||
|
LOG.debug("Updating subnet information for %s", subnet_id)
|
||||||
|
subnet = serialize_subnet(payload['subnet'])
|
||||||
|
|
||||||
|
version = self.get_version(subnet, timestamp)
|
||||||
|
self.index_helper.save_document(subnet, version=version)
|
||||||
|
|
||||||
|
def delete(self, payload, timestamp):
|
||||||
|
subnet_id = payload['subnet_id']
|
||||||
|
LOG.debug("Deleting subnet information for %s", subnet_id)
|
||||||
|
try:
|
||||||
|
self.index_helper.delete_document({'_id': subnet_id})
|
||||||
|
except Exception as exc:
|
||||||
|
LOG.error(_LE(
|
||||||
|
'Error deleting subnet %(subnet_id)s '
|
||||||
|
'from index: %(exc)s') %
|
||||||
|
{'subnet_id': subnet_id, 'exc': exc})
|
||||||
|
|
||||||
|
|
||||||
|
class RouterHandler(base.NotificationBase):
|
||||||
|
@classmethod
|
||||||
|
def _get_notification_exchanges(cls):
|
||||||
|
return ['neutron']
|
||||||
|
|
||||||
|
def get_event_handlers(self):
|
||||||
|
return {
|
||||||
|
'router.create.end': self.create_or_update,
|
||||||
|
'router.update.end': self.create_or_update,
|
||||||
|
'router.delete.end': self.delete
|
||||||
|
}
|
||||||
|
|
||||||
|
def create_or_update(self, payload, timestamp):
|
||||||
|
router_id = payload['router']['id']
|
||||||
|
LOG.debug("Updating router information for %s", router_id)
|
||||||
|
router = serialize_router(
|
||||||
|
payload['router'],
|
||||||
|
updated_at=utils.timestamp_to_isotime(timestamp))
|
||||||
|
version = self.get_version(router, timestamp)
|
||||||
|
self.index_helper.save_document(router, version=version)
|
||||||
|
|
||||||
|
def delete(self, payload, timestamp):
|
||||||
|
router_id = payload['router_id']
|
||||||
|
LOG.debug("Deleting router information for %s", router_id)
|
||||||
|
try:
|
||||||
|
self.index_helper.delete_document({'_id': router_id})
|
||||||
|
except Exception as exc:
|
||||||
|
LOG.error(_LE(
|
||||||
|
'Error deleting router %(router)s '
|
||||||
|
'from index: %(exc)s') %
|
||||||
|
{'router': router_id, 'exc': exc})
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
# Copyright (c) 2016 Hewlett-Packard Enterprise Development Company, L.P.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
# implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
from searchlight.elasticsearch.plugins import base
|
||||||
|
from searchlight.elasticsearch.plugins.neutron import notification_handlers
|
||||||
|
from searchlight.elasticsearch.plugins.neutron import serialize_router
|
||||||
|
from searchlight.elasticsearch.plugins import openstack_clients
|
||||||
|
|
||||||
|
|
||||||
|
class RouterIndex(base.IndexBase):
|
||||||
|
NotificationHandlerCls = notification_handlers.RouterHandler
|
||||||
|
|
||||||
|
ADMIN_ONLY_FIELDS = ['distributed', 'ha']
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_document_type(self):
|
||||||
|
return 'OS::Neutron::Router'
|
||||||
|
|
||||||
|
def get_mapping(self):
|
||||||
|
return {
|
||||||
|
'dynamic': 'false',
|
||||||
|
'properties': {
|
||||||
|
'admin_state_up': {'type': 'boolean'},
|
||||||
|
'availability_zone_hints': {'type': 'string',
|
||||||
|
'index': 'not_analyzed'},
|
||||||
|
'availability_zones': {'type': 'string',
|
||||||
|
'index': 'not_analyzed'},
|
||||||
|
# Routers don't have created_at
|
||||||
|
'description': {'type': 'string'},
|
||||||
|
'distributed': {'type': 'boolean'},
|
||||||
|
'external_gateway_info': {
|
||||||
|
'type': 'nested',
|
||||||
|
'properties': {
|
||||||
|
'enable_snat': {'type': 'boolean'},
|
||||||
|
'external_fixed_ips': {
|
||||||
|
'type': 'nested',
|
||||||
|
# TODO(sjmc7) Check we can deal with arbitrary
|
||||||
|
# levels of nesting with facets
|
||||||
|
'properties': {
|
||||||
|
'ip_address': {'type': 'string',
|
||||||
|
'index': 'not_analyzed'},
|
||||||
|
'subnet_id': {'type': 'string',
|
||||||
|
'index': 'not_analyzed'},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'network_id': {'type': 'string',
|
||||||
|
'index': 'not_analyzed'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'ha': {'type': 'boolean'},
|
||||||
|
'id': {'type': 'string', 'index': 'not_analyzed'},
|
||||||
|
'name': {
|
||||||
|
'type': 'string',
|
||||||
|
'fields': {
|
||||||
|
'raw': {'type': 'string', 'index': 'not_analyzed'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'project_id': {'type': 'string', 'index': 'not_analyzed'},
|
||||||
|
# TODO(sjmc7) Decide whether to keep these;
|
||||||
|
# they seem like trouble
|
||||||
|
'routes': {
|
||||||
|
'type': 'nested',
|
||||||
|
'properties': {
|
||||||
|
'destination': {'type': 'string',
|
||||||
|
'index': 'not_analyzed'},
|
||||||
|
'nexthop': {'type': 'string', 'index': 'not_analyzed'},
|
||||||
|
'action': {'type': 'string', 'index': 'not_analyzed'},
|
||||||
|
'source': {'type': 'string',
|
||||||
|
'index': 'not_analyzed'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'status': {'type': 'string', 'index': 'not_analyzed'},
|
||||||
|
'tenant_id': {'type': 'string', 'index': 'not_analyzed'},
|
||||||
|
'updated_at': {'type': 'date'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def admin_only_fields(self):
|
||||||
|
from_conf = super(RouterIndex, self).admin_only_fields
|
||||||
|
return from_conf + RouterIndex.ADMIN_ONLY_FIELDS
|
||||||
|
|
||||||
|
@property
|
||||||
|
def facets_with_options(self):
|
||||||
|
return ('admin_state_up', 'availability_zones', 'status',
|
||||||
|
'distributed', 'ha', 'external_gateway_info.enable_snat')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def facets_excluded(self):
|
||||||
|
return {'tenant_id': True, 'distributed': True, 'ha': True,
|
||||||
|
'project_id': False}
|
||||||
|
|
||||||
|
def _get_rbac_field_filters(self, request_context):
|
||||||
|
return [
|
||||||
|
{'term': {'tenant_id': request_context.owner}}
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_objects(self):
|
||||||
|
neutron_client = openstack_clients.get_neutronclient()
|
||||||
|
for router in neutron_client.list_routers()['routers']:
|
||||||
|
yield router
|
||||||
|
|
||||||
|
def serialize(self, router):
|
||||||
|
return serialize_router(router)
|
|
@ -0,0 +1,120 @@
|
||||||
|
# Copyright (c) 2016 Hewlett-Packard Enterprise Development Company, L.P.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
# implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from searchlight.elasticsearch.plugins import base
|
||||||
|
from searchlight.elasticsearch.plugins.neutron import notification_handlers
|
||||||
|
from searchlight.elasticsearch.plugins.neutron import serialize_subnet
|
||||||
|
from searchlight.elasticsearch.plugins import openstack_clients
|
||||||
|
|
||||||
|
|
||||||
|
class SubnetIndex(base.IndexBase):
|
||||||
|
NotificationHandlerCls = notification_handlers.SubnetHandler
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_document_type(self):
|
||||||
|
return 'OS::Neutron::Subnet'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def parent_plugin_type(cls):
|
||||||
|
return 'OS::Neutron::Net'
|
||||||
|
|
||||||
|
def get_parent_id_field(self):
|
||||||
|
return 'network_id'
|
||||||
|
|
||||||
|
def get_mapping(self):
|
||||||
|
return {
|
||||||
|
'dynamic': False,
|
||||||
|
'properties': {
|
||||||
|
'allocation_pools': {
|
||||||
|
'type': 'nested',
|
||||||
|
'properties': {
|
||||||
|
'start': {'type': 'string', 'index': 'not_analyzed'},
|
||||||
|
'end': {'type': 'string', 'index': 'not_analyzed'},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'cidr': {'type': 'string', 'index': 'not_analyzed'},
|
||||||
|
'created_at': {'type': 'date'},
|
||||||
|
'description': {'type': 'string'},
|
||||||
|
'dns_nameservers': {'type': 'string', 'index': 'not_analyzed'},
|
||||||
|
'enable_dhcp': {'type': 'boolean'},
|
||||||
|
'gateway_ip': {'type': 'string', 'index': 'not_analyzed'},
|
||||||
|
'host_routes': {
|
||||||
|
'type': 'nested',
|
||||||
|
'properties': {
|
||||||
|
'destination': {'type': 'string',
|
||||||
|
'index': 'not_analyzed'},
|
||||||
|
'next_hop': {'type': 'string',
|
||||||
|
'index': 'not_analyzed'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'id': {'type': 'string', 'index': 'not_analyzed'},
|
||||||
|
'ip_version': {'type': 'short'},
|
||||||
|
'ipv6_address_mode': {'type': 'string',
|
||||||
|
'index': 'not_analyzed'},
|
||||||
|
'ipv6_ra_mode': {'type': 'string', 'index': 'not_analyzed'},
|
||||||
|
'name': {
|
||||||
|
'type': 'string',
|
||||||
|
'fields': {
|
||||||
|
'raw': {'type': 'string', 'index': 'not_analyzed'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'network_id': {'type': 'string', 'index': 'not_analyzed'},
|
||||||
|
'project_id': {'type': 'string', 'index': 'not_analyzed'},
|
||||||
|
'subnetpool_id': {'type': 'string', 'index': 'not_analyzed'},
|
||||||
|
'tenant_id': {'type': 'string', 'index': 'not_analyzed'},
|
||||||
|
'updated_at': {'type': 'date'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def requires_role_separation(self):
|
||||||
|
return self.parent_plugin.requires_role_separation
|
||||||
|
|
||||||
|
@property
|
||||||
|
def facets_with_options(self):
|
||||||
|
return ('ip_version', 'dns_nameservers', 'network_id', 'enable_dhcp',
|
||||||
|
'ipv6_address_mode', 'ipv6_ra_mode')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def facets_excluded(self):
|
||||||
|
"""A map of {name: allow_admin} that indicate which
|
||||||
|
fields should not be offered as facet options, or those that should
|
||||||
|
only be available to administrators.
|
||||||
|
"""
|
||||||
|
return {'tenant_id': True, 'project_id': False}
|
||||||
|
|
||||||
|
def _get_rbac_field_filters(self, request_context):
|
||||||
|
"""Subnets are visible to their owners and if they belong to networks
|
||||||
|
with the 'shared' property.
|
||||||
|
"""
|
||||||
|
return [{
|
||||||
|
"or": [
|
||||||
|
{'term': {'tenant_id': request_context.owner}},
|
||||||
|
{
|
||||||
|
'has_parent': {
|
||||||
|
'type': self.parent_plugin_type(),
|
||||||
|
'query': {'term': {'shared': True}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
|
||||||
|
def get_objects(self):
|
||||||
|
neutron_client = openstack_clients.get_neutronclient()
|
||||||
|
for subnet in neutron_client.list_subnets()['subnets']:
|
||||||
|
yield subnet
|
||||||
|
|
||||||
|
def serialize(self, subnet):
|
||||||
|
return serialize_subnet(subnet)
|
|
@ -374,19 +374,23 @@ class FunctionalTest(test_utils.BaseTestCase):
|
||||||
plugin_classes = {
|
plugin_classes = {
|
||||||
'glance': {'images': 'ImageIndex', 'metadefs': 'MetadefIndex'},
|
'glance': {'images': 'ImageIndex', 'metadefs': 'MetadefIndex'},
|
||||||
'nova': {'servers': 'ServerIndex'},
|
'nova': {'servers': 'ServerIndex'},
|
||||||
'neutron': {'networks': 'NetworkIndex', 'ports': 'PortIndex'},
|
|
||||||
'cinder': {'volumes': 'VolumeIndex', 'snapshots': 'SnapshotIndex'},
|
'cinder': {'volumes': 'VolumeIndex', 'snapshots': 'SnapshotIndex'},
|
||||||
|
'neutron': {'networks': 'NetworkIndex', 'ports': 'PortIndex',
|
||||||
|
'subnets': 'SubnetIndex', 'routers': 'RouterIndex'},
|
||||||
'swift': {'accounts': 'AccountIndex',
|
'swift': {'accounts': 'AccountIndex',
|
||||||
'containers': 'ContainerIndex',
|
'containers': 'ContainerIndex',
|
||||||
'objects': 'ObjectIndex'}
|
'objects': 'ObjectIndex'},
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins = include_plugins or (
|
plugins = include_plugins or (
|
||||||
('glance', 'images'), ('glance', 'metadefs'),
|
('glance', 'images'), ('glance', 'metadefs'),
|
||||||
('nova', 'servers'),
|
('nova', 'servers'),
|
||||||
|
('cinder', 'volumes'), ('cinder', 'snapshots'),
|
||||||
('neutron', 'networks'), ('neutron', 'ports'),
|
('neutron', 'networks'), ('neutron', 'ports'),
|
||||||
|
('neutron', 'subnets'), ('neutron', 'routers'),
|
||||||
('cinder', 'volumes'), ('cinder', 'snapshots'),
|
('cinder', 'volumes'), ('cinder', 'snapshots'),
|
||||||
('swift', 'accounts'), ('swift', 'containers'),
|
('swift', 'accounts'), ('swift', 'containers'),
|
||||||
('swift', 'objects')
|
('swift', 'objects'),
|
||||||
)
|
)
|
||||||
plugins = filter(lambda plugin: plugin not in exclude_plugins, plugins)
|
plugins = filter(lambda plugin: plugin not in exclude_plugins, plugins)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,281 @@
|
||||||
|
{
|
||||||
|
"router.create.end": {
|
||||||
|
"event_type": "router.create.end",
|
||||||
|
"payload": {
|
||||||
|
"router": {
|
||||||
|
"status": "ACTIVE",
|
||||||
|
"external_gateway_info": null,
|
||||||
|
"availability_zone_hints": [],
|
||||||
|
"availability_zones": [],
|
||||||
|
"name": "test-router",
|
||||||
|
"admin_state_up": true,
|
||||||
|
"tenant_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"distributed": false,
|
||||||
|
"routes": [],
|
||||||
|
"ha": false,
|
||||||
|
"id": "0b143748-44d2-4545-9230-864c3abbc786"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"publisher_id": "network.devstack",
|
||||||
|
"ctxt": {
|
||||||
|
"read_only": false,
|
||||||
|
"domain": null,
|
||||||
|
"project_name": "admin",
|
||||||
|
"user_id": "d2ac2752732444adac10fc4911fdac75",
|
||||||
|
"show_deleted": false,
|
||||||
|
"roles": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"user_identity": "d2ac2752732444adac10fc4911fdac75 75c31cdaa3604b76b7e279de50aec9f0 - - -",
|
||||||
|
"project_domain": null,
|
||||||
|
"tenant_name": "admin",
|
||||||
|
"auth_token": "20cd67462bb540b98210f7dd118b7ce2",
|
||||||
|
"resource_uuid": null,
|
||||||
|
"project_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"tenant_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"is_admin": true,
|
||||||
|
"user": "d2ac2752732444adac10fc4911fdac75",
|
||||||
|
"request_id": "req-64f15ef0-c172-44da-bb7e-eafac7ebdee0",
|
||||||
|
"user_domain": null,
|
||||||
|
"timestamp": "2016-03-13 23:36:25.080945",
|
||||||
|
"tenant": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"user_name": "admin"
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"timestamp": "2016-03-13 23:36:25.145439",
|
||||||
|
"message_id": "0d408f9c-d996-40b5-98fe-738765ae093d"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"router.update.end": {
|
||||||
|
"event_type": "router.update.end",
|
||||||
|
"payload": {
|
||||||
|
"router": {
|
||||||
|
"status": "ACTIVE",
|
||||||
|
"external_gateway_info": null,
|
||||||
|
"availability_zone_hints": [],
|
||||||
|
"availability_zones": [],
|
||||||
|
"name": "renamed router",
|
||||||
|
"admin_state_up": true,
|
||||||
|
"tenant_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"distributed": false,
|
||||||
|
"routes": [],
|
||||||
|
"ha": false,
|
||||||
|
"id": "0b143748-44d2-4545-9230-864c3abbc786"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"publisher_id": "network.devstack",
|
||||||
|
"ctxt": {
|
||||||
|
"read_only": false,
|
||||||
|
"domain": null,
|
||||||
|
"project_name": "admin",
|
||||||
|
"user_id": "d2ac2752732444adac10fc4911fdac75",
|
||||||
|
"show_deleted": false,
|
||||||
|
"roles": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"user_identity": "d2ac2752732444adac10fc4911fdac75 75c31cdaa3604b76b7e279de50aec9f0 - - -",
|
||||||
|
"project_domain": null,
|
||||||
|
"tenant_name": "admin",
|
||||||
|
"auth_token": "32846cb7f8524e13ae0b399e7dd19f03",
|
||||||
|
"resource_uuid": null,
|
||||||
|
"project_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"tenant_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"is_admin": true,
|
||||||
|
"user": "d2ac2752732444adac10fc4911fdac75",
|
||||||
|
"request_id": "req-17f689d2-0f35-4eb7-8074-bed59a2151f0",
|
||||||
|
"user_domain": null,
|
||||||
|
"timestamp": "2016-03-13 23:38:18.481114",
|
||||||
|
"tenant": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"user_name": "admin"
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"timestamp": "2016-03-13 23:38:18.651866",
|
||||||
|
"message_id": "e90ab0d3-2ba6-476b-b092-af44ecc29532"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"router.interface.create": {
|
||||||
|
"event_type": "router.interface.create",
|
||||||
|
"payload": {
|
||||||
|
"router_interface": {
|
||||||
|
"network_id": "60e80dca-302d-4460-8984-9b85dc782bca",
|
||||||
|
"tenant_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"subnet_id": "4cd5c1d7-68ec-4e9a-bf16-9fd7571f8805",
|
||||||
|
"subnet_ids": [
|
||||||
|
"4cd5c1d7-68ec-4e9a-bf16-9fd7571f8805"
|
||||||
|
],
|
||||||
|
"port_id": "a5324522-47d3-4547-85df-a01ef6bde4b1",
|
||||||
|
"id": "0b143748-44d2-4545-9230-864c3abbc786"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"publisher_id": "network.devstack",
|
||||||
|
"ctxt": {
|
||||||
|
"read_only": false,
|
||||||
|
"domain": null,
|
||||||
|
"project_name": "admin",
|
||||||
|
"user_id": "d2ac2752732444adac10fc4911fdac75",
|
||||||
|
"show_deleted": false,
|
||||||
|
"roles": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"user_identity": "d2ac2752732444adac10fc4911fdac75 75c31cdaa3604b76b7e279de50aec9f0 - - -",
|
||||||
|
"project_domain": null,
|
||||||
|
"tenant_name": "admin",
|
||||||
|
"auth_token": "b29f0dd426ca41af90ba36eb022ddbda",
|
||||||
|
"resource_uuid": null,
|
||||||
|
"project_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"tenant_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"is_admin": true,
|
||||||
|
"user": "d2ac2752732444adac10fc4911fdac75",
|
||||||
|
"request_id": "req-f9be76a5-dcf1-4296-9add-a06e8105413e",
|
||||||
|
"user_domain": null,
|
||||||
|
"timestamp": "2016-03-13 23:42:47.959774",
|
||||||
|
"tenant": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"user_name": "admin"
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"timestamp": "2016-03-13 23:42:48.273491",
|
||||||
|
"message_id": "a90d5a20-5206-42e3-ab9b-08309cf2d96c"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"router.interface.delete": {
|
||||||
|
"event_type": "router.interface.delete",
|
||||||
|
"payload": {
|
||||||
|
"router_interface": {
|
||||||
|
"network_id": "60e80dca-302d-4460-8984-9b85dc782bca",
|
||||||
|
"tenant_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"subnet_id": "4cd5c1d7-68ec-4e9a-bf16-9fd7571f8805",
|
||||||
|
"subnet_ids": [
|
||||||
|
"4cd5c1d7-68ec-4e9a-bf16-9fd7571f8805"
|
||||||
|
],
|
||||||
|
"port_id": "a5324522-47d3-4547-85df-a01ef6bde4b1",
|
||||||
|
"id": "0b143748-44d2-4545-9230-864c3abbc786"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"publisher_id": "network.devstack",
|
||||||
|
"ctxt": {
|
||||||
|
"read_only": false,
|
||||||
|
"domain": null,
|
||||||
|
"project_name": "admin",
|
||||||
|
"user_id": "d2ac2752732444adac10fc4911fdac75",
|
||||||
|
"show_deleted": false,
|
||||||
|
"roles": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"user_identity": "d2ac2752732444adac10fc4911fdac75 75c31cdaa3604b76b7e279de50aec9f0 - - -",
|
||||||
|
"project_domain": null,
|
||||||
|
"tenant_name": "admin",
|
||||||
|
"auth_token": "3d9c4d8a583f42ad84cf8f45d647937a",
|
||||||
|
"resource_uuid": null,
|
||||||
|
"project_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"tenant_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"is_admin": false,
|
||||||
|
"user": "d2ac2752732444adac10fc4911fdac75",
|
||||||
|
"request_id": "req-1c3bc795-43b1-4ad8-aa17-b6f2b5c3fe2b",
|
||||||
|
"user_domain": null,
|
||||||
|
"timestamp": "2016-03-17 17:29:32.388395",
|
||||||
|
"tenant": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"user_name": "admin"
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"timestamp": "2016-03-13 23:42:51.273491",
|
||||||
|
"message_id": "6d917992-07ef-471e-9720-6c5e3b60f2d4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"router.gateway.set": {
|
||||||
|
"event_type": "router.update.end",
|
||||||
|
"payload": {
|
||||||
|
"router": {
|
||||||
|
"status": "ACTIVE",
|
||||||
|
"external_gateway_info": {
|
||||||
|
"network_id": "8891323e-bf5b-48d7-a75e-669af0608538",
|
||||||
|
"enable_snat": true,
|
||||||
|
"external_fixed_ips": [
|
||||||
|
{
|
||||||
|
"subnet_id": "8cbe9b71-ecf1-4355-b5ba-dee54ec88fa7",
|
||||||
|
"ip_address": "172.25.0.3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"subnet_id": "d7774648-ba81-477a-9329-2acc9a810e50",
|
||||||
|
"ip_address": "2001:db8::3"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"availability_zone_hints": [],
|
||||||
|
"availability_zones": [
|
||||||
|
"nova"
|
||||||
|
],
|
||||||
|
"name": "renamed router",
|
||||||
|
"admin_state_up": true,
|
||||||
|
"tenant_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"distributed": false,
|
||||||
|
"routes": [],
|
||||||
|
"ha": false,
|
||||||
|
"id": "0b143748-44d2-4545-9230-864c3abbc786"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"publisher_id": "network.devstack",
|
||||||
|
"ctxt": {
|
||||||
|
"read_only": false,
|
||||||
|
"domain": null,
|
||||||
|
"project_name": "admin",
|
||||||
|
"user_id": "d2ac2752732444adac10fc4911fdac75",
|
||||||
|
"show_deleted": false,
|
||||||
|
"roles": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"user_identity": "d2ac2752732444adac10fc4911fdac75 75c31cdaa3604b76b7e279de50aec9f0 - - -",
|
||||||
|
"project_domain": null,
|
||||||
|
"tenant_name": "admin",
|
||||||
|
"auth_token": "f55ae4544c6040358bad962ac20f725d",
|
||||||
|
"resource_uuid": null,
|
||||||
|
"project_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"tenant_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"is_admin": true,
|
||||||
|
"user": "d2ac2752732444adac10fc4911fdac75",
|
||||||
|
"request_id": "req-0f16f883-c413-480a-9d4b-4e79fc7fd476",
|
||||||
|
"user_domain": null,
|
||||||
|
"timestamp": "2016-03-13 23:46:39.283489",
|
||||||
|
"tenant": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"user_name": "admin"
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"timestamp": "2016-03-13 23:46:39.809556",
|
||||||
|
"message_id": "7c92b12c-1477-4e87-a76a-024518da354b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"router.delete.end": {
|
||||||
|
"event_type": "router.delete.end",
|
||||||
|
"payload": {
|
||||||
|
"router_id": "0b143748-44d2-4545-9230-864c3abbc786"
|
||||||
|
},
|
||||||
|
"publisher_id": "network.devstack",
|
||||||
|
"ctxt": {
|
||||||
|
"read_only": false,
|
||||||
|
"domain": null,
|
||||||
|
"project_name": "admin",
|
||||||
|
"user_id": "d2ac2752732444adac10fc4911fdac75",
|
||||||
|
"show_deleted": false,
|
||||||
|
"roles": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"user_identity": "d2ac2752732444adac10fc4911fdac75 75c31cdaa3604b76b7e279de50aec9f0 - - -",
|
||||||
|
"project_domain": null,
|
||||||
|
"tenant_name": "admin",
|
||||||
|
"auth_token": "ee110ae55ebc4ca0af695e106745833c",
|
||||||
|
"resource_uuid": null,
|
||||||
|
"project_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"tenant_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"is_admin": true,
|
||||||
|
"user": "d2ac2752732444adac10fc4911fdac75",
|
||||||
|
"request_id": "req-adba6854-8bcf-47a5-9710-7a7a7df33a37",
|
||||||
|
"user_domain": null,
|
||||||
|
"timestamp": "2016-03-14 00:44:56.857061",
|
||||||
|
"tenant": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"user_name": "admin"
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"timestamp": "2016-03-14 00:44:57.126816",
|
||||||
|
"message_id": "56428f7d-3f07-4b23-882d-612d8852e422"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,151 @@
|
||||||
|
{
|
||||||
|
"subnet.create.end": {
|
||||||
|
"event_type": "subnet.create.end",
|
||||||
|
"payload": {
|
||||||
|
"subnet": {
|
||||||
|
"name": "",
|
||||||
|
"enable_dhcp": true,
|
||||||
|
"network_id": "60e80dca-302d-4460-8984-9b85dc782bca",
|
||||||
|
"tenant_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"dns_nameservers": [],
|
||||||
|
"ipv6_ra_mode": null,
|
||||||
|
"allocation_pools": [
|
||||||
|
{
|
||||||
|
"start": "172.45.0.2",
|
||||||
|
"end": "172.45.255.254"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"gateway_ip": "172.45.0.1",
|
||||||
|
"ipv6_address_mode": null,
|
||||||
|
"ip_version": 4,
|
||||||
|
"host_routes": [],
|
||||||
|
"cidr": "172.45.0.0/16",
|
||||||
|
"id": "4cd5c1d7-68ec-4e9a-bf16-9fd7571f8805",
|
||||||
|
"subnetpool_id": null,
|
||||||
|
"updated_at": "2016-03-13T23:41:32",
|
||||||
|
"created_at": "2016-03-13T23:41:32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"publisher_id": "network.devstack",
|
||||||
|
"ctxt": {
|
||||||
|
"read_only": false,
|
||||||
|
"domain": null,
|
||||||
|
"project_name": "admin",
|
||||||
|
"user_id": "d2ac2752732444adac10fc4911fdac75",
|
||||||
|
"show_deleted": false,
|
||||||
|
"roles": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"user_identity": "d2ac2752732444adac10fc4911fdac75 75c31cdaa3604b76b7e279de50aec9f0 - - -",
|
||||||
|
"project_domain": null,
|
||||||
|
"tenant_name": "admin",
|
||||||
|
"auth_token": "2af46d5627ef422491be4400038b5709",
|
||||||
|
"resource_uuid": null,
|
||||||
|
"project_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"tenant_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"is_admin": true,
|
||||||
|
"user": "d2ac2752732444adac10fc4911fdac75",
|
||||||
|
"request_id": "req-8148c629-919d-4fac-b8ff-57220d7f10b3",
|
||||||
|
"user_domain": null,
|
||||||
|
"timestamp": "2016-03-13 23:41:32.473691",
|
||||||
|
"tenant": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"user_name": "admin"
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"timestamp": "2016-03-13 23:41:32.562400",
|
||||||
|
"message_id": "7e3277a1-68cb-4114-87bf-a622d0417ac7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"subnet.update.end": {
|
||||||
|
"event_type": "subnet.update.end",
|
||||||
|
"payload": {
|
||||||
|
"subnet": {
|
||||||
|
"name": "Updated subnet",
|
||||||
|
"enable_dhcp": true,
|
||||||
|
"network_id": "60e80dca-302d-4460-8984-9b85dc782bca",
|
||||||
|
"tenant_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"dns_nameservers": [],
|
||||||
|
"ipv6_ra_mode": null,
|
||||||
|
"allocation_pools": [
|
||||||
|
{
|
||||||
|
"start": "172.45.0.2",
|
||||||
|
"end": "172.45.255.254"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"gateway_ip": "172.45.0.1",
|
||||||
|
"ipv6_address_mode": null,
|
||||||
|
"ip_version": 4,
|
||||||
|
"host_routes": [],
|
||||||
|
"cidr": "172.45.0.0/16",
|
||||||
|
"id": "4cd5c1d7-68ec-4e9a-bf16-9fd7571f8805",
|
||||||
|
"subnetpool_id": null,
|
||||||
|
"updated_at": "2016-03-13T23:42:20",
|
||||||
|
"created_at": "2016-03-13T23:41:32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"publisher_id": "network.devstack",
|
||||||
|
"ctxt": {
|
||||||
|
"read_only": false,
|
||||||
|
"domain": null,
|
||||||
|
"project_name": "admin",
|
||||||
|
"user_id": "d2ac2752732444adac10fc4911fdac75",
|
||||||
|
"show_deleted": false,
|
||||||
|
"roles": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"user_identity": "d2ac2752732444adac10fc4911fdac75 75c31cdaa3604b76b7e279de50aec9f0 - - -",
|
||||||
|
"project_domain": null,
|
||||||
|
"tenant_name": "admin",
|
||||||
|
"auth_token": "cc90d47602134401802295b0b109ab26",
|
||||||
|
"resource_uuid": null,
|
||||||
|
"project_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"tenant_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"is_admin": true,
|
||||||
|
"user": "d2ac2752732444adac10fc4911fdac75",
|
||||||
|
"request_id": "req-0171556b-f68e-48ff-93a4-9214b286087b",
|
||||||
|
"user_domain": null,
|
||||||
|
"timestamp": "2016-03-13 23:42:20.408564",
|
||||||
|
"tenant": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"user_name": "admin"
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"timestamp": "2016-03-13 23:42:20.631587",
|
||||||
|
"message_id": "cf136c26-9aa6-40ed-80ac-afc468ca09d7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"subnet.delete.end": {
|
||||||
|
"event_type": "subnet.delete.end",
|
||||||
|
"payload": {
|
||||||
|
"subnet_id": "4cd5c1d7-68ec-4e9a-bf16-9fd7571f8805"
|
||||||
|
},
|
||||||
|
"publisher_id": "network.devstack",
|
||||||
|
"ctxt": {
|
||||||
|
"read_only": false,
|
||||||
|
"domain": null,
|
||||||
|
"project_name": "admin",
|
||||||
|
"user_id": "d2ac2752732444adac10fc4911fdac75",
|
||||||
|
"show_deleted": false,
|
||||||
|
"roles": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"user_identity": "d2ac2752732444adac10fc4911fdac75 75c31cdaa3604b76b7e279de50aec9f0 - - -",
|
||||||
|
"project_domain": null,
|
||||||
|
"tenant_name": "admin",
|
||||||
|
"auth_token": "f4611508539a43a6b3511e6f8bdd8492",
|
||||||
|
"resource_uuid": null,
|
||||||
|
"project_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"tenant_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"is_admin": true,
|
||||||
|
"user": "d2ac2752732444adac10fc4911fdac75",
|
||||||
|
"request_id": "req-0c5ccd33-730d-40ca-86d9-3b76b7dbc568",
|
||||||
|
"user_domain": null,
|
||||||
|
"timestamp": "2016-03-14 00:43:17.952733",
|
||||||
|
"tenant": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"user_name": "admin"
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"timestamp": "2016-03-14 00:43:18.143933",
|
||||||
|
"message_id": "adac0012-c79c-4905-9a24-1777f9675808"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,7 +25,22 @@
|
||||||
"router:external": false,
|
"router:external": false,
|
||||||
"shared": true,
|
"shared": true,
|
||||||
"status": "ACTIVE",
|
"status": "ACTIVE",
|
||||||
"subnets": ["63785b90-f3d1-4124-b2e9-1e62dd7c8dab"],
|
"subnets": ["def"],
|
||||||
|
"tenant_id": "aaaaaabbbbbbccccc555552222255511"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"admin_state_up": true,
|
||||||
|
"id": "00000000-4808-4c88-8c3b-000000000000",
|
||||||
|
"mtu": 0,
|
||||||
|
"name": "test-not-shared",
|
||||||
|
"port_security_enabled": true,
|
||||||
|
"provider:network_type": "vxlan",
|
||||||
|
"provider:physical_network": null,
|
||||||
|
"provider:segmentation_id": 1078,
|
||||||
|
"router:external": false,
|
||||||
|
"shared": false,
|
||||||
|
"status": "ACTIVE",
|
||||||
|
"subnets": ["abc"],
|
||||||
"tenant_id": "aaaaaabbbbbbccccc555552222255511"
|
"tenant_id": "aaaaaabbbbbbccccc555552222255511"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
{
|
||||||
|
"routers": [
|
||||||
|
{
|
||||||
|
"admin_state_up": true,
|
||||||
|
"availability_zone_hints": [],
|
||||||
|
"availability_zones": [
|
||||||
|
"nova"
|
||||||
|
],
|
||||||
|
"distributed": false,
|
||||||
|
"external_gateway_info": {
|
||||||
|
"enable_snat": true,
|
||||||
|
"external_fixed_ips": [
|
||||||
|
{
|
||||||
|
"ip_address": "172.25.0.3",
|
||||||
|
"subnet_id": "8cbe9b71-ecf1-4355-b5ba-dee54ec88fa7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ip_address": "2001:db8::3",
|
||||||
|
"subnet_id": "d7774648-ba81-477a-9329-2acc9a810e50"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"network_id": "8891323e-bf5b-48d7-a75e-669af0608538"
|
||||||
|
},
|
||||||
|
"ha": false,
|
||||||
|
"id": "0b143748-44d2-4545-9230-864c3abbc786",
|
||||||
|
"name": "renamed router",
|
||||||
|
"routes": [],
|
||||||
|
"status": "ACTIVE",
|
||||||
|
"tenant_id": "75c31cdaa3604b76b7e279de50aec9f0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"admin_state_up": true,
|
||||||
|
"availability_zone_hints": [],
|
||||||
|
"availability_zones": [
|
||||||
|
"nova"
|
||||||
|
],
|
||||||
|
"distributed": true,
|
||||||
|
"external_gateway_info": {
|
||||||
|
"enable_snat": true,
|
||||||
|
"external_fixed_ips": [
|
||||||
|
{
|
||||||
|
"ip_address": "172.25.0.2",
|
||||||
|
"subnet_id": "8cbe9b71-ecf1-4355-b5ba-dee54ec88fa7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ip_address": "2001:db8::1",
|
||||||
|
"subnet_id": "d7774648-ba81-477a-9329-2acc9a810e50"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"network_id": "8891323e-bf5b-48d7-a75e-669af0608538"
|
||||||
|
},
|
||||||
|
"ha": false,
|
||||||
|
"id": "324d16fc-c381-4ea4-8f77-feda17cea1d7",
|
||||||
|
"name": "router1",
|
||||||
|
"routes": [],
|
||||||
|
"status": "ACTIVE",
|
||||||
|
"tenant_id": "1816a16093df465dbc609cf638422a05"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,122 @@
|
||||||
|
{
|
||||||
|
"subnets": [
|
||||||
|
{
|
||||||
|
"allocation_pools": [
|
||||||
|
{
|
||||||
|
"end": "172.25.255.254",
|
||||||
|
"start": "172.25.0.2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cidr": "172.25.0.0/16",
|
||||||
|
"dns_nameservers": [],
|
||||||
|
"enable_dhcp": false,
|
||||||
|
"gateway_ip": "172.25.0.1",
|
||||||
|
"host_routes": [],
|
||||||
|
"id": "8cbe9b71-ecf1-4355-b5ba-dee54ec88fa7",
|
||||||
|
"ip_version": 4,
|
||||||
|
"ipv6_address_mode": null,
|
||||||
|
"ipv6_ra_mode": null,
|
||||||
|
"name": "public-subnet",
|
||||||
|
"network_id": "8891323e-bf5b-48d7-a75e-669af0608538",
|
||||||
|
"subnetpool_id": null,
|
||||||
|
"tenant_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"updated_at": "2016-03-13T23:41:32",
|
||||||
|
"created_at": "2016-03-13T23:45:32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allocation_pools": [
|
||||||
|
{
|
||||||
|
"end": "2001:db8::1",
|
||||||
|
"start": "2001:db8::1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"end": "2001:db8::ffff:ffff:ffff:ffff",
|
||||||
|
"start": "2001:db8::3"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cidr": "2001:db8::/64",
|
||||||
|
"dns_nameservers": [],
|
||||||
|
"enable_dhcp": false,
|
||||||
|
"gateway_ip": "2001:db8::2",
|
||||||
|
"host_routes": [],
|
||||||
|
"id": "d7774648-ba81-477a-9329-2acc9a810e50",
|
||||||
|
"ip_version": 6,
|
||||||
|
"ipv6_address_mode": null,
|
||||||
|
"ipv6_ra_mode": null,
|
||||||
|
"name": "ipv6-public-subnet",
|
||||||
|
"network_id": "8891323e-bf5b-48d7-a75e-669af0608538",
|
||||||
|
"subnetpool_id": null,
|
||||||
|
"tenant_id": "75c31cdaa3604b76b7e279de50aec9f0",
|
||||||
|
"updated_at": "2016-03-13T23:41:32",
|
||||||
|
"created_at": "2016-03-13T23:45:32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allocation_pools": [
|
||||||
|
{
|
||||||
|
"end": "fd2c:ac9d:23d1:0:ffff:ffff:ffff:ffff",
|
||||||
|
"start": "fd2c:ac9d:23d1::2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cidr": "fd2c:ac9d:23d1::/64",
|
||||||
|
"dns_nameservers": [],
|
||||||
|
"enable_dhcp": true,
|
||||||
|
"gateway_ip": "fd2c:ac9d:23d1::1",
|
||||||
|
"host_routes": [],
|
||||||
|
"id": "12e00c04-7699-4f5a-80e7-8b84c65b2ee3",
|
||||||
|
"ip_version": 6,
|
||||||
|
"ipv6_address_mode": "slaac",
|
||||||
|
"ipv6_ra_mode": "slaac",
|
||||||
|
"name": "ipv6-private-subnet",
|
||||||
|
"network_id": "60e80dca-302d-4460-8984-9b85dc782bca",
|
||||||
|
"subnetpool_id": null,
|
||||||
|
"tenant_id": "1816a16093df465dbc609cf638422a05",
|
||||||
|
"updated_at": "2016-03-13T23:41:32",
|
||||||
|
"created_at": "2016-03-13T23:45:32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allocation_pools": [
|
||||||
|
{
|
||||||
|
"end": "fd2c:ac9d:23d1:0:ffff:ffff:ffff:ffff",
|
||||||
|
"start": "fd2c:ac9d:23d1::2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cidr": "fd2c:ac9d:23d1::/64",
|
||||||
|
"dns_nameservers": [],
|
||||||
|
"enable_dhcp": true,
|
||||||
|
"gateway_ip": "4444:ac9d:54d1::1",
|
||||||
|
"host_routes": [],
|
||||||
|
"id": "fe6b1c72-2560-421d-bd4c-867e545d1234",
|
||||||
|
"ip_version": 6,
|
||||||
|
"ipv6_address_mode": "slaac",
|
||||||
|
"ipv6_ra_mode": "slaac",
|
||||||
|
"name": "shared-subnet",
|
||||||
|
"network_id": "deadbeef-4808-4c88-8c3b-deadbeefdead",
|
||||||
|
"subnetpool_id": null,
|
||||||
|
"tenant_id": "aaaaaabbbbbbccccc555552222255511",
|
||||||
|
"updated_at": "2016-03-13T23:41:32",
|
||||||
|
"created_at": "2016-03-13T23:45:32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allocation_pools": [
|
||||||
|
{
|
||||||
|
"end": "fd2c:ac9d:23d1:0:ffff:ffff:ffff:ffff",
|
||||||
|
"start": "fd2c:ac9d:23d1::2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cidr": "fd2c:ac9d:23d1::/64",
|
||||||
|
"dns_nameservers": [],
|
||||||
|
"enable_dhcp": true,
|
||||||
|
"gateway_ip": "4444:ac9d:54d1::1",
|
||||||
|
"host_routes": [],
|
||||||
|
"id": "0134324324-0000-aaaa-cccc-543534534",
|
||||||
|
"ip_version": 6,
|
||||||
|
"ipv6_address_mode": "slaac",
|
||||||
|
"ipv6_ra_mode": "slaac",
|
||||||
|
"name": "not-shared-subnet",
|
||||||
|
"network_id": "11112222-4808-4c88-8c3b-111122223333",
|
||||||
|
"subnetpool_id": null,
|
||||||
|
"tenant_id": "aaaaaabbbbbbccccc555552222255511",
|
||||||
|
"updated_at": "2016-03-13T23:41:32",
|
||||||
|
"created_at": "2016-03-13T23:45:32"
|
||||||
|
}
|
||||||
|
]}
|
|
@ -26,6 +26,16 @@ from searchlight.tests.functional import test_listener
|
||||||
# This is in the load file
|
# This is in the load file
|
||||||
TENANT1 = "8eaac046b2c44ab99246cb0850c7f06d"
|
TENANT1 = "8eaac046b2c44ab99246cb0850c7f06d"
|
||||||
TENANT2 = "aaaaaabbbbbbccccc555552222255511"
|
TENANT2 = "aaaaaabbbbbbccccc555552222255511"
|
||||||
|
|
||||||
|
# Subnets and routers use these
|
||||||
|
TENANT3 = "75c31cdaa3604b76b7e279de50aec9f0"
|
||||||
|
TENANT4 = "1816a16093df465dbc609cf638422a05"
|
||||||
|
NETID3 = "8891323e-bf5b-48d7-a75e-669af0608538"
|
||||||
|
NETID4 = "60e80dca-302d-4460-8984-9b85dc782bca"
|
||||||
|
|
||||||
|
SHARED_NET_ID = "deadbeef-4808-4c88-8c3b-deadbeefdead"
|
||||||
|
|
||||||
|
|
||||||
_now_str = timeutils.isotime(datetime.datetime.utcnow())
|
_now_str = timeutils.isotime(datetime.datetime.utcnow())
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,8 +43,17 @@ class TestNeutronPlugins(functional.FunctionalTest):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestNeutronPlugins, self).setUp()
|
super(TestNeutronPlugins, self).setUp()
|
||||||
self.networks_plugin = self.initialized_plugins['OS::Neutron::Net']
|
self.networks_plugin = self.initialized_plugins['OS::Neutron::Net']
|
||||||
|
self.subnets_plugin = self.initialized_plugins['OS::Neutron::Subnet']
|
||||||
|
self.routers_plugin = self.initialized_plugins['OS::Neutron::Router']
|
||||||
|
|
||||||
self.network_objects = self._load_fixture_data('load/networks.json')
|
self.network_objects = self._load_fixture_data('load/networks.json')
|
||||||
|
|
||||||
|
self.subnet_objects = self._load_fixture_data('load/subnets.json')
|
||||||
|
self.subnet_objects = self.subnet_objects['subnets']
|
||||||
|
|
||||||
|
self.router_objects = self._load_fixture_data('load/routers.json')
|
||||||
|
self.router_objects = self.router_objects['routers']
|
||||||
|
|
||||||
@mock.patch('searchlight.elasticsearch.plugins.utils.get_now_str')
|
@mock.patch('searchlight.elasticsearch.plugins.utils.get_now_str')
|
||||||
def test_network_rbac_tenant(self, mock_utcnow_str):
|
def test_network_rbac_tenant(self, mock_utcnow_str):
|
||||||
mock_utcnow_str.return_value = _now_str
|
mock_utcnow_str.return_value = _now_str
|
||||||
|
@ -50,10 +69,11 @@ class TestNeutronPlugins(functional.FunctionalTest):
|
||||||
response, json_content = self._search_request(test_api.MATCH_ALL,
|
response, json_content = self._search_request(test_api.MATCH_ALL,
|
||||||
TENANT2)
|
TENANT2)
|
||||||
self.assertEqual(200, response.status)
|
self.assertEqual(200, response.status)
|
||||||
self.assertEqual(2, json_content['hits']['total'])
|
self.assertEqual(3, json_content['hits']['total'])
|
||||||
|
|
||||||
hits = json_content['hits']['hits']
|
hits = json_content['hits']['hits']
|
||||||
expected_names = ['test-shared', 'test-external-router']
|
expected_names = ['test-shared', 'test-external-router',
|
||||||
|
'test-not-shared']
|
||||||
actual_names = [hit['_source']['name'] for hit in hits]
|
actual_names = [hit['_source']['name'] for hit in hits]
|
||||||
|
|
||||||
self.assertEqual(set(expected_names), set(actual_names))
|
self.assertEqual(set(expected_names), set(actual_names))
|
||||||
|
@ -62,7 +82,7 @@ class TestNeutronPlugins(functional.FunctionalTest):
|
||||||
{"query": {"match_all": {}}, "all_projects": True},
|
{"query": {"match_all": {}}, "all_projects": True},
|
||||||
TENANT2, role="admin")
|
TENANT2, role="admin")
|
||||||
self.assertEqual(200, response.status)
|
self.assertEqual(200, response.status)
|
||||||
self.assertEqual(3, json_content['hits']['total'])
|
self.assertEqual(4, json_content['hits']['total'])
|
||||||
|
|
||||||
@mock.patch('searchlight.elasticsearch.plugins.utils.get_now_str')
|
@mock.patch('searchlight.elasticsearch.plugins.utils.get_now_str')
|
||||||
def test_network_rbac_shared_external(self, mock_utcnow_str):
|
def test_network_rbac_shared_external(self, mock_utcnow_str):
|
||||||
|
@ -91,30 +111,207 @@ class TestNeutronPlugins(functional.FunctionalTest):
|
||||||
|
|
||||||
self.assertEqual(set(expected_names), set(actual_names))
|
self.assertEqual(set(expected_names), set(actual_names))
|
||||||
|
|
||||||
|
@mock.patch('searchlight.elasticsearch.plugins.utils.get_now_str')
|
||||||
|
def test_subnet_rbac(self, mock_utcnow_str):
|
||||||
|
"""These tests intentionally don't set a parent network so that they're
|
||||||
|
just testing the tenant id check
|
||||||
|
"""
|
||||||
|
mock_utcnow_str.return_value = _now_str
|
||||||
|
serialized_subnets = [self.subnets_plugin.serialize(subnet)
|
||||||
|
for subnet in self.subnet_objects
|
||||||
|
if subnet["tenant_id"] == TENANT3]
|
||||||
|
self._index(self.subnets_plugin.alias_name_listener,
|
||||||
|
self.subnets_plugin.get_document_type(),
|
||||||
|
serialized_subnets,
|
||||||
|
TENANT3,
|
||||||
|
parent_id_field="network_id",
|
||||||
|
role_separation=True)
|
||||||
|
|
||||||
class TestNeutronListener(test_listener.TestSearchListenerBase):
|
serialized_subnets = [self.subnets_plugin.serialize(subnet)
|
||||||
|
for subnet in self.subnet_objects
|
||||||
|
if subnet["tenant_id"] == TENANT4]
|
||||||
|
self._index(self.subnets_plugin.alias_name_listener,
|
||||||
|
self.subnets_plugin.get_document_type(),
|
||||||
|
serialized_subnets,
|
||||||
|
TENANT4,
|
||||||
|
parent_id_field="network_id",
|
||||||
|
role_separation=True)
|
||||||
|
|
||||||
|
response, json_content = self._search_request(
|
||||||
|
{"query": {"match_all": {}}, "type": "OS::Neutron::Subnet"},
|
||||||
|
TENANT3)
|
||||||
|
self.assertEqual(200, response.status)
|
||||||
|
self.assertEqual(2, json_content['hits']['total'])
|
||||||
|
self.assertEqual(set([NETID3]),
|
||||||
|
set(hit["_source"]["network_id"]
|
||||||
|
for hit in json_content['hits']['hits']))
|
||||||
|
|
||||||
|
@mock.patch('searchlight.elasticsearch.plugins.utils.get_now_str')
|
||||||
|
def test_shared_network_subnet(self, mock_utcnow_str):
|
||||||
|
mock_utcnow_str.return_value = _now_str
|
||||||
|
role_sep = self.networks_plugin.requires_role_separation
|
||||||
|
|
||||||
|
tenant2_nets = [self.networks_plugin.serialize(net)
|
||||||
|
for net in self.network_objects
|
||||||
|
if net['tenant_id'] == TENANT2]
|
||||||
|
self._index(self.networks_plugin.alias_name_listener,
|
||||||
|
self.networks_plugin.get_document_type(),
|
||||||
|
tenant2_nets,
|
||||||
|
TENANT2,
|
||||||
|
role_separation=role_sep)
|
||||||
|
|
||||||
|
# Index the subnets that belongs to the shared network
|
||||||
|
tenant2_subnets = [self.subnets_plugin.serialize(subnet)
|
||||||
|
for subnet in self.subnet_objects
|
||||||
|
if subnet["tenant_id"] == TENANT2]
|
||||||
|
self._index(self.subnets_plugin.alias_name_listener,
|
||||||
|
self.subnets_plugin.get_document_type(),
|
||||||
|
tenant2_subnets,
|
||||||
|
TENANT2,
|
||||||
|
parent_id_field="network_id",
|
||||||
|
role_separation=True)
|
||||||
|
|
||||||
|
# There are now two networks each with one subnet. Both should
|
||||||
|
# show up for tenant 2 but only one for tenant3
|
||||||
|
response, json_content = self._search_request(
|
||||||
|
{"query": {"match_all": {}}, "type": "OS::Neutron::Subnet"},
|
||||||
|
TENANT2)
|
||||||
|
self.assertEqual(2, json_content['hits']['total'])
|
||||||
|
self.assertEqual(
|
||||||
|
set(['shared-subnet', 'not-shared-subnet']),
|
||||||
|
set([h['_source']['name'] for h in json_content['hits']['hits']]))
|
||||||
|
|
||||||
|
# Tenant 3 can see the shared network's subnet
|
||||||
|
response, json_content = self._search_request(
|
||||||
|
{"query": {"match_all": {}}, "type": "OS::Neutron::Subnet"},
|
||||||
|
TENANT3)
|
||||||
|
self.assertEqual(1, json_content['hits']['total'])
|
||||||
|
self.assertEqual(
|
||||||
|
'shared-subnet',
|
||||||
|
json_content['hits']['hits'][0]['_source']['name'])
|
||||||
|
|
||||||
|
@mock.patch('searchlight.elasticsearch.plugins.utils.get_now_str')
|
||||||
|
def test_router_rbac(self, mock_utcnow_str):
|
||||||
|
mock_utcnow_str.return_value = _now_str
|
||||||
|
serialized_routers = [self.routers_plugin.serialize(router)
|
||||||
|
for router in self.router_objects
|
||||||
|
if router["tenant_id"] == TENANT3]
|
||||||
|
role_sep = self.routers_plugin.requires_role_separation
|
||||||
|
self.assertTrue(role_sep)
|
||||||
|
|
||||||
|
self._index(self.routers_plugin.alias_name_listener,
|
||||||
|
self.routers_plugin.get_document_type(),
|
||||||
|
serialized_routers,
|
||||||
|
TENANT3,
|
||||||
|
role_separation=role_sep)
|
||||||
|
|
||||||
|
serialized_routers = [self.routers_plugin.serialize(router)
|
||||||
|
for router in self.router_objects
|
||||||
|
if router["tenant_id"] == TENANT4]
|
||||||
|
self._index(self.routers_plugin.alias_name_listener,
|
||||||
|
self.routers_plugin.get_document_type(),
|
||||||
|
serialized_routers,
|
||||||
|
TENANT4,
|
||||||
|
role_separation=role_sep)
|
||||||
|
|
||||||
|
query = {"query": {"match_all": {}}, "type": "OS::Neutron::Router"}
|
||||||
|
response, json_content = self._search_request(query,
|
||||||
|
TENANT3)
|
||||||
|
self.assertEqual(200, response.status)
|
||||||
|
self.assertEqual(1, json_content['hits']['total'])
|
||||||
|
self.assertEqual('0b143748-44d2-4545-9230-864c3abbc786',
|
||||||
|
json_content['hits']['hits'][0]['_source']['id'])
|
||||||
|
|
||||||
|
response, json_content = self._search_request(query,
|
||||||
|
TENANT4)
|
||||||
|
self.assertEqual(200, response.status)
|
||||||
|
self.assertEqual(1, json_content['hits']['total'])
|
||||||
|
self.assertEqual('324d16fc-c381-4ea4-8f77-feda17cea1d7',
|
||||||
|
json_content['hits']['hits'][0]['_source']['id'])
|
||||||
|
|
||||||
|
def test_router_fixed_ip(self):
|
||||||
|
serialized_routers = [self.routers_plugin.serialize(router)
|
||||||
|
for router in self.router_objects
|
||||||
|
if router["tenant_id"] == TENANT4]
|
||||||
|
role_sep = self.routers_plugin.requires_role_separation
|
||||||
|
self._index(self.routers_plugin.alias_name_listener,
|
||||||
|
self.routers_plugin.get_document_type(),
|
||||||
|
serialized_routers,
|
||||||
|
TENANT4,
|
||||||
|
role_separation=role_sep)
|
||||||
|
|
||||||
|
query = {
|
||||||
|
"query": {
|
||||||
|
"nested": {
|
||||||
|
"path": "external_gateway_info",
|
||||||
|
"query": {
|
||||||
|
"term": {"external_gateway_info.enable_snat": True}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "OS::Neutron::Router"
|
||||||
|
}
|
||||||
|
response, json_content = self._search_request(query,
|
||||||
|
TENANT4)
|
||||||
|
self.assertEqual(200, response.status)
|
||||||
|
self.assertEqual(1, json_content['hits']['total'])
|
||||||
|
|
||||||
|
fixed_ip_path = "external_gateway_info.external_fixed_ips"
|
||||||
|
ip_addr = "%s.ip_address" % fixed_ip_path
|
||||||
|
net_id = "external_gateway_info.network_id"
|
||||||
|
query = {
|
||||||
|
"query": {
|
||||||
|
"nested": {
|
||||||
|
"path": "external_gateway_info",
|
||||||
|
"query": {
|
||||||
|
"bool": {
|
||||||
|
"must": [
|
||||||
|
{"term": {net_id: NETID3}},
|
||||||
|
{"nested": {
|
||||||
|
"path": fixed_ip_path,
|
||||||
|
"query": {
|
||||||
|
"term": {ip_addr: "2001:db8::1"}}
|
||||||
|
}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response, json_content = self._search_request(query,
|
||||||
|
TENANT4)
|
||||||
|
self.assertEqual(200, response.status)
|
||||||
|
self.assertEqual(1, json_content['hits']['total'])
|
||||||
|
|
||||||
|
|
||||||
|
class TestNeutronListeners(test_listener.TestSearchListenerBase):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(TestNeutronListener, self).__init__(*args, **kwargs)
|
super(TestNeutronListeners, self).__init__(*args, **kwargs)
|
||||||
self.network_events = self._load_fixture_data('events/networks.json')
|
self.network_events = self._load_fixture_data('events/networks.json')
|
||||||
self.port_events = self._load_fixture_data('events/ports.json')
|
self.port_events = self._load_fixture_data('events/ports.json')
|
||||||
|
self.subnet_events = self._load_fixture_data('events/subnets.json')
|
||||||
|
self.router_events = self._load_fixture_data('events/routers.json')
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestNeutronListener, self).setUp()
|
super(TestNeutronListeners, self).setUp()
|
||||||
|
|
||||||
self.networks_plugin = self.initialized_plugins['OS::Neutron::Net']
|
self.networks_plugin = self.initialized_plugins['OS::Neutron::Net']
|
||||||
self.ports_plugin = self.initialized_plugins['OS::Neutron::Port']
|
self.ports_plugin = self.initialized_plugins['OS::Neutron::Port']
|
||||||
|
self.subnets_plugin = self.initialized_plugins['OS::Neutron::Subnet']
|
||||||
|
self.routers_plugin = self.initialized_plugins['OS::Neutron::Router']
|
||||||
|
|
||||||
notification_plugins = {
|
notification_plugins = {
|
||||||
plugin.document_type: test_listener.StevedoreMock(plugin)
|
plugin.document_type: test_listener.StevedoreMock(plugin)
|
||||||
for plugin in (self.networks_plugin, self.ports_plugin)}
|
for plugin in (self.networks_plugin, self.ports_plugin,
|
||||||
|
self.subnets_plugin, self.routers_plugin)}
|
||||||
self.notification_endpoint = NotificationEndpoint(notification_plugins)
|
self.notification_endpoint = NotificationEndpoint(notification_plugins)
|
||||||
|
|
||||||
self.index_name = self.networks_plugin.alias_name_listener
|
self.listener_alias = self.networks_plugin.alias_name_listener
|
||||||
|
|
||||||
def test_network_create_update_delete(self):
|
def test_network_create_update_delete(self):
|
||||||
'''Send network.create.end notification event to listener'''
|
'''Send network.create.end notification event to listener'''
|
||||||
create_event = self.network_events['network.create.end']
|
create_event = self.network_events['network.create.end']
|
||||||
self._send_event_to_listener(create_event, self.index_name)
|
self._send_event_to_listener(create_event, self.listener_alias)
|
||||||
result = self._verify_event_processing(create_event, owner=TENANT1)
|
result = self._verify_event_processing(create_event, owner=TENANT1)
|
||||||
verification_keys = ['id', 'status', 'port_security_enabled', 'name']
|
verification_keys = ['id', 'status', 'port_security_enabled', 'name']
|
||||||
self._verify_result(create_event, verification_keys, result,
|
self._verify_result(create_event, verification_keys, result,
|
||||||
|
@ -124,20 +321,20 @@ class TestNeutronListener(test_listener.TestSearchListenerBase):
|
||||||
self.assertEqual('2016-01-13T17:39:04Z', hit['updated_at'])
|
self.assertEqual('2016-01-13T17:39:04Z', hit['updated_at'])
|
||||||
|
|
||||||
update_event = self.network_events['network.update.end']
|
update_event = self.network_events['network.update.end']
|
||||||
self._send_event_to_listener(update_event, self.index_name)
|
self._send_event_to_listener(update_event, self.listener_alias)
|
||||||
result = self._verify_event_processing(update_event, owner=TENANT1)
|
result = self._verify_event_processing(update_event, owner=TENANT1)
|
||||||
verification_keys = ['id', 'status', 'port_security_enabled', 'name']
|
verification_keys = ['id', 'status', 'port_security_enabled', 'name']
|
||||||
self._verify_result(update_event, verification_keys, result,
|
self._verify_result(update_event, verification_keys, result,
|
||||||
inner_key='network')
|
inner_key='network')
|
||||||
|
|
||||||
delete_event = self.network_events['network.delete.end']
|
delete_event = self.network_events['network.delete.end']
|
||||||
self._send_event_to_listener(delete_event, self.index_name)
|
self._send_event_to_listener(delete_event, self.listener_alias)
|
||||||
self._verify_event_processing(delete_event, count=0,
|
self._verify_event_processing(delete_event, count=0,
|
||||||
owner=TENANT1)
|
owner=TENANT1)
|
||||||
|
|
||||||
def test_port_create_event(self):
|
def test_port_create_event(self):
|
||||||
create_event = self.port_events['port.create.end']
|
create_event = self.port_events['port.create.end']
|
||||||
self._send_event_to_listener(create_event, self.index_name)
|
self._send_event_to_listener(create_event, self.listener_alias)
|
||||||
result = self._verify_event_processing(create_event, owner=TENANT1)
|
result = self._verify_event_processing(create_event, owner=TENANT1)
|
||||||
verification_keys = ['id', 'status', 'mac_address', 'status']
|
verification_keys = ['id', 'status', 'mac_address', 'status']
|
||||||
self._verify_result(create_event, verification_keys, result,
|
self._verify_result(create_event, verification_keys, result,
|
||||||
|
@ -147,7 +344,7 @@ class TestNeutronListener(test_listener.TestSearchListenerBase):
|
||||||
|
|
||||||
def test_port_rename_event(self):
|
def test_port_rename_event(self):
|
||||||
update_event = self.port_events['port_rename']
|
update_event = self.port_events['port_rename']
|
||||||
self._send_event_to_listener(update_event, self.index_name)
|
self._send_event_to_listener(update_event, self.listener_alias)
|
||||||
result = self._verify_event_processing(update_event, owner=TENANT1)
|
result = self._verify_event_processing(update_event, owner=TENANT1)
|
||||||
verification_keys = ['name']
|
verification_keys = ['name']
|
||||||
self._verify_result(update_event, verification_keys, result,
|
self._verify_result(update_event, verification_keys, result,
|
||||||
|
@ -155,21 +352,21 @@ class TestNeutronListener(test_listener.TestSearchListenerBase):
|
||||||
|
|
||||||
def test_port_attach_detach_events(self):
|
def test_port_attach_detach_events(self):
|
||||||
create_event = self.port_events['port.create.end']
|
create_event = self.port_events['port.create.end']
|
||||||
self._send_event_to_listener(create_event, self.index_name)
|
self._send_event_to_listener(create_event, self.listener_alias)
|
||||||
result = self._verify_event_processing(create_event, owner=TENANT1)
|
result = self._verify_event_processing(create_event, owner=TENANT1)
|
||||||
verification_keys = ['device_owner', 'device_id']
|
verification_keys = ['device_owner', 'device_id']
|
||||||
self._verify_result(create_event, verification_keys, result,
|
self._verify_result(create_event, verification_keys, result,
|
||||||
inner_key='port')
|
inner_key='port')
|
||||||
|
|
||||||
attach_event = self.port_events['port_attach']
|
attach_event = self.port_events['port_attach']
|
||||||
self._send_event_to_listener(attach_event, self.index_name)
|
self._send_event_to_listener(attach_event, self.listener_alias)
|
||||||
result = self._verify_event_processing(attach_event, owner=TENANT1)
|
result = self._verify_event_processing(attach_event, owner=TENANT1)
|
||||||
verification_keys = ['device_owner', 'device_id']
|
verification_keys = ['device_owner', 'device_id']
|
||||||
self._verify_result(attach_event, verification_keys, result,
|
self._verify_result(attach_event, verification_keys, result,
|
||||||
inner_key='port')
|
inner_key='port')
|
||||||
|
|
||||||
detach_event = self.port_events['port_detach']
|
detach_event = self.port_events['port_detach']
|
||||||
self._send_event_to_listener(detach_event, self.index_name)
|
self._send_event_to_listener(detach_event, self.listener_alias)
|
||||||
result = self._verify_event_processing(attach_event, owner=TENANT1)
|
result = self._verify_event_processing(attach_event, owner=TENANT1)
|
||||||
verification_keys = ['device_owner', 'device_id']
|
verification_keys = ['device_owner', 'device_id']
|
||||||
self._verify_result(detach_event, verification_keys, result,
|
self._verify_result(detach_event, verification_keys, result,
|
||||||
|
@ -177,6 +374,98 @@ class TestNeutronListener(test_listener.TestSearchListenerBase):
|
||||||
|
|
||||||
def test_port_delete_event(self):
|
def test_port_delete_event(self):
|
||||||
delete_event = self.port_events['port.delete.end']
|
delete_event = self.port_events['port.delete.end']
|
||||||
self._send_event_to_listener(delete_event, self.index_name)
|
self._send_event_to_listener(delete_event, self.listener_alias)
|
||||||
self._verify_event_processing(None, count=0,
|
self._verify_event_processing(None, count=0,
|
||||||
owner=TENANT1)
|
owner=TENANT1)
|
||||||
|
|
||||||
|
def test_subnet_create_update_delete(self):
|
||||||
|
create_event = self.subnet_events['subnet.create.end']
|
||||||
|
self._send_event_to_listener(create_event, self.listener_alias)
|
||||||
|
result = self._verify_event_processing(create_event, owner=TENANT3)
|
||||||
|
verification_keys = ['network_id', 'name']
|
||||||
|
self._verify_result(create_event, verification_keys, result,
|
||||||
|
inner_key='subnet')
|
||||||
|
|
||||||
|
update_event = self.subnet_events['subnet.update.end']
|
||||||
|
self._send_event_to_listener(update_event, self.listener_alias)
|
||||||
|
result = self._verify_event_processing(update_event, owner=TENANT3)
|
||||||
|
verification_keys = ['network_id', 'name']
|
||||||
|
self._verify_result(update_event, verification_keys, result,
|
||||||
|
inner_key='subnet')
|
||||||
|
|
||||||
|
delete_event = self.subnet_events['subnet.delete.end']
|
||||||
|
self._send_event_to_listener(delete_event, self.listener_alias)
|
||||||
|
self._verify_event_processing(delete_event, count=0,
|
||||||
|
owner=TENANT3)
|
||||||
|
|
||||||
|
def test_router_create_update_delete(self):
|
||||||
|
create_event = self.router_events['router.create.end']
|
||||||
|
self._send_event_to_listener(create_event, self.listener_alias)
|
||||||
|
result = self._verify_event_processing(create_event, owner=TENANT3)
|
||||||
|
verification_keys = ['status', 'name', 'id']
|
||||||
|
self._verify_result(create_event, verification_keys, result,
|
||||||
|
inner_key='router')
|
||||||
|
|
||||||
|
update_event = self.router_events['router.update.end']
|
||||||
|
self._send_event_to_listener(update_event, self.listener_alias)
|
||||||
|
result = self._verify_event_processing(update_event, owner=TENANT3)
|
||||||
|
verification_keys = ['status', 'name', 'id']
|
||||||
|
self._verify_result(update_event, verification_keys, result,
|
||||||
|
inner_key='router')
|
||||||
|
|
||||||
|
delete_event = self.router_events['router.delete.end']
|
||||||
|
self._send_event_to_listener(delete_event, self.listener_alias)
|
||||||
|
self._verify_event_processing(delete_event, count=0,
|
||||||
|
owner=TENANT3)
|
||||||
|
|
||||||
|
def test_router_interface_create_delete(self):
|
||||||
|
"""Check that port creation and deletion is registered on interface
|
||||||
|
creation and deletion events
|
||||||
|
"""
|
||||||
|
interface_port = {
|
||||||
|
u'port': {
|
||||||
|
u'admin_state_up': True,
|
||||||
|
u'allowed_address_pairs': [],
|
||||||
|
u'binding:vnic_type': u'normal',
|
||||||
|
u'device_id': u'9262552b-6e46-41ee-9ede-393d5f65f325',
|
||||||
|
u'device_owner': u'network:router_interface',
|
||||||
|
u'dns_name': None,
|
||||||
|
u'extra_dhcp_opts': [],
|
||||||
|
u'fixed_ips': [{
|
||||||
|
u'ip_address': u'172.45.1.1',
|
||||||
|
u'subnet_id': u'4cd5c1d7-68ec-4e9a-bf16-9fd7571f8805'
|
||||||
|
}],
|
||||||
|
u'id': u'a5324522-47d3-4547-85df-a01ef6bde4b1',
|
||||||
|
u'mac_address': u'fa:16:3e:5f:06:e3',
|
||||||
|
u'name': u'',
|
||||||
|
u'network_id': NETID4,
|
||||||
|
u'port_security_enabled': False,
|
||||||
|
u'security_groups': [],
|
||||||
|
u'status': u'ACTIVE',
|
||||||
|
u'tenant_id': TENANT3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
create_event = self.router_events['router.interface.create']
|
||||||
|
with mock.patch('neutronclient.v2_0.client.Client.show_port',
|
||||||
|
return_value=interface_port):
|
||||||
|
self._send_event_to_listener(create_event, self.listener_alias)
|
||||||
|
|
||||||
|
query = {
|
||||||
|
"type": "OS::Neutron::Port",
|
||||||
|
"query": {"term": {"id": "a5324522-47d3-4547-85df-a01ef6bde4b1"}}
|
||||||
|
}
|
||||||
|
response, json_content = self._search_request(query,
|
||||||
|
TENANT3)
|
||||||
|
self.assertEqual(200, response.status)
|
||||||
|
self.assertEqual(1, json_content['hits']['total'])
|
||||||
|
hit = json_content['hits']['hits'][0]['_source']
|
||||||
|
|
||||||
|
self.assertEqual(NETID4, hit['network_id'])
|
||||||
|
self.assertEqual('network:router_interface', hit['device_owner'])
|
||||||
|
|
||||||
|
delete_event = self.router_events['router.interface.delete']
|
||||||
|
self._send_event_to_listener(delete_event, self.listener_alias)
|
||||||
|
|
||||||
|
response, json_content = self._search_request(query,
|
||||||
|
TENANT3)
|
||||||
|
self.assertEqual(0, json_content['hits']['total'])
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
# Copyright (c) 2016 Hewlett-Packard Enterprise Development Company, L.P.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
# implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
from oslo_utils import timeutils
|
||||||
|
|
||||||
|
from searchlight.elasticsearch.plugins.neutron import\
|
||||||
|
routers as routers_plugin
|
||||||
|
import searchlight.tests.unit.utils as unit_test_utils
|
||||||
|
import searchlight.tests.utils as test_utils
|
||||||
|
|
||||||
|
|
||||||
|
_now_str = timeutils.isotime(datetime.datetime.utcnow())
|
||||||
|
USER1 = u'27f4d76b-be62-4e4e-aa33bb11cc55'
|
||||||
|
ID1 = "813dd936-663e-4e5b-877c-986021b73e2c"
|
||||||
|
NETID1 = "98dcb60c-59b9-4b3c-bf6a-b8504112e978"
|
||||||
|
TENANT1 = "8eaac046b2c44ab99246cb0850c7f06d"
|
||||||
|
|
||||||
|
|
||||||
|
def _router_fixture(router_id, tenant_id, name, **kwargs):
|
||||||
|
fixture = {
|
||||||
|
u'admin_state_up': True,
|
||||||
|
u'availability_zone_hints': [],
|
||||||
|
u'availability_zones': [],
|
||||||
|
u'external_gateway_info': {
|
||||||
|
u'enable_snat': True,
|
||||||
|
u'external_fixed_ips': [{
|
||||||
|
u'ip_address': u'172.25.0.2',
|
||||||
|
u'subnet_id': u'8cbe9b71-ecf1-4355-b5ba-dee54ec88fa7'
|
||||||
|
}, {
|
||||||
|
u'ip_address': u'2001:db8::1',
|
||||||
|
u'subnet_id': u'd7774648-ba81-477a-9329-2acc9a810e50'
|
||||||
|
}],
|
||||||
|
u'network_id': u'8891323e-bf5b-48d7-a75e-669af0608538'},
|
||||||
|
u'id': router_id,
|
||||||
|
u'name': name,
|
||||||
|
u'routes': [],
|
||||||
|
u'status': u'ACTIVE',
|
||||||
|
u'tenant_id': tenant_id}
|
||||||
|
fixture.update(**kwargs)
|
||||||
|
return fixture
|
||||||
|
|
||||||
|
|
||||||
|
def _gateway_info(network_id, fixed_ips):
|
||||||
|
return {
|
||||||
|
u'enable_snat': True,
|
||||||
|
u'external_fixed_ips': fixed_ips,
|
||||||
|
u'network_id': network_id
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TestRouterLoaderPlugin(test_utils.BaseTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestRouterLoaderPlugin, self).setUp()
|
||||||
|
self.plugin = routers_plugin.RouterIndex()
|
||||||
|
self._create_fixtures()
|
||||||
|
|
||||||
|
def _create_fixtures(self):
|
||||||
|
self.router1 = _router_fixture(router_id=ID1, network_id=NETID1,
|
||||||
|
tenant_id=TENANT1, name="test-router-1")
|
||||||
|
self.routers = [self.router1]
|
||||||
|
|
||||||
|
def test_admin_only(self):
|
||||||
|
self.assertEqual(['distributed', 'ha'], self.plugin.admin_only_fields)
|
||||||
|
|
||||||
|
def test_document_type(self):
|
||||||
|
self.assertEqual('OS::Neutron::Router',
|
||||||
|
self.plugin.get_document_type())
|
||||||
|
|
||||||
|
def test_rbac_filter(self):
|
||||||
|
fake_request = unit_test_utils.get_fake_request(
|
||||||
|
USER1, TENANT1, '/v1/search', is_admin=False
|
||||||
|
)
|
||||||
|
rbac_terms = self.plugin._get_rbac_field_filters(fake_request.context)
|
||||||
|
self.assertEqual(
|
||||||
|
[{"term": {"tenant_id": TENANT1}}],
|
||||||
|
rbac_terms
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_notification_events(self):
|
||||||
|
handler = self.plugin.get_notification_handler()
|
||||||
|
self.assertEqual(
|
||||||
|
set(['router.create.end', 'router.update.end',
|
||||||
|
'router.delete.end']),
|
||||||
|
set(handler.get_event_handlers().keys())
|
||||||
|
)
|
|
@ -0,0 +1,87 @@
|
||||||
|
# Copyright (c) 2016 Hewlett-Packard Enterprise Development Company, L.P.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
# implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
from oslo_utils import timeutils
|
||||||
|
|
||||||
|
from searchlight.elasticsearch.plugins.neutron import\
|
||||||
|
subnets as subnets_plugin
|
||||||
|
import searchlight.tests.unit.utils as unit_test_utils
|
||||||
|
import searchlight.tests.utils as test_utils
|
||||||
|
|
||||||
|
|
||||||
|
_now_str = timeutils.isotime(datetime.datetime.utcnow())
|
||||||
|
USER1 = u'27f4d76b-be62-4e4e-aa33bb11cc55'
|
||||||
|
ID1 = "813dd936-663e-4e5b-877c-986021b73e2c"
|
||||||
|
NETID1 = "98dcb60c-59b9-4b3c-bf6a-b8504112e978"
|
||||||
|
TENANT1 = "8eaac046b2c44ab99246cb0850c7f06d"
|
||||||
|
|
||||||
|
|
||||||
|
def _subnet_fixture(network_id, tenant_id, subnet_id, name, **kwargs):
|
||||||
|
fixture = {
|
||||||
|
"id": subnet_id,
|
||||||
|
"network_id": network_id,
|
||||||
|
"name": name,
|
||||||
|
"tenant_id": tenant_id,
|
||||||
|
"ip_version": kwargs.pop("ip_version", 4),
|
||||||
|
"cidr": kwargs.pop("cidr", "192.0.0.1/24")
|
||||||
|
}
|
||||||
|
pools = kwargs.get('allocation_pools', [{"start": "192.0.0.2",
|
||||||
|
"end": "192.254.254.254"}])
|
||||||
|
fixture['allocation_pools'] = pools
|
||||||
|
fixture.update(kwargs)
|
||||||
|
return fixture
|
||||||
|
|
||||||
|
|
||||||
|
class TestSubnetLoaderPlugin(test_utils.BaseTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestSubnetLoaderPlugin, self).setUp()
|
||||||
|
self.plugin = subnets_plugin.SubnetIndex()
|
||||||
|
self._create_fixtures()
|
||||||
|
|
||||||
|
def _create_fixtures(self):
|
||||||
|
self.subnet1 = _subnet_fixture(subnet_id=ID1, network_id=NETID1,
|
||||||
|
tenant_id=TENANT1, name="test-net-1")
|
||||||
|
self.subnets = [self.subnet1]
|
||||||
|
|
||||||
|
def test_document_type(self):
|
||||||
|
self.assertEqual('OS::Neutron::Subnet',
|
||||||
|
self.plugin.get_document_type())
|
||||||
|
|
||||||
|
def test_rbac_filter(self):
|
||||||
|
fake_request = unit_test_utils.get_fake_request(
|
||||||
|
USER1, TENANT1, '/v1/search', is_admin=False
|
||||||
|
)
|
||||||
|
rbac_terms = self.plugin._get_rbac_field_filters(fake_request.context)
|
||||||
|
self.assertEqual(
|
||||||
|
[{"or": [
|
||||||
|
{"term": {"tenant_id": TENANT1}},
|
||||||
|
{
|
||||||
|
"has_parent": {
|
||||||
|
"type": "OS::Neutron::Net",
|
||||||
|
"query": {"term": {"shared": True}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]}],
|
||||||
|
rbac_terms
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_notification_events(self):
|
||||||
|
handler = self.plugin.get_notification_handler()
|
||||||
|
self.assertEqual(
|
||||||
|
set(['subnet.create.end', 'subnet.update.end',
|
||||||
|
'subnet.delete.end']),
|
||||||
|
set(handler.get_event_handlers().keys())
|
||||||
|
)
|
|
@ -282,6 +282,8 @@ class TestSearchDeserializer(test_utils.BaseTestCase):
|
||||||
'OS::Nova::Server',
|
'OS::Nova::Server',
|
||||||
'OS::Neutron::Net',
|
'OS::Neutron::Net',
|
||||||
'OS::Neutron::Port',
|
'OS::Neutron::Port',
|
||||||
|
'OS::Neutron::Subnet',
|
||||||
|
'OS::Neutron::Router',
|
||||||
'OS::Cinder::Volume',
|
'OS::Cinder::Volume',
|
||||||
'OS::Cinder::Snapshot'
|
'OS::Cinder::Snapshot'
|
||||||
]
|
]
|
||||||
|
|
|
@ -32,7 +32,9 @@ searchlight.index_backend =
|
||||||
os_glance_metadef = searchlight.elasticsearch.plugins.glance.metadefs:MetadefIndex
|
os_glance_metadef = searchlight.elasticsearch.plugins.glance.metadefs:MetadefIndex
|
||||||
os_nova_server = searchlight.elasticsearch.plugins.nova.servers:ServerIndex
|
os_nova_server = searchlight.elasticsearch.plugins.nova.servers:ServerIndex
|
||||||
os_neutron_network = searchlight.elasticsearch.plugins.neutron.networks:NetworkIndex
|
os_neutron_network = searchlight.elasticsearch.plugins.neutron.networks:NetworkIndex
|
||||||
|
os_neutron_subnet = searchlight.elasticsearch.plugins.neutron.subnets:SubnetIndex
|
||||||
os_neutron_port = searchlight.elasticsearch.plugins.neutron.ports:PortIndex
|
os_neutron_port = searchlight.elasticsearch.plugins.neutron.ports:PortIndex
|
||||||
|
os_neutron_router = searchlight.elasticsearch.plugins.neutron.routers:RouterIndex
|
||||||
os_designate_recordset = searchlight.elasticsearch.plugins.designate.recordsets:RecordSetIndex
|
os_designate_recordset = searchlight.elasticsearch.plugins.designate.recordsets:RecordSetIndex
|
||||||
os_designate_zone = searchlight.elasticsearch.plugins.designate.zones:ZoneIndex
|
os_designate_zone = searchlight.elasticsearch.plugins.designate.zones:ZoneIndex
|
||||||
os_cinder_volume = searchlight.elasticsearch.plugins.cinder.volumes:VolumeIndex
|
os_cinder_volume = searchlight.elasticsearch.plugins.cinder.volumes:VolumeIndex
|
||||||
|
|
Loading…
Reference in New Issue