Add multi-segment support
Neutron ML2 mechanisms allows multiple network segments. A net-show call with a multi-segment setup won't return a single network-type or segmentation id. Instead it returns a list of it with a certain hierarchy. Co-Authored-By: Daniel Gonzalez <daniel@gonzalez-nothnagel.de> Change-Id: I3570752920d897c11cacb9e4a0b0d012ae2ce13a Partially-Implements: bp manila-hpb-support
This commit is contained in:
parent
345b8021ec
commit
8328ebde24
@ -29,6 +29,16 @@ from manila import utils
|
|||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
neutron_network_plugin_opts = [
|
||||||
|
cfg.StrOpt(
|
||||||
|
'neutron_physical_net_name',
|
||||||
|
help="The name of the physical network to determine which net segment "
|
||||||
|
"is used. This opt is optional and will only be used for "
|
||||||
|
"networks configured with multiple segments.",
|
||||||
|
default=None,
|
||||||
|
deprecated_group='DEFAULT'),
|
||||||
|
]
|
||||||
|
|
||||||
neutron_single_network_plugin_opts = [
|
neutron_single_network_plugin_opts = [
|
||||||
cfg.StrOpt(
|
cfg.StrOpt(
|
||||||
'neutron_net_id',
|
'neutron_net_id',
|
||||||
@ -95,6 +105,9 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
|||||||
self._neutron_api_args = args
|
self._neutron_api_args = args
|
||||||
self._neutron_api_kwargs = kwargs
|
self._neutron_api_kwargs = kwargs
|
||||||
self._label = kwargs.pop('label', 'user')
|
self._label = kwargs.pop('label', 'user')
|
||||||
|
CONF.register_opts(
|
||||||
|
neutron_network_plugin_opts,
|
||||||
|
group=self.neutron_api.config_group_name)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def label(self):
|
def label(self):
|
||||||
@ -108,6 +121,10 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
|||||||
**self._neutron_api_kwargs)
|
**self._neutron_api_kwargs)
|
||||||
return self._neutron_api
|
return self._neutron_api
|
||||||
|
|
||||||
|
def _store_neutron_net_info(self, context, share_network):
|
||||||
|
self._save_neutron_network_data(context, share_network)
|
||||||
|
self._save_neutron_subnet_data(context, share_network)
|
||||||
|
|
||||||
def allocate_network(self, context, share_server, share_network=None,
|
def allocate_network(self, context, share_server, share_network=None,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
"""Allocate network resources using given network information.
|
"""Allocate network resources using given network information.
|
||||||
@ -128,8 +145,7 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
|||||||
raise exception.NetworkBadConfigurationException(reason=msg)
|
raise exception.NetworkBadConfigurationException(reason=msg)
|
||||||
|
|
||||||
self._verify_share_network(share_server['id'], share_network)
|
self._verify_share_network(share_server['id'], share_network)
|
||||||
self._save_neutron_network_data(context, share_network)
|
self._store_neutron_net_info(context, share_network)
|
||||||
self._save_neutron_subnet_data(context, share_network)
|
|
||||||
|
|
||||||
allocation_count = kwargs.get('count', 1)
|
allocation_count = kwargs.get('count', 1)
|
||||||
device_owner = kwargs.get('device_owner', 'share')
|
device_owner = kwargs.get('device_owner', 'share')
|
||||||
@ -181,8 +197,8 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
|||||||
'mac_address': port['mac_address'],
|
'mac_address': port['mac_address'],
|
||||||
'status': constants.STATUS_ACTIVE,
|
'status': constants.STATUS_ACTIVE,
|
||||||
'label': self.label,
|
'label': self.label,
|
||||||
'network_type': share_network['network_type'],
|
'network_type': share_network.get('network_type'),
|
||||||
'segmentation_id': share_network['segmentation_id'],
|
'segmentation_id': share_network.get('segmentation_id'),
|
||||||
'ip_version': share_network['ip_version'],
|
'ip_version': share_network['ip_version'],
|
||||||
'cidr': share_network['cidr'],
|
'cidr': share_network['cidr'],
|
||||||
'mtu': share_network['mtu'],
|
'mtu': share_network['mtu'],
|
||||||
@ -203,13 +219,43 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
|||||||
extensions = self.neutron_api.list_extensions()
|
extensions = self.neutron_api.list_extensions()
|
||||||
return neutron_constants.PROVIDER_NW_EXT in extensions
|
return neutron_constants.PROVIDER_NW_EXT in extensions
|
||||||
|
|
||||||
|
def _is_neutron_multi_segment(self, share_network, net_info=None):
|
||||||
|
if net_info is None:
|
||||||
|
net_info = self.neutron_api.get_network(
|
||||||
|
share_network['neutron_net_id'])
|
||||||
|
return 'segments' in net_info
|
||||||
|
|
||||||
def _save_neutron_network_data(self, context, share_network):
|
def _save_neutron_network_data(self, context, share_network):
|
||||||
net_info = self.neutron_api.get_network(
|
net_info = self.neutron_api.get_network(
|
||||||
share_network['neutron_net_id'])
|
share_network['neutron_net_id'])
|
||||||
|
segmentation_id = None
|
||||||
|
network_type = None
|
||||||
|
|
||||||
|
if self._is_neutron_multi_segment(share_network, net_info):
|
||||||
|
# we have a multi segment network and need to identify the
|
||||||
|
# lowest segment used for binding
|
||||||
|
phy_nets = []
|
||||||
|
phy = self.neutron_api.configuration.neutron_physical_net_name
|
||||||
|
if not phy:
|
||||||
|
msg = "Cannot identify segment used for binding. Please add "
|
||||||
|
"neutron_physical_net_name in configuration."
|
||||||
|
raise exception.NetworkBadConfigurationException(reason=msg)
|
||||||
|
for segment in net_info['segments']:
|
||||||
|
phy_nets.append(segment['provider:physical_network'])
|
||||||
|
if segment['provider:physical_network'] == phy:
|
||||||
|
segmentation_id = segment['provider:segmentation_id']
|
||||||
|
network_type = segment['provider:network_type']
|
||||||
|
if not (segmentation_id and network_type):
|
||||||
|
msg = ("No matching neutron_physical_net_name found for %s "
|
||||||
|
"(found: %s)." % (phy, phy_nets))
|
||||||
|
raise exception.NetworkBadConfigurationException(reason=msg)
|
||||||
|
else:
|
||||||
|
network_type = net_info['provider:network_type']
|
||||||
|
segmentation_id = net_info['provider:segmentation_id']
|
||||||
|
|
||||||
provider_nw_dict = {
|
provider_nw_dict = {
|
||||||
'network_type': net_info['provider:network_type'],
|
'network_type': network_type,
|
||||||
'segmentation_id': net_info['provider:segmentation_id'],
|
'segmentation_id': segmentation_id,
|
||||||
'mtu': net_info['mtu'],
|
'mtu': net_info['mtu'],
|
||||||
}
|
}
|
||||||
share_network.update(provider_nw_dict)
|
share_network.update(provider_nw_dict)
|
||||||
@ -377,6 +423,23 @@ class NeutronBindNetworkPlugin(NeutronNetworkPlugin):
|
|||||||
"local_link_information": local_links}
|
"local_link_information": local_links}
|
||||||
return arguments
|
return arguments
|
||||||
|
|
||||||
|
def _store_neutron_net_info(self, context, share_network):
|
||||||
|
"""Store the Neutron network info.
|
||||||
|
|
||||||
|
In case of dynamic multi segments the segment is determined while
|
||||||
|
binding the port. Therefore this method will return for multi segments
|
||||||
|
network without storing network information.
|
||||||
|
|
||||||
|
Instead, multi segments network will wait until ports are bound and
|
||||||
|
then store network information (see allocate_network()).
|
||||||
|
"""
|
||||||
|
if self._is_neutron_multi_segment(share_network):
|
||||||
|
# In case of dynamic multi segment the segment is determined while
|
||||||
|
# binding the port
|
||||||
|
return
|
||||||
|
super(NeutronBindNetworkPlugin, self)._store_neutron_net_info(
|
||||||
|
context, share_network)
|
||||||
|
|
||||||
def allocate_network(self, context, share_server, share_network=None,
|
def allocate_network(self, context, share_server, share_network=None,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
ports = super(NeutronBindNetworkPlugin, self).allocate_network(
|
ports = super(NeutronBindNetworkPlugin, self).allocate_network(
|
||||||
@ -389,6 +452,19 @@ class NeutronBindNetworkPlugin(NeutronNetworkPlugin):
|
|||||||
# order to update the ports with the correct binding.
|
# order to update the ports with the correct binding.
|
||||||
if self.config.neutron_vnic_type != 'normal':
|
if self.config.neutron_vnic_type != 'normal':
|
||||||
self._wait_for_ports_bind(ports, share_server)
|
self._wait_for_ports_bind(ports, share_server)
|
||||||
|
if self._is_neutron_multi_segment(share_network):
|
||||||
|
# update segment information after port bind
|
||||||
|
super(NeutronBindNetworkPlugin, self)._store_neutron_net_info(
|
||||||
|
context, share_network)
|
||||||
|
for num, port in enumerate(ports):
|
||||||
|
port_info = {
|
||||||
|
'network_type': share_network['network_type'],
|
||||||
|
'segmentation_id': share_network['segmentation_id'],
|
||||||
|
'cidr': share_network['cidr'],
|
||||||
|
'ip_version': share_network['ip_version'],
|
||||||
|
}
|
||||||
|
ports[num] = self.db.network_allocation_update(
|
||||||
|
context, port['id'], port_info)
|
||||||
return ports
|
return ports
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,8 +73,8 @@ fake_neutron_network = {
|
|||||||
|
|
||||||
fake_share_network = {
|
fake_share_network = {
|
||||||
'id': 'fake nw info id',
|
'id': 'fake nw info id',
|
||||||
'neutron_subnet_id': 'fake subnet id',
|
'neutron_subnet_id': fake_neutron_network['subnets'][0],
|
||||||
'neutron_net_id': 'fake net id',
|
'neutron_net_id': fake_neutron_network['id'],
|
||||||
'project_id': 'fake project id',
|
'project_id': 'fake project id',
|
||||||
'status': 'test_subnet_status',
|
'status': 'test_subnet_status',
|
||||||
'name': 'fake name',
|
'name': 'fake name',
|
||||||
@ -111,6 +111,77 @@ fake_network_allocation = {
|
|||||||
'mtu': 1509,
|
'mtu': 1509,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fake_nw_info = {
|
||||||
|
'segments': [
|
||||||
|
{
|
||||||
|
'provider:network_type': 'vlan',
|
||||||
|
'provider:physical_network': 'net1',
|
||||||
|
'provider:segmentation_id': 3926,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'provider:network_type': 'vxlan',
|
||||||
|
'provider:physical_network': None,
|
||||||
|
'provider:segmentation_id': 2000,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'mtu': 1509,
|
||||||
|
}
|
||||||
|
|
||||||
|
fake_neutron_network_multi = {
|
||||||
|
'admin_state_up': True,
|
||||||
|
'availability_zone_hints': [],
|
||||||
|
'availability_zones': ['nova'],
|
||||||
|
'description': '',
|
||||||
|
'id': 'fake net id',
|
||||||
|
'ipv4_address_scope': None,
|
||||||
|
'ipv6_address_scope': None,
|
||||||
|
'name': 'test_neutron_network',
|
||||||
|
'port_security_enabled': True,
|
||||||
|
'router:external': False,
|
||||||
|
'shared': False,
|
||||||
|
'status': 'ACTIVE',
|
||||||
|
'subnets': ['fake subnet id',
|
||||||
|
'fake subnet id 2'],
|
||||||
|
'segments': fake_nw_info['segments'],
|
||||||
|
'mtu': fake_nw_info['mtu'],
|
||||||
|
}
|
||||||
|
|
||||||
|
fake_share_network_multi = {
|
||||||
|
'id': 'fake nw info id',
|
||||||
|
'neutron_subnet_id': fake_neutron_network_multi['subnets'][0],
|
||||||
|
'neutron_net_id': fake_neutron_network_multi['id'],
|
||||||
|
'project_id': 'fake project id',
|
||||||
|
'status': 'test_subnet_status',
|
||||||
|
'name': 'fake name',
|
||||||
|
'description': 'fake description',
|
||||||
|
'security_services': [],
|
||||||
|
'ip_version': 4,
|
||||||
|
'cidr': 'fake_cidr',
|
||||||
|
'gateway': 'fake_gateway',
|
||||||
|
'mtu': fake_neutron_network_multi['mtu'],
|
||||||
|
}
|
||||||
|
|
||||||
|
fake_network_allocation_multi = {
|
||||||
|
'id': fake_neutron_port['id'],
|
||||||
|
'share_server_id': fake_share_server['id'],
|
||||||
|
'ip_address': fake_neutron_port['fixed_ips'][0]['ip_address'],
|
||||||
|
'mac_address': fake_neutron_port['mac_address'],
|
||||||
|
'status': constants.STATUS_ACTIVE,
|
||||||
|
'label': 'user',
|
||||||
|
'network_type': None,
|
||||||
|
'segmentation_id': None,
|
||||||
|
'ip_version': fake_share_network_multi['ip_version'],
|
||||||
|
'cidr': fake_share_network_multi['cidr'],
|
||||||
|
'gateway': 'fake_gateway',
|
||||||
|
'mtu': fake_share_network_multi['mtu'],
|
||||||
|
}
|
||||||
|
|
||||||
|
fake_binding_profile = {
|
||||||
|
'neutron_switch_id': 'fake switch id',
|
||||||
|
'neutron_port_id': 'fake port id',
|
||||||
|
'neutron_switch_info': 'fake switch info'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class NeutronNetworkPluginTest(test.TestCase):
|
class NeutronNetworkPluginTest(test.TestCase):
|
||||||
|
|
||||||
@ -310,6 +381,58 @@ class NeutronNetworkPluginTest(test.TestCase):
|
|||||||
fake_share_network['id'],
|
fake_share_network['id'],
|
||||||
share_nw_update_dict)
|
share_nw_update_dict)
|
||||||
|
|
||||||
|
@mock.patch.object(db_api, 'share_network_update', mock.Mock())
|
||||||
|
def test_save_neutron_network_data_multi_segment(self):
|
||||||
|
share_nw_update_dict = {
|
||||||
|
'network_type': 'vlan',
|
||||||
|
'segmentation_id': 3926,
|
||||||
|
'mtu': 1509
|
||||||
|
}
|
||||||
|
config_data = {
|
||||||
|
'DEFAULT': {
|
||||||
|
'neutron_physical_net_name': 'net1',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.mock_object(self.plugin.neutron_api, 'get_network')
|
||||||
|
self.plugin.neutron_api.get_network.return_value = fake_nw_info
|
||||||
|
|
||||||
|
with test_utils.create_temp_config_with_opts(config_data):
|
||||||
|
self.plugin._save_neutron_network_data(self.fake_context,
|
||||||
|
fake_share_network)
|
||||||
|
|
||||||
|
self.plugin.neutron_api.get_network.assert_called_once_with(
|
||||||
|
fake_share_network['neutron_net_id'])
|
||||||
|
self.plugin.db.share_network_update.assert_called_once_with(
|
||||||
|
self.fake_context,
|
||||||
|
fake_share_network['id'],
|
||||||
|
share_nw_update_dict)
|
||||||
|
|
||||||
|
@mock.patch.object(db_api, 'share_network_update', mock.Mock())
|
||||||
|
def test_save_neutron_network_data_multi_segment_without_ident(self):
|
||||||
|
config_data = {
|
||||||
|
'DEFAULT': {
|
||||||
|
'neutron_physical_net_name': 'net100',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.mock_object(self.plugin.neutron_api, 'get_network')
|
||||||
|
self.plugin.neutron_api.get_network.return_value = fake_nw_info
|
||||||
|
|
||||||
|
with test_utils.create_temp_config_with_opts(config_data):
|
||||||
|
self.assertRaises(exception.NetworkBadConfigurationException,
|
||||||
|
self.plugin._save_neutron_network_data,
|
||||||
|
self.fake_context, fake_share_network)
|
||||||
|
|
||||||
|
@mock.patch.object(db_api, 'share_network_update', mock.Mock())
|
||||||
|
def test_save_neutron_network_data_multi_segment_without_cfg(self):
|
||||||
|
self.mock_object(self.plugin.neutron_api, 'get_network')
|
||||||
|
self.plugin.neutron_api.get_network.return_value = fake_nw_info
|
||||||
|
|
||||||
|
self.assertRaises(exception.NetworkBadConfigurationException,
|
||||||
|
self.plugin._save_neutron_network_data,
|
||||||
|
self.fake_context, fake_share_network)
|
||||||
|
|
||||||
@mock.patch.object(db_api, 'share_network_update', mock.Mock())
|
@mock.patch.object(db_api, 'share_network_update', mock.Mock())
|
||||||
def test_save_neutron_subnet_data(self):
|
def test_save_neutron_subnet_data(self):
|
||||||
neutron_subnet_info = {
|
neutron_subnet_info = {
|
||||||
@ -543,6 +666,7 @@ class NeutronBindNetworkPluginTest(test.TestCase):
|
|||||||
self.bind_plugin = self._get_neutron_network_plugin_instance()
|
self.bind_plugin = self._get_neutron_network_plugin_instance()
|
||||||
self.bind_plugin.db = db_api
|
self.bind_plugin.db = db_api
|
||||||
self.sleep_mock = self.mock_object(time, 'sleep')
|
self.sleep_mock = self.mock_object(time, 'sleep')
|
||||||
|
self.fake_share_network_multi = dict(fake_share_network_multi)
|
||||||
|
|
||||||
def _get_neutron_network_plugin_instance(self, config_data=None):
|
def _get_neutron_network_plugin_instance(self, config_data=None):
|
||||||
if config_data is None:
|
if config_data is None:
|
||||||
@ -593,8 +717,6 @@ class NeutronBindNetworkPluginTest(test.TestCase):
|
|||||||
[fake_neut_port1, fake_neut_port2],
|
[fake_neut_port1, fake_neut_port2],
|
||||||
fake_share_server)
|
fake_share_server)
|
||||||
|
|
||||||
@mock.patch.object(db_api, 'network_allocation_create',
|
|
||||||
mock.Mock(return_values=fake_network_allocation))
|
|
||||||
@mock.patch.object(db_api, 'share_network_get',
|
@mock.patch.object(db_api, 'share_network_get',
|
||||||
mock.Mock(return_value=fake_share_network))
|
mock.Mock(return_value=fake_share_network))
|
||||||
@mock.patch.object(db_api, 'share_server_get',
|
@mock.patch.object(db_api, 'share_server_get',
|
||||||
@ -611,6 +733,10 @@ class NeutronBindNetworkPluginTest(test.TestCase):
|
|||||||
self.mock_object(neutron_host_id_opts, 'default')
|
self.mock_object(neutron_host_id_opts, 'default')
|
||||||
neutron_host_id_opts.default = 'foohost1'
|
neutron_host_id_opts.default = 'foohost1'
|
||||||
self.mock_object(db_api, 'network_allocation_create')
|
self.mock_object(db_api, 'network_allocation_create')
|
||||||
|
db_api.network_allocation_create.return_value = fake_network_allocation
|
||||||
|
self.mock_object(self.bind_plugin.neutron_api, 'get_network')
|
||||||
|
self.bind_plugin.neutron_api.get_network.return_value = (
|
||||||
|
fake_neutron_network)
|
||||||
|
|
||||||
with mock.patch.object(self.bind_plugin.neutron_api, 'create_port',
|
with mock.patch.object(self.bind_plugin.neutron_api, 'create_port',
|
||||||
mock.Mock(return_value=fake_neutron_port)):
|
mock.Mock(return_value=fake_neutron_port)):
|
||||||
@ -641,6 +767,96 @@ class NeutronBindNetworkPluginTest(test.TestCase):
|
|||||||
self.bind_plugin._wait_for_ports_bind.assert_called_once_with(
|
self.bind_plugin._wait_for_ports_bind.assert_called_once_with(
|
||||||
[db_api.network_allocation_create()], fake_share_server)
|
[db_api.network_allocation_create()], fake_share_server)
|
||||||
|
|
||||||
|
@mock.patch.object(db_api, 'network_allocation_create',
|
||||||
|
mock.Mock(return_values=fake_network_allocation_multi))
|
||||||
|
@mock.patch.object(db_api, 'share_network_get',
|
||||||
|
mock.Mock(return_value=fake_share_network_multi))
|
||||||
|
@mock.patch.object(db_api, 'share_server_get',
|
||||||
|
mock.Mock(return_value=fake_share_server))
|
||||||
|
def test_allocate_network_multi_segment(self):
|
||||||
|
network_allocation_update_data = {
|
||||||
|
'network_type':
|
||||||
|
fake_nw_info['segments'][0]['provider:network_type'],
|
||||||
|
'segmentation_id':
|
||||||
|
fake_nw_info['segments'][0]['provider:segmentation_id'],
|
||||||
|
}
|
||||||
|
network_update_data = dict(network_allocation_update_data)
|
||||||
|
network_update_data['mtu'] = fake_nw_info['mtu']
|
||||||
|
fake_network_allocation_multi_updated = dict(
|
||||||
|
fake_network_allocation_multi)
|
||||||
|
fake_network_allocation_multi_updated.update(
|
||||||
|
network_allocation_update_data)
|
||||||
|
fake_share_network_multi_updated = dict(fake_share_network_multi)
|
||||||
|
fake_share_network_multi_updated.update(network_update_data)
|
||||||
|
config_data = {
|
||||||
|
'DEFAULT': {
|
||||||
|
'neutron_net_id': 'fake net id',
|
||||||
|
'neutron_subnet_id': 'fake subnet id',
|
||||||
|
'neutron_physical_net_name': 'net1',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.bind_plugin = self._get_neutron_network_plugin_instance(
|
||||||
|
config_data)
|
||||||
|
self.bind_plugin.db = db_api
|
||||||
|
|
||||||
|
self.mock_object(self.bind_plugin, '_has_provider_network_extension')
|
||||||
|
self.bind_plugin._has_provider_network_extension.return_value = True
|
||||||
|
save_subnet_data = self.mock_object(self.bind_plugin,
|
||||||
|
'_save_neutron_subnet_data')
|
||||||
|
self.mock_object(self.bind_plugin, '_wait_for_ports_bind')
|
||||||
|
neutron_host_id_opts = plugin.neutron_bind_network_plugin_opts[1]
|
||||||
|
self.mock_object(neutron_host_id_opts, 'default')
|
||||||
|
neutron_host_id_opts.default = 'foohost1'
|
||||||
|
|
||||||
|
self.mock_object(db_api, 'network_allocation_create')
|
||||||
|
db_api.network_allocation_create.return_value = (
|
||||||
|
fake_network_allocation_multi)
|
||||||
|
self.mock_object(db_api, 'network_allocation_update')
|
||||||
|
db_api.network_allocation_update.return_value = (
|
||||||
|
fake_network_allocation_multi_updated)
|
||||||
|
self.mock_object(self.bind_plugin.neutron_api, 'get_network')
|
||||||
|
self.bind_plugin.neutron_api.get_network.return_value = (
|
||||||
|
fake_neutron_network_multi)
|
||||||
|
self.mock_object(db_api, 'share_network_update')
|
||||||
|
|
||||||
|
with mock.patch.object(self.bind_plugin.neutron_api, 'create_port',
|
||||||
|
mock.Mock(return_value=fake_neutron_port)):
|
||||||
|
self.bind_plugin.allocate_network(
|
||||||
|
self.fake_context,
|
||||||
|
fake_share_server,
|
||||||
|
self.fake_share_network_multi,
|
||||||
|
allocation_info={'count': 1})
|
||||||
|
|
||||||
|
self.bind_plugin._has_provider_network_extension.assert_any_call()
|
||||||
|
save_subnet_data.assert_called_once_with(
|
||||||
|
self.fake_context,
|
||||||
|
fake_share_network_multi_updated)
|
||||||
|
expected_kwargs = {
|
||||||
|
'binding:vnic_type': 'baremetal',
|
||||||
|
'host_id': 'foohost1',
|
||||||
|
'network_id': fake_share_network_multi['neutron_net_id'],
|
||||||
|
'subnet_id': fake_share_network_multi['neutron_subnet_id'],
|
||||||
|
'device_owner': 'manila:share',
|
||||||
|
'device_id': fake_share_network_multi['id']
|
||||||
|
}
|
||||||
|
self.bind_plugin.neutron_api.create_port.assert_called_once_with(
|
||||||
|
fake_share_network_multi['project_id'], **expected_kwargs)
|
||||||
|
db_api.network_allocation_create.assert_called_once_with(
|
||||||
|
self.fake_context,
|
||||||
|
fake_network_allocation_multi)
|
||||||
|
db_api.share_network_update.assert_called_once_with(
|
||||||
|
self.fake_context,
|
||||||
|
fake_share_network_multi['id'],
|
||||||
|
network_update_data)
|
||||||
|
network_allocation_update_data['cidr'] = (
|
||||||
|
fake_share_network_multi['cidr'])
|
||||||
|
network_allocation_update_data['ip_version'] = (
|
||||||
|
fake_share_network_multi['ip_version'])
|
||||||
|
db_api.network_allocation_update.assert_called_once_with(
|
||||||
|
self.fake_context,
|
||||||
|
fake_neutron_port['id'],
|
||||||
|
network_allocation_update_data)
|
||||||
|
|
||||||
@ddt.data({
|
@ddt.data({
|
||||||
'neutron_binding_profiles': None,
|
'neutron_binding_profiles': None,
|
||||||
'binding_profiles': {}
|
'binding_profiles': {}
|
||||||
@ -821,6 +1037,7 @@ class NeutronBindSingleNetworkPluginTest(test.TestCase):
|
|||||||
'DEFAULT': {
|
'DEFAULT': {
|
||||||
'neutron_net_id': fake_net_id,
|
'neutron_net_id': fake_net_id,
|
||||||
'neutron_subnet_id': fake_subnet_id,
|
'neutron_subnet_id': fake_subnet_id,
|
||||||
|
'neutron_physical_net_name': 'net1',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fake_net = {'subnets': ['fake1', 'fake2', fake_subnet_id]}
|
fake_net = {'subnets': ['fake1', 'fake2', fake_subnet_id]}
|
||||||
@ -836,8 +1053,8 @@ class NeutronBindSingleNetworkPluginTest(test.TestCase):
|
|||||||
'port1', 'port2']
|
'port1', 'port2']
|
||||||
instance = self._get_neutron_network_plugin_instance()
|
instance = self._get_neutron_network_plugin_instance()
|
||||||
share_server = 'fake_share_server'
|
share_server = 'fake_share_server'
|
||||||
share_network = 'fake_share_network'
|
share_network = {'neutron_net_id': {}}
|
||||||
share_network_upd = 'updated_fake_share_network'
|
share_network_upd = {'neutron_net_id': {'upd': True}}
|
||||||
count = 2
|
count = 2
|
||||||
device_owner = 'fake_device_owner'
|
device_owner = 'fake_device_owner'
|
||||||
self.mock_object(
|
self.mock_object(
|
||||||
@ -1279,6 +1496,9 @@ class NeutronBindNetworkPluginWithNormalTypeTest(test.TestCase):
|
|||||||
self.mock_object(neutron_host_id_opts, 'default')
|
self.mock_object(neutron_host_id_opts, 'default')
|
||||||
neutron_host_id_opts.default = 'foohost1'
|
neutron_host_id_opts.default = 'foohost1'
|
||||||
self.mock_object(db_api, 'network_allocation_create')
|
self.mock_object(db_api, 'network_allocation_create')
|
||||||
|
multi_seg = self.mock_object(
|
||||||
|
self.bind_plugin, '_is_neutron_multi_segment')
|
||||||
|
multi_seg.return_value = False
|
||||||
|
|
||||||
with mock.patch.object(self.bind_plugin.neutron_api, 'create_port',
|
with mock.patch.object(self.bind_plugin.neutron_api, 'create_port',
|
||||||
mock.Mock(return_value=fake_neutron_port)):
|
mock.Mock(return_value=fake_neutron_port)):
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Added port binding support for neutron networks with multiple segments.
|
Loading…
Reference in New Issue
Block a user