Merge "Central and local plugin (part 2, l3 functionality)"
This commit is contained in:
commit
2d43c3f7aa
|
@ -46,16 +46,9 @@ OVS_BRIDGE_MAPPINGS=bridge:br-bridge
|
|||
Q_ENABLE_TRICIRCLE=True
|
||||
enable_plugin tricircle https://github.com/openstack/tricircle/
|
||||
|
||||
# Tricircle Services
|
||||
enable_service t-api
|
||||
enable_service t-ngw
|
||||
enable_service t-cgw
|
||||
enable_service t-job
|
||||
|
||||
# Use Neutron instead of nova-network
|
||||
disable_service n-net
|
||||
enable_service q-svc
|
||||
enable_service q-svc1
|
||||
enable_service q-dhcp
|
||||
enable_service q-agt
|
||||
enable_service q-l3
|
||||
|
@ -68,3 +61,22 @@ disable_service n-obj
|
|||
disable_service c-bak
|
||||
disable_service tempest
|
||||
disable_service horizon
|
||||
|
||||
CENTRAL_REGION_NAME=CentralRegion
|
||||
TRICIRCLE_NEUTRON_PORT=20001
|
||||
|
||||
[[post-config|$NEUTRON_CONF]]
|
||||
|
||||
[DEFAULT]
|
||||
core_plugin=tricircle.network.local_plugin.TricirclePlugin
|
||||
|
||||
[client]
|
||||
admin_username=admin
|
||||
admin_password=$ADMIN_PASSWORD
|
||||
admin_tenant=demo
|
||||
auto_refresh_endpoint=True
|
||||
top_pod_name=$CENTRAL_REGION_NAME
|
||||
|
||||
[tricircle]
|
||||
real_core_plugin=neutron.plugins.ml2.plugin.Ml2Plugin
|
||||
central_neutron_url=http://127.0.0.1:$TRICIRCLE_NEUTRON_PORT
|
||||
|
|
|
@ -38,12 +38,11 @@ NEUTRON_CREATE_INITIAL_NETWORKS=False
|
|||
Q_USE_PROVIDERNET_FOR_PUBLIC=True
|
||||
|
||||
HOST_IP=10.250.201.25
|
||||
REGION_NAME=Pod2
|
||||
REGION_NAME=RegionTwo
|
||||
KEYSTONE_REGION_NAME=RegionOne
|
||||
SERVICE_HOST=$HOST_IP
|
||||
KEYSTONE_SERVICE_HOST=10.250.201.24
|
||||
KEYSTONE_AUTH_HOST=10.250.201.24
|
||||
GLANCE_SERVICE_HOST=10.250.201.24
|
||||
|
||||
Q_ML2_PLUGIN_VLAN_TYPE_OPTIONS=(network_vlan_ranges=bridge:2001:3000,extern:3001:4000)
|
||||
OVS_BRIDGE_MAPPINGS=bridge:br-bridge,extern:br-ext
|
||||
|
@ -60,8 +59,26 @@ enable_service c-vol
|
|||
enable_service c-sch
|
||||
|
||||
disable_service n-obj
|
||||
disable_service g-api
|
||||
disable_service g-reg
|
||||
disable_service c-bak
|
||||
disable_service tempest
|
||||
disable_service horizon
|
||||
|
||||
CENTRAL_REGION_NAME=CentralRegion
|
||||
TRICIRCLE_NEUTRON_PORT=20001
|
||||
|
||||
[[post-config|$NEUTRON_CONF]]
|
||||
|
||||
[DEFAULT]
|
||||
core_plugin=tricircle.network.local_plugin.TricirclePlugin
|
||||
|
||||
[client]
|
||||
admin_username=admin
|
||||
admin_password=$ADMIN_PASSWORD
|
||||
admin_tenant=demo
|
||||
auto_refresh_endpoint=True
|
||||
top_pod_name=$CENTRAL_REGION_NAME
|
||||
|
||||
[tricircle]
|
||||
real_core_plugin=neutron.plugins.ml2.plugin.Ml2Plugin
|
||||
# change the ip to the ip of the machine hosting central Neutron server
|
||||
central_neutron_url=http://10.250.201.24:$TRICIRCLE_NEUTRON_PORT
|
||||
|
|
|
@ -35,10 +35,6 @@ LIBVIRT_FIREWALL_DRIVER=nova.virt.firewall.NoopFirewallDriver
|
|||
Q_ENABLE_TRICIRCLE=True
|
||||
enable_plugin tricircle https://github.com/openstack/tricircle/
|
||||
|
||||
# Tricircle Services
|
||||
enable_service t-api
|
||||
enable_service t-job
|
||||
|
||||
# Use Neutron instead of nova-network
|
||||
disable_service n-net
|
||||
enable_service q-svc
|
||||
|
|
|
@ -86,7 +86,6 @@ function configure_tricircle_xjob {
|
|||
echo "Configuring Tricircle xjob"
|
||||
|
||||
init_common_tricircle_conf $TRICIRCLE_XJOB_CONF
|
||||
iniset $TRICIRCLE_XJOB_CONF DEFAULT enable_api_gateway False
|
||||
|
||||
setup_colorized_logging $TRICIRCLE_XJOB_CONF DEFAULT
|
||||
fi
|
||||
|
|
|
@ -59,6 +59,7 @@ ns_bridge_port_name = 'ns_bridge_port_%s_%s_%s'
|
|||
|
||||
dhcp_port_name = 'dhcp_port_%s' # subnet_id
|
||||
interface_port_name = 'interface_%s_%s' # b_pod_id t_subnet_id
|
||||
interface_port_device_id = 'reserved_gateway_port'
|
||||
|
||||
MAX_INT = 0x7FFFFFFF
|
||||
expire_time = datetime.datetime(2000, 1, 1)
|
||||
|
|
|
@ -18,6 +18,7 @@ import six
|
|||
import pecan
|
||||
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from tricircle.common import constants as cons
|
||||
import tricircle.common.exceptions as t_exceptions
|
||||
|
@ -126,6 +127,21 @@ def get_bottom_network_name(network):
|
|||
return '%s#%s' % (network['id'], network['name'])
|
||||
|
||||
|
||||
def get_id_from_name(_type, name):
|
||||
if _type == cons.RT_NETWORK:
|
||||
tokens = name.split('#')
|
||||
if len(tokens) == 2:
|
||||
id_candidate = tokens[1]
|
||||
else:
|
||||
id_candidate = tokens[0]
|
||||
else:
|
||||
id_candidate = name
|
||||
if uuidutils.is_uuid_like(id_candidate):
|
||||
return id_candidate
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def format_error(code, message, error_type=None):
|
||||
error_type_map = {400: 'badRequest',
|
||||
403: 'forbidden',
|
||||
|
|
|
@ -57,9 +57,8 @@ def get_pod(context, pod_id):
|
|||
|
||||
|
||||
def list_pods(context, filters=None, sorts=None):
|
||||
with context.session.begin():
|
||||
return core.query_resource(context, models.Pod, filters or [],
|
||||
sorts or [])
|
||||
return core.query_resource(context, models.Pod, filters or [],
|
||||
sorts or [])
|
||||
|
||||
|
||||
def update_pod(context, pod_id, update_dict):
|
||||
|
@ -116,9 +115,8 @@ def get_pod_service_configuration(context, config_id):
|
|||
|
||||
|
||||
def list_pod_service_configurations(context, filters=None, sorts=None):
|
||||
with context.session.begin():
|
||||
return core.query_resource(context, models.PodServiceConfiguration,
|
||||
filters or [], sorts or [])
|
||||
return core.query_resource(context, models.PodServiceConfiguration,
|
||||
filters or [], sorts or [])
|
||||
|
||||
|
||||
def update_pod_service_configuration(context, config_id, update_dict):
|
||||
|
|
|
@ -386,6 +386,19 @@ class TricirclePlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||
context, subnet_id, subnet)
|
||||
|
||||
def create_port(self, context, port):
|
||||
port_body = port['port']
|
||||
if port_body['device_id'] == t_constants.interface_port_device_id:
|
||||
_, region_name, subnet_id = port_body['name'].split('_')
|
||||
gateway_port_body = self.helper.get_create_interface_body(
|
||||
port_body['tenant_id'], port_body['network_id'], region_name,
|
||||
subnet_id)
|
||||
t_ctx = t_context.get_context_from_neutron_context(context)
|
||||
pod = db_api.get_pod_by_name(t_ctx, region_name)
|
||||
_, t_gateway_id = self.helper.prepare_top_element(
|
||||
t_ctx, context, port_body['tenant_id'], pod,
|
||||
{'id': port_body['name']}, t_constants.RT_PORT,
|
||||
gateway_port_body)
|
||||
return super(TricirclePlugin, self).get_port(context, t_gateway_id)
|
||||
db_port = super(TricirclePlugin, self).create_port_db(context, port)
|
||||
return self._make_port_dict(db_port)
|
||||
|
||||
|
@ -414,6 +427,20 @@ class TricirclePlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||
db_api.create_resource_mapping(t_ctx, resource_id, resource_id,
|
||||
pod['pod_id'], res['tenant_id'],
|
||||
resource_type)
|
||||
|
||||
interfaces = super(TricirclePlugin, self).get_ports(
|
||||
context,
|
||||
{'network_id': [res['network_id']],
|
||||
'device_owner': [constants.DEVICE_OWNER_ROUTER_INTF]})
|
||||
interfaces = [inf for inf in interfaces if inf['device_id']]
|
||||
if interfaces:
|
||||
# request may be come from service, we use an admin context
|
||||
# to run the xjob
|
||||
admin_context = t_context.get_admin_context()
|
||||
self.xjob_handler.setup_bottom_router(
|
||||
admin_context, res['network_id'],
|
||||
interfaces[0]['device_id'], pod['pod_id'])
|
||||
|
||||
return res
|
||||
|
||||
def delete_port(self, context, port_id, l3_port_check=True):
|
||||
|
|
|
@ -32,3 +32,8 @@ class BottomPodOperationFailure(exceptions.NeutronException):
|
|||
|
||||
class DhcpPortNotFound(exceptions.NotFound):
|
||||
message = _('Dhcp port for subnet %(subnet_id)s not found')
|
||||
|
||||
|
||||
class GatewayPortNotFound(exceptions.NotFound):
|
||||
message = _('Gateway port for subnet %(subnet_id)s and region %(region)s '
|
||||
'not found')
|
||||
|
|
|
@ -28,7 +28,9 @@ from tricircle.common import client # noqa
|
|||
import tricircle.common.constants as t_constants
|
||||
import tricircle.common.context as t_context
|
||||
from tricircle.common.i18n import _
|
||||
|
||||
from tricircle.common import resource_handle
|
||||
import tricircle.common.utils as t_utils
|
||||
import tricircle.network.exceptions as t_exceptions
|
||||
from tricircle.network import helper
|
||||
|
||||
|
@ -59,6 +61,18 @@ class TricirclePlugin(plugin.Ml2Plugin):
|
|||
self.neutron_handle.endpoint_url = \
|
||||
cfg.CONF.tricircle.central_neutron_url
|
||||
|
||||
def start_rpc_listeners(self):
|
||||
return self.core_plugin.start_rpc_listeners()
|
||||
|
||||
def start_rpc_state_reports_listener(self):
|
||||
return self.core_plugin.start_rpc_state_reports_listener()
|
||||
|
||||
def rpc_workers_supported(self):
|
||||
return self.core_plugin.rpc_workers_supported()
|
||||
|
||||
def rpc_state_report_workers_supported(self):
|
||||
return self.core_plugin.rpc_state_report_workers_supported()
|
||||
|
||||
@staticmethod
|
||||
def _adapt_network_body(network):
|
||||
network_type = network.get('provider:network_type')
|
||||
|
@ -147,6 +161,43 @@ class TricirclePlugin(plugin.Ml2Plugin):
|
|||
dhcp_port_body['port']['id'] = t_ports[0]['id']
|
||||
self.core_plugin.create_port(q_ctx, dhcp_port_body)
|
||||
|
||||
def _ensure_gateway_port(self, t_ctx, t_subnet):
|
||||
region_name = cfg.CONF.nova.region_name
|
||||
gateway_port_name = t_constants.interface_port_name % (region_name,
|
||||
t_subnet['id'])
|
||||
gateway_port_body = {
|
||||
'port': {'tenant_id': t_subnet['tenant_id'],
|
||||
'admin_state_up': True,
|
||||
'name': gateway_port_name,
|
||||
'network_id': t_subnet['network_id'],
|
||||
'device_id': t_constants.interface_port_device_id}}
|
||||
try:
|
||||
return self.neutron_handle.handle_create(
|
||||
t_ctx, t_constants.RT_PORT, gateway_port_body)
|
||||
except Exception:
|
||||
raw_client = self.neutron_handle._get_client(t_ctx)
|
||||
params = {'name': gateway_port_name}
|
||||
t_ports = raw_client.list_ports(**params)['ports']
|
||||
if not t_ports:
|
||||
raise t_exceptions.GatewayPortNotFound(
|
||||
subnet_id=t_subnet['id'], region=region_name)
|
||||
return t_ports[0]
|
||||
|
||||
def create_network(self, context, network):
|
||||
# this method is overwritten for bottom bridge network and external
|
||||
# network creation, for internal network, get_network and get_networks
|
||||
# will do the trick
|
||||
net_body = network['network']
|
||||
self._adapt_network_body(net_body)
|
||||
if net_body['name']:
|
||||
net_id = t_utils.get_id_from_name(t_constants.RT_NETWORK,
|
||||
net_body['name'])
|
||||
if net_id:
|
||||
net_body['id'] = net_id
|
||||
b_network = self.core_plugin.create_network(context,
|
||||
{'network': net_body})
|
||||
return b_network
|
||||
|
||||
def get_network(self, context, _id, fields=None):
|
||||
try:
|
||||
b_network = self.core_plugin.get_network(context, _id, fields)
|
||||
|
@ -174,12 +225,14 @@ class TricirclePlugin(plugin.Ml2Plugin):
|
|||
return self.core_plugin.get_networks(
|
||||
context, filters, fields, sorts, limit, marker, page_reverse)
|
||||
|
||||
b_networks = self.core_plugin.get_networks(
|
||||
context, filters, fields, sorts, limit, marker, page_reverse)
|
||||
for b_network in b_networks:
|
||||
b_full_networks = self.core_plugin.get_networks(
|
||||
context, filters, None, sorts, limit, marker, page_reverse)
|
||||
b_networks = []
|
||||
for b_network in b_full_networks:
|
||||
subnet_ids = self._ensure_subnet(context, b_network, False)
|
||||
if subnet_ids:
|
||||
b_network['subnets'] = subnet_ids
|
||||
b_networks.append(self._fields(b_network, fields))
|
||||
|
||||
if len(b_networks) == len(filters['id']):
|
||||
return b_networks
|
||||
|
@ -206,6 +259,31 @@ class TricirclePlugin(plugin.Ml2Plugin):
|
|||
b_networks.append(self._fields(b_network, fields))
|
||||
return b_networks
|
||||
|
||||
def create_subnet(self, context, subnet):
|
||||
# this method is overwritten for bottom bridge subnet and external
|
||||
# subnet creation, for internal subnet, get_subnet and get_subnets
|
||||
# will do the trick
|
||||
subnet_body = subnet['subnet']
|
||||
if subnet_body['name']:
|
||||
subnet_id = t_utils.get_id_from_name(t_constants.RT_SUBNET,
|
||||
subnet_body['name'])
|
||||
if subnet_id:
|
||||
subnet_body['id'] = subnet_id
|
||||
b_subnet = self.core_plugin.create_subnet(context,
|
||||
{'subnet': subnet_body})
|
||||
return b_subnet
|
||||
|
||||
def _create_bottom_subnet(self, t_ctx, q_ctx, t_subnet):
|
||||
gateway_port = self._ensure_gateway_port(t_ctx, t_subnet)
|
||||
subnet_body = helper.NetworkHelper.get_create_subnet_body(
|
||||
gateway_port['tenant_id'], t_subnet, t_subnet['network_id'],
|
||||
gateway_port['fixed_ips'][0]['ip_address'])['subnet']
|
||||
t_subnet['gateway_ip'] = subnet_body['gateway_ip']
|
||||
t_subnet['allocation_pools'] = subnet_body['allocation_pools']
|
||||
|
||||
b_subnet = self.core_plugin.create_subnet(q_ctx, {'subnet': t_subnet})
|
||||
return b_subnet
|
||||
|
||||
def get_subnet(self, context, _id, fields=None):
|
||||
t_ctx = t_context.get_context_from_neutron_context(context)
|
||||
try:
|
||||
|
@ -214,11 +292,9 @@ class TricirclePlugin(plugin.Ml2Plugin):
|
|||
t_subnet = self.neutron_handle.handle_get(t_ctx, 'subnet', _id)
|
||||
if not t_subnet:
|
||||
raise q_exceptions.SubnetNotFound(subnet_id=_id)
|
||||
b_subnet = self.core_plugin.create_subnet(context,
|
||||
{'subnet': t_subnet})
|
||||
b_subnet = self._create_bottom_subnet(t_ctx, context, t_subnet)
|
||||
if b_subnet['enable_dhcp']:
|
||||
self._ensure_subnet_dhcp_port(t_ctx, context, b_subnet)
|
||||
|
||||
return self._fields(b_subnet, fields)
|
||||
|
||||
def get_subnets(self, context, filters=None, fields=None, sorts=None,
|
||||
|
@ -232,10 +308,13 @@ class TricirclePlugin(plugin.Ml2Plugin):
|
|||
context, filters, fields, sorts, limit, marker, page_reverse)
|
||||
|
||||
t_ctx = t_context.get_context_from_neutron_context(context)
|
||||
b_subnets = self.core_plugin.get_subnets(
|
||||
context, filters, fields, sorts, limit, marker, page_reverse)
|
||||
for b_subnet in b_subnets:
|
||||
self._ensure_subnet_dhcp_port(t_ctx, context, b_subnet)
|
||||
b_full_subnets = self.core_plugin.get_subnets(
|
||||
context, filters, None, sorts, limit, marker, page_reverse)
|
||||
b_subnets = []
|
||||
for b_subnet in b_full_subnets:
|
||||
if b_subnet['enable_dhcp']:
|
||||
self._ensure_subnet_dhcp_port(t_ctx, context, b_subnet)
|
||||
b_subnets.append(self._fields(b_subnet, fields))
|
||||
if len(b_subnets) == len(filters['id']):
|
||||
return b_subnets
|
||||
|
||||
|
@ -251,13 +330,19 @@ class TricirclePlugin(plugin.Ml2Plugin):
|
|||
missing_subnets = [subnet for subnet in t_subnets if (
|
||||
subnet['id'] in missing_id_set)]
|
||||
for subnet in missing_subnets:
|
||||
b_subnet = self.core_plugin.create_subnet(
|
||||
context, {'subnet': subnet})
|
||||
b_subnet = self._create_bottom_subnet(t_ctx, context, subnet)
|
||||
if b_subnet['enable_dhcp']:
|
||||
self._ensure_subnet_dhcp_port(t_ctx, context, b_subnet)
|
||||
b_subnets.append(self._fields(b_subnet, fields))
|
||||
return b_subnets
|
||||
|
||||
@staticmethod
|
||||
def _is_special_port(port):
|
||||
return port.get('device_owner') in (
|
||||
q_constants.DEVICE_OWNER_ROUTER_INTF,
|
||||
q_constants.DEVICE_OWNER_FLOATINGIP,
|
||||
q_constants.DEVICE_OWNER_ROUTER_GW)
|
||||
|
||||
def create_port(self, context, port):
|
||||
port_body = port['port']
|
||||
network_id = port_body['network_id']
|
||||
|
@ -268,25 +353,34 @@ class TricirclePlugin(plugin.Ml2Plugin):
|
|||
raw_client = self.neutron_handle._get_client(t_ctx)
|
||||
|
||||
if port_body['fixed_ips'] is not q_constants.ATTR_NOT_SPECIFIED:
|
||||
fixed_ip = port_body['fixed_ips'][0]
|
||||
ip_address = fixed_ip.get('ip_address')
|
||||
if not ip_address:
|
||||
# dhcp agent may request to create a dhcp port without
|
||||
# specifying ip address, we just raise an exception to reject
|
||||
# this request
|
||||
raise q_exceptions.InvalidIpForNetwork(ip_address='None')
|
||||
params = {'fixed_ips': 'ip_address=%s' % ip_address}
|
||||
t_ports = raw_client.list_ports(**params)['ports']
|
||||
if not t_ports:
|
||||
raise q_exceptions.InvalidIpForNetwork(
|
||||
ip_address=fixed_ip['ip_address'])
|
||||
t_port = t_ports[0]
|
||||
if not self._is_special_port(port_body):
|
||||
fixed_ip = port_body['fixed_ips'][0]
|
||||
ip_address = fixed_ip.get('ip_address')
|
||||
if not ip_address:
|
||||
# dhcp agent may request to create a dhcp port without
|
||||
# specifying ip address, we just raise an exception to
|
||||
# reject this request
|
||||
raise q_exceptions.InvalidIpForNetwork(ip_address='None')
|
||||
params = {'fixed_ips': 'ip_address=%s' % ip_address}
|
||||
t_ports = raw_client.list_ports(**params)['ports']
|
||||
if not t_ports:
|
||||
raise q_exceptions.InvalidIpForNetwork(
|
||||
ip_address=fixed_ip['ip_address'])
|
||||
t_port = t_ports[0]
|
||||
else:
|
||||
t_port = port_body
|
||||
else:
|
||||
self._adapt_port_body_for_client(port['port'])
|
||||
t_port = raw_client.create_port(port)['port']
|
||||
subnet_id = t_port['fixed_ips'][0]['subnet_id']
|
||||
# get_subnet will create bottom subnet if it doesn't exist
|
||||
self.get_subnet(context, subnet_id)
|
||||
|
||||
if not self._is_special_port(port_body):
|
||||
subnet_id = t_port['fixed_ips'][0]['subnet_id']
|
||||
# get_subnet will create bottom subnet if it doesn't exist
|
||||
self.get_subnet(context, subnet_id)
|
||||
|
||||
for field in ('name', 'device_id'):
|
||||
if port_body.get(field):
|
||||
t_port[field] = port_body[field]
|
||||
b_port = self.core_plugin.create_port(context, {'port': t_port})
|
||||
return b_port
|
||||
|
||||
|
|
|
@ -1020,9 +1020,11 @@ class PluginTest(unittest.TestCase,
|
|||
core.initialize()
|
||||
core.ModelBase.metadata.create_all(core.get_engine())
|
||||
cfg.CONF.register_opts(q_config.core_opts)
|
||||
cfg.CONF.register_opts(plugin.tricircle_opts)
|
||||
plugin_path = \
|
||||
'tricircle.tests.unit.network.test_central_plugin.FakePlugin'
|
||||
cfg.CONF.set_override('core_plugin', plugin_path)
|
||||
cfg.CONF.set_override('enable_api_gateway', True)
|
||||
self.context = context.Context()
|
||||
self.save_method = manager.NeutronManager._get_default_service_plugins
|
||||
manager.NeutronManager._get_default_service_plugins = mock.Mock()
|
||||
|
@ -2110,16 +2112,16 @@ class PluginTest(unittest.TestCase,
|
|||
b_bridge_net_id = db_api.get_bottom_id_by_top_id_pod_name(
|
||||
t_ctx, net['id'], 'pod_1', constants.RT_NETWORK)
|
||||
calls = [mock.call(t_ctx,
|
||||
{'floatingip': {
|
||||
'floating_network_id': b_bridge_net_id,
|
||||
'floating_ip_address': '100.128.0.3',
|
||||
'port_id': b_port_id}}),
|
||||
mock.call(t_ctx,
|
||||
{'floatingip': {
|
||||
'floating_network_id': b_ext_net_id,
|
||||
'floating_ip_address': fip[
|
||||
'floating_ip_address'],
|
||||
'port_id': ns_bridge_port['id']}}),
|
||||
mock.call(t_ctx,
|
||||
{'floatingip': {
|
||||
'floating_network_id': b_bridge_net_id,
|
||||
'floating_ip_address': '100.128.0.3',
|
||||
'port_id': b_port_id}})]
|
||||
'port_id': ns_bridge_port['id']}})]
|
||||
mock_create.assert_has_calls(calls)
|
||||
|
||||
@patch.object(driver.Pool, 'get_instance', new=fake_get_instance)
|
||||
|
|
|
@ -19,6 +19,7 @@ from mock import patch
|
|||
import six
|
||||
import unittest
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
import neutron_lib.constants as q_constants
|
||||
|
@ -106,6 +107,9 @@ class FakeCorePlugin(object):
|
|||
create_resource('port', False, port['port'])
|
||||
return port['port']
|
||||
|
||||
def update_port(self, context, _id, port):
|
||||
pass
|
||||
|
||||
def get_port(self, context, _id, fields=None):
|
||||
return get_resource('port', False, _id)
|
||||
|
||||
|
@ -180,6 +184,15 @@ class FakeNeutronHandle(object):
|
|||
def handle_get(self, context, _type, _id):
|
||||
return get_resource(_type, True, _id)
|
||||
|
||||
def handle_create(self, context, _type, body):
|
||||
if _type == 'port':
|
||||
return FakeClient().create_port(body)['port']
|
||||
create_resource(_type, True, body[_type])
|
||||
return body[_type]
|
||||
|
||||
def handle_update(self, context, _type, _id, body):
|
||||
pass
|
||||
|
||||
|
||||
class FakePlugin(plugin.TricirclePlugin):
|
||||
def __init__(self):
|
||||
|
@ -207,6 +220,9 @@ class PluginTest(unittest.TestCase):
|
|||
'name': 'subnet1',
|
||||
'network_id': network_id,
|
||||
'cidr': '10.0.1.0/24',
|
||||
'ip_version': 4,
|
||||
'allocation_pools': [{'start': '10.0.1.2',
|
||||
'end': '10.0.1.254'}],
|
||||
'enable_dhcp': True}
|
||||
t_port = {'id': port_id,
|
||||
'tenant_id': self.tenant_id,
|
||||
|
@ -232,10 +248,26 @@ class PluginTest(unittest.TestCase):
|
|||
b_port = get_resource('port', False, port['id'])
|
||||
b_net.pop('project_id')
|
||||
b_subnet.pop('project_id')
|
||||
pool = subnet.pop('allocation_pools')[0]
|
||||
b_pools = b_subnet.pop('allocation_pools')
|
||||
b_gateway_ip = b_subnet.pop('gateway_ip')
|
||||
|
||||
def ip_to_digit(ip):
|
||||
return int(ip[ip.rindex('.') + 1:])
|
||||
|
||||
pool_range = range(ip_to_digit(pool['start']),
|
||||
ip_to_digit(pool['end']) + 1)
|
||||
b_pool_range1 = range(ip_to_digit(b_pools[0]['start']),
|
||||
ip_to_digit(b_pools[0]['end']) + 1)
|
||||
b_pool_range2 = range(ip_to_digit(b_pools[1]['start']),
|
||||
ip_to_digit(b_pools[1]['end']) + 1)
|
||||
b_pool_range = b_pool_range1 + [
|
||||
ip_to_digit(b_gateway_ip)] + b_pool_range2
|
||||
port.pop('name')
|
||||
b_port.pop('name')
|
||||
self.assertDictEqual(net, b_net)
|
||||
self.assertDictEqual(subnet, b_subnet)
|
||||
self.assertEqual(pool_range, b_pool_range)
|
||||
self.assertEqual('vlan', b_net_type)
|
||||
self.assertDictEqual(port, b_port)
|
||||
|
||||
|
@ -329,6 +361,19 @@ class PluginTest(unittest.TestCase):
|
|||
b_port.pop('project_id')
|
||||
self.assertDictEqual(t_ports[i], b_port)
|
||||
|
||||
@patch.object(t_context, 'get_context_from_neutron_context')
|
||||
@patch.object(FakeNeutronHandle, 'handle_update')
|
||||
def test_update_port(self, mock_update, mock_context):
|
||||
cfg.CONF.set_override('region_name', 'Pod1', 'nova')
|
||||
mock_context.return_value = self.context
|
||||
update_body = {'port': {'device_owner': 'compute:None',
|
||||
'binding:host_id': 'fake_host'}}
|
||||
port_id = 'fake_port_id'
|
||||
self.plugin.update_port(self.context, port_id, update_body)
|
||||
mock_update.assert_called_once_with(
|
||||
self.context, 'port', port_id,
|
||||
{'port': {'binding:profile': {'region': 'Pod1'}}})
|
||||
|
||||
def tearDown(self):
|
||||
for res in RES_LIST:
|
||||
del res[:]
|
||||
|
|
|
@ -385,9 +385,13 @@ class XManager(PeriodicTasks):
|
|||
t_subnet_id = t_port['fixed_ips'][0]['subnet_id']
|
||||
t_subnet = t_client.get_subnets(ctx, t_subnet_id)
|
||||
|
||||
(b_net_id,
|
||||
subnet_map) = self.helper.prepare_bottom_network_subnets(
|
||||
ctx, q_ctx, project_id, b_pod, t_net, [t_subnet])
|
||||
if CONF.enable_api_gateway:
|
||||
(b_net_id,
|
||||
subnet_map) = self.helper.prepare_bottom_network_subnets(
|
||||
ctx, q_ctx, project_id, b_pod, t_net, [t_subnet])
|
||||
else:
|
||||
(b_net_id,
|
||||
subnet_map) = (t_net['id'], {t_subnet['id']: t_subnet['id']})
|
||||
|
||||
# the gateway ip of bottom subnet is set to the ip of t_port, so
|
||||
# we just attach the bottom subnet to the bottom router and neutron
|
||||
|
@ -456,13 +460,14 @@ class XManager(PeriodicTasks):
|
|||
_, b_ns_bridge_port_id = self.helper.prepare_bottom_element(
|
||||
ctx, project_id, b_ext_pod, t_ns_bridge_port,
|
||||
constants.RT_PORT, port_body)
|
||||
self._safe_create_bottom_floatingip(
|
||||
ctx, b_ext_pod, b_ext_client, b_ext_net_id, add_fip,
|
||||
b_ns_bridge_port_id)
|
||||
# swap these two lines
|
||||
self._safe_create_bottom_floatingip(
|
||||
ctx, b_pod, b_client, b_ns_bridge_net_id,
|
||||
t_ns_bridge_port['fixed_ips'][0]['ip_address'],
|
||||
b_int_port_id)
|
||||
self._safe_create_bottom_floatingip(
|
||||
ctx, b_ext_pod, b_ext_client, b_ext_net_id, add_fip,
|
||||
b_ns_bridge_port_id)
|
||||
else:
|
||||
self._safe_create_bottom_floatingip(
|
||||
ctx, b_pod, b_client, b_ext_net_id, add_fip,
|
||||
|
|
|
@ -55,7 +55,10 @@ common_opts = [
|
|||
help=_("Running job is considered expires after this time, in"
|
||||
" seconds")),
|
||||
cfg.FloatOpt('worker_sleep_time', default=0.1,
|
||||
help=_("Seconds a worker sleeps after one run in a loop"))
|
||||
help=_("Seconds a worker sleeps after one run in a loop")),
|
||||
cfg.BoolOpt('enable_api_gateway',
|
||||
default=False,
|
||||
help=_('Whether the Nova API gateway is enabled'))
|
||||
]
|
||||
|
||||
service_opts = [
|
||||
|
|
Loading…
Reference in New Issue