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]
|
||||
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 sends notifications on create/update/delete actions on the
|
||||
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
|
||||
------------
|
||||
|
@ -92,6 +106,8 @@ Release Notes
|
|||
|
||||
All provider:* properties of networks are exposed to administrators only.
|
||||
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`
|
||||
under each plugin's configuration section. Glob-like patterns are supported.
|
||||
|
@ -103,3 +119,4 @@ For instance::
|
|||
See: ADMIN_ONLY_FIELDS in:
|
||||
* searchlight/elasticsearch/plugins/neutron/networks.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::RecordSet: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:
|
||||
- Adds neutron plugins for networks and ports.
|
||||
- Adds neutron plugins for networks, subnets, ports
|
||||
and routers.
|
||||
issues:
|
||||
- Neutron resources do not provide dates (created_at
|
||||
or updated_at). created_at is left empty; updated_at
|
||||
|
|
|
@ -18,6 +18,14 @@ import copy
|
|||
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):
|
||||
serialized = copy.deepcopy(network)
|
||||
# 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['updated_at'] = updated_at or utils.get_now_str()
|
||||
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.neutron import serialize_network
|
||||
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 import i18n
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
@ -73,7 +77,10 @@ class PortHandler(base.NotificationBase):
|
|||
return {
|
||||
'port.create.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):
|
||||
|
@ -98,3 +105,90 @@ class PortHandler(base.NotificationBase):
|
|||
'Error deleting port %(port_id)s '
|
||||
'from index. Error: %(exc)s') %
|
||||
{'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 = {
|
||||
'glance': {'images': 'ImageIndex', 'metadefs': 'MetadefIndex'},
|
||||
'nova': {'servers': 'ServerIndex'},
|
||||
'neutron': {'networks': 'NetworkIndex', 'ports': 'PortIndex'},
|
||||
'cinder': {'volumes': 'VolumeIndex', 'snapshots': 'SnapshotIndex'},
|
||||
'neutron': {'networks': 'NetworkIndex', 'ports': 'PortIndex',
|
||||
'subnets': 'SubnetIndex', 'routers': 'RouterIndex'},
|
||||
'swift': {'accounts': 'AccountIndex',
|
||||
'containers': 'ContainerIndex',
|
||||
'objects': 'ObjectIndex'}
|
||||
'objects': 'ObjectIndex'},
|
||||
}
|
||||
|
||||
plugins = include_plugins or (
|
||||
('glance', 'images'), ('glance', 'metadefs'),
|
||||
('nova', 'servers'),
|
||||
('cinder', 'volumes'), ('cinder', 'snapshots'),
|
||||
('neutron', 'networks'), ('neutron', 'ports'),
|
||||
('neutron', 'subnets'), ('neutron', 'routers'),
|
||||
('cinder', 'volumes'), ('cinder', 'snapshots'),
|
||||
('swift', 'accounts'), ('swift', 'containers'),
|
||||
('swift', 'objects')
|
||||
('swift', 'objects'),
|
||||
)
|
||||
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,
|
||||
"shared": true,
|
||||
"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"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -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
|
||||
TENANT1 = "8eaac046b2c44ab99246cb0850c7f06d"
|
||||
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())
|
||||
|
||||
|
||||
|
@ -33,8 +43,17 @@ class TestNeutronPlugins(functional.FunctionalTest):
|
|||
def setUp(self):
|
||||
super(TestNeutronPlugins, self).setUp()
|
||||
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.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')
|
||||
def test_network_rbac_tenant(self, mock_utcnow_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,
|
||||
TENANT2)
|
||||
self.assertEqual(200, response.status)
|
||||
self.assertEqual(2, json_content['hits']['total'])
|
||||
self.assertEqual(3, json_content['hits']['total'])
|
||||
|
||||
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]
|
||||
|
||||
self.assertEqual(set(expected_names), set(actual_names))
|
||||
|
@ -62,7 +82,7 @@ class TestNeutronPlugins(functional.FunctionalTest):
|
|||
{"query": {"match_all": {}}, "all_projects": True},
|
||||
TENANT2, role="admin")
|
||||
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')
|
||||
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))
|
||||
|
||||
@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):
|
||||
super(TestNeutronListener, self).__init__(*args, **kwargs)
|
||||
super(TestNeutronListeners, self).__init__(*args, **kwargs)
|
||||
self.network_events = self._load_fixture_data('events/networks.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):
|
||||
super(TestNeutronListener, self).setUp()
|
||||
super(TestNeutronListeners, self).setUp()
|
||||
|
||||
self.networks_plugin = self.initialized_plugins['OS::Neutron::Net']
|
||||
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 = {
|
||||
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.index_name = self.networks_plugin.alias_name_listener
|
||||
self.listener_alias = self.networks_plugin.alias_name_listener
|
||||
|
||||
def test_network_create_update_delete(self):
|
||||
'''Send network.create.end notification event to listener'''
|
||||
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)
|
||||
verification_keys = ['id', 'status', 'port_security_enabled', 'name']
|
||||
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'])
|
||||
|
||||
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)
|
||||
verification_keys = ['id', 'status', 'port_security_enabled', 'name']
|
||||
self._verify_result(update_event, verification_keys, result,
|
||||
inner_key='network')
|
||||
|
||||
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,
|
||||
owner=TENANT1)
|
||||
|
||||
def test_port_create_event(self):
|
||||
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)
|
||||
verification_keys = ['id', 'status', 'mac_address', 'status']
|
||||
self._verify_result(create_event, verification_keys, result,
|
||||
|
@ -147,7 +344,7 @@ class TestNeutronListener(test_listener.TestSearchListenerBase):
|
|||
|
||||
def test_port_rename_event(self):
|
||||
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)
|
||||
verification_keys = ['name']
|
||||
self._verify_result(update_event, verification_keys, result,
|
||||
|
@ -155,21 +352,21 @@ class TestNeutronListener(test_listener.TestSearchListenerBase):
|
|||
|
||||
def test_port_attach_detach_events(self):
|
||||
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)
|
||||
verification_keys = ['device_owner', 'device_id']
|
||||
self._verify_result(create_event, verification_keys, result,
|
||||
inner_key='port')
|
||||
|
||||
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)
|
||||
verification_keys = ['device_owner', 'device_id']
|
||||
self._verify_result(attach_event, verification_keys, result,
|
||||
inner_key='port')
|
||||
|
||||
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)
|
||||
verification_keys = ['device_owner', 'device_id']
|
||||
self._verify_result(detach_event, verification_keys, result,
|
||||
|
@ -177,6 +374,98 @@ class TestNeutronListener(test_listener.TestSearchListenerBase):
|
|||
|
||||
def test_port_delete_event(self):
|
||||
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,
|
||||
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::Neutron::Net',
|
||||
'OS::Neutron::Port',
|
||||
'OS::Neutron::Subnet',
|
||||
'OS::Neutron::Router',
|
||||
'OS::Cinder::Volume',
|
||||
'OS::Cinder::Snapshot'
|
||||
]
|
||||
|
|
|
@ -32,7 +32,9 @@ searchlight.index_backend =
|
|||
os_glance_metadef = searchlight.elasticsearch.plugins.glance.metadefs:MetadefIndex
|
||||
os_nova_server = searchlight.elasticsearch.plugins.nova.servers:ServerIndex
|
||||
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_router = searchlight.elasticsearch.plugins.neutron.routers:RouterIndex
|
||||
os_designate_recordset = searchlight.elasticsearch.plugins.designate.recordsets:RecordSetIndex
|
||||
os_designate_zone = searchlight.elasticsearch.plugins.designate.zones:ZoneIndex
|
||||
os_cinder_volume = searchlight.elasticsearch.plugins.cinder.volumes:VolumeIndex
|
||||
|
|
Loading…
Reference in New Issue