Merge "Add neutron driver for binding"
This commit is contained in:
commit
3b73777227
devstack
doc/source/adminref
manila
releasenotes/notes
@ -75,6 +75,12 @@ function configure_default_backends {
|
||||
iniset $MANILA_CONF $group_name service_instance_user $MANILA_SERVICE_INSTANCE_USER
|
||||
iniset $MANILA_CONF $group_name driver_handles_share_servers True
|
||||
|
||||
if [ "$SHARE_DRIVER" == $MANILA_CONTAINER_DRIVER ]; then
|
||||
iniset $MANILA_CONF $group_name network_api_class $MANILA_NETWORK_API_CLASS
|
||||
iniset $MANILA_CONF $group_name neutron_host_id $(hostname)
|
||||
iniset $MANILA_CONF $group_name neutron_vnic_type $MANILA_NEUTRON_VNIC_TYPE
|
||||
fi
|
||||
|
||||
if [ $(trueorfalse False MANILA_USE_SERVICE_INSTANCE_PASSWORD) == True ]; then
|
||||
iniset $MANILA_CONF $group_name service_instance_password $MANILA_SERVICE_INSTANCE_PASSWORD
|
||||
fi
|
||||
@ -522,7 +528,6 @@ function init_manila {
|
||||
elif [ "$SHARE_DRIVER" == $MANILA_CONTAINER_DRIVER ]; then
|
||||
if is_service_enabled m-shr; then
|
||||
SHARE_GROUP=$MANILA_CONTAINER_VOLUME_GROUP_NAME
|
||||
iniset $MANILA_CONF DEFAULT neutron_host_id $(hostname)
|
||||
configure_backing_file
|
||||
fi
|
||||
|
||||
|
@ -166,6 +166,10 @@ MANILA_CONTAINER_VOLUME_GROUP_NAME=${MANILA_CONTAINER_VOLUME_GROUP_NAME:-"manila
|
||||
# permanent one as soon as possible.
|
||||
MANILA_DOCKER_IMAGE_URL=${MANILA_DOCKER_IMAGE_URL:-"https://github.com/a-ovchinnikov/manila-image-elements-lxd-images/releases/download/0.1.0/manila-docker-container.tar.gz"}
|
||||
|
||||
# Network Plugin
|
||||
MANILA_NETWORK_API_CLASS=${MANILA_NETWORK_API_CLASS:-"manila.network.neutron.neutron_network_plugin.NeutronBindNetworkPlugin"}
|
||||
MANILA_NEUTRON_VNIC_TYPE=${MANILA_NEUTRON_VNIC_TYPE:-"normal"}
|
||||
|
||||
# Enable manila services
|
||||
# ----------------------
|
||||
# We have to add Manila to enabled services for screen_it to work
|
||||
|
@ -77,6 +77,13 @@ There are three different network plugins and five python classes in Manila:
|
||||
`neutron_net_id` and `neutron_subnet_id` from the Manila configuration
|
||||
file and uses one network for all shares.
|
||||
|
||||
1.3 `manila.network.neutron.neutron_network_plugin.NeutronBindNetworkPlugin`.
|
||||
This driver waits for active binding and fails if a Neutron port can't be
|
||||
bound or an error occurs. This plugin is useful for agent based binding
|
||||
(like OVS with docker driver) and fabric binding where real HW
|
||||
reconfiguration is taking place. The existing
|
||||
`NeutronBindSingleNetworkPlugin` is a combination of 1.2 and 1.3.
|
||||
|
||||
When only a single network is needed, the NeutronSingleNetworkPlugin (1.2)
|
||||
is a simple solution. Otherwise NeutronNetworkPlugin (1.1) should be chosen.
|
||||
|
||||
|
@ -114,6 +114,10 @@ class NetworkException(ManilaException):
|
||||
message = _("Exception due to network failure.")
|
||||
|
||||
|
||||
class NetworkBindException(ManilaException):
|
||||
message = _("Exception due to failed port status in binding.")
|
||||
|
||||
|
||||
class NetworkBadConfigurationException(NetworkException):
|
||||
message = _("Bad network configuration: %(reason)s.")
|
||||
|
||||
|
@ -65,6 +65,17 @@ class NetworkBaseAPI(db_base.Base):
|
||||
"'%s'.") % share_server_id
|
||||
raise exception.NetworkBadConfigurationException(reason=msg)
|
||||
|
||||
def update_network_allocation(self, context, share_server):
|
||||
"""Update network allocation.
|
||||
|
||||
Optional method to be called by the manager after share server creation
|
||||
which can be overloaded in case the port state has to be updated.
|
||||
|
||||
:param context: RequestContext object
|
||||
:param share_server: share server object
|
||||
:return: list of updated ports or None if nothing was updated
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def allocate_network(self, context, share_server, share_network=None,
|
||||
**kwargs):
|
||||
|
@ -164,7 +164,8 @@ class API(object):
|
||||
|
||||
def create_port(self, tenant_id, network_id, host_id=None, subnet_id=None,
|
||||
fixed_ip=None, device_owner=None, device_id=None,
|
||||
mac_address=None, security_group_ids=None, dhcp_opts=None):
|
||||
mac_address=None, security_group_ids=None, dhcp_opts=None,
|
||||
**kwargs):
|
||||
try:
|
||||
port_req_body = {'port': {}}
|
||||
port_req_body['port']['network_id'] = network_id
|
||||
@ -187,6 +188,8 @@ class API(object):
|
||||
port_req_body['port']['device_owner'] = device_owner
|
||||
if device_id:
|
||||
port_req_body['port']['device_id'] = device_id
|
||||
if kwargs:
|
||||
port_req_body['port'].update(kwargs)
|
||||
port = self.client.create_port(port_req_body).get('port', {})
|
||||
return port
|
||||
except neutron_client_exc.NeutronClientException as e:
|
||||
|
@ -15,3 +15,8 @@
|
||||
|
||||
PROVIDER_NW_EXT = 'Provider Network'
|
||||
PORTBINDING_EXT = 'Port Binding'
|
||||
|
||||
PORT_STATUS_ERROR = 'ERROR'
|
||||
PORT_STATUS_ACTIVE = 'ACTIVE'
|
||||
|
||||
VIF_TYPE_BINDING_FAILED = 'binding_failed'
|
||||
|
@ -14,15 +14,21 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import socket
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log
|
||||
|
||||
from manila.common import constants
|
||||
from manila import exception
|
||||
from manila.i18n import _
|
||||
from manila import network
|
||||
from manila.network.neutron import api as neutron_api
|
||||
from manila.network.neutron import constants as neutron_constants
|
||||
from manila import utils
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
neutron_single_network_plugin_opts = [
|
||||
cfg.StrOpt(
|
||||
'neutron_net_id',
|
||||
@ -39,12 +45,18 @@ neutron_single_network_plugin_opts = [
|
||||
deprecated_group='DEFAULT'),
|
||||
]
|
||||
|
||||
neutron_network_plugin_opts = [
|
||||
neutron_bind_network_plugin_opts = [
|
||||
cfg.StrOpt(
|
||||
'neutron_vnic_type',
|
||||
help="vNIC type used for binding.",
|
||||
choices=['baremetal', 'normal', 'direct',
|
||||
'direct-physical', 'macvtap'],
|
||||
default='baremetal'),
|
||||
cfg.StrOpt(
|
||||
"neutron_host_id",
|
||||
help="Host ID to be used when creating neutron port. Hostname of "
|
||||
"a controller running Neutron should be used in a general case.",
|
||||
deprecated_group='DEFAULT'),
|
||||
help="Host ID to be used when creating neutron port. If not set "
|
||||
"host is set to manila-share host by default.",
|
||||
default=socket.gethostname()),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
@ -59,9 +71,6 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
||||
self._neutron_api_args = args
|
||||
self._neutron_api_kwargs = kwargs
|
||||
self._label = kwargs.pop('label', 'user')
|
||||
CONF.register_opts(
|
||||
neutron_network_plugin_opts,
|
||||
group=self.neutron_api.config_group_name)
|
||||
|
||||
@property
|
||||
def label(self):
|
||||
@ -124,13 +133,22 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
||||
for port in ports:
|
||||
self._delete_port(context, port)
|
||||
|
||||
def _get_port_create_args(self, share_server, share_network,
|
||||
device_owner):
|
||||
return {
|
||||
"network_id": share_network['neutron_net_id'],
|
||||
"subnet_id": share_network['neutron_subnet_id'],
|
||||
"device_owner": 'manila:' + device_owner,
|
||||
"device_id": share_server.get('id'),
|
||||
}
|
||||
|
||||
def _create_port(self, context, share_server, share_network, device_owner):
|
||||
host_id = self.neutron_api.configuration.neutron_host_id
|
||||
create_args = self._get_port_create_args(share_server, share_network,
|
||||
device_owner)
|
||||
|
||||
port = self.neutron_api.create_port(
|
||||
share_network['project_id'],
|
||||
network_id=share_network['neutron_net_id'],
|
||||
subnet_id=share_network['neutron_subnet_id'],
|
||||
device_owner='manila:' + device_owner, host_id=host_id)
|
||||
share_network['project_id'], **create_args)
|
||||
|
||||
port_dict = {
|
||||
'id': port['id'],
|
||||
'share_server_id': share_server['id'],
|
||||
@ -214,7 +232,7 @@ class NeutronSingleNetworkPlugin(NeutronNetworkPlugin):
|
||||
'neutron_net_id': self.net,
|
||||
'neutron_subnet_id': self.subnet,
|
||||
}
|
||||
super(NeutronSingleNetworkPlugin, self).allocate_network(
|
||||
return super(NeutronSingleNetworkPlugin, self).allocate_network(
|
||||
context, share_server, share_network, **kwargs)
|
||||
|
||||
def _verify_net_and_subnet(self):
|
||||
@ -261,3 +279,73 @@ class NeutronSingleNetworkPlugin(NeutronNetworkPlugin):
|
||||
share_network = self.db.share_network_update(
|
||||
context, share_network['id'], upd)
|
||||
return share_network
|
||||
|
||||
|
||||
class NeutronBindNetworkPlugin(NeutronNetworkPlugin):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(NeutronBindNetworkPlugin, self).__init__(*args, **kwargs)
|
||||
CONF.register_opts(
|
||||
neutron_bind_network_plugin_opts,
|
||||
group=self.neutron_api.config_group_name)
|
||||
self.config = self.neutron_api.configuration
|
||||
|
||||
def update_network_allocation(self, context, share_server):
|
||||
if self.config.neutron_vnic_type == 'normal':
|
||||
ports = self.db.network_allocations_get_for_share_server(
|
||||
context,
|
||||
share_server['id'])
|
||||
self._wait_for_ports_bind(ports, share_server)
|
||||
return ports
|
||||
|
||||
@utils.retry(exception.NetworkBindException, retries=20)
|
||||
def _wait_for_ports_bind(self, ports, share_server):
|
||||
inactive_ports = []
|
||||
for port in ports:
|
||||
port = self._neutron_api.show_port(port['id'])
|
||||
if (port['status'] == neutron_constants.PORT_STATUS_ERROR or
|
||||
('binding:vif_type' in port and
|
||||
port['binding:vif_type'] ==
|
||||
neutron_constants.VIF_TYPE_BINDING_FAILED)):
|
||||
msg = _("Port binding %s failed.") % port['id']
|
||||
raise exception.NetworkException(msg)
|
||||
elif port['status'] != neutron_constants.PORT_STATUS_ACTIVE:
|
||||
LOG.debug("The port %(id)s is in state %(state)s. "
|
||||
"Wait for active state.", {
|
||||
"id": port['id'],
|
||||
"state": port['status']})
|
||||
inactive_ports.append(port['id'])
|
||||
if len(inactive_ports) == 0:
|
||||
return
|
||||
msg = _("Ports are not fully bound for share server "
|
||||
"'%(s_id)s' (inactive ports: %(ports)s)") % {
|
||||
"s_id": share_server['id'],
|
||||
"ports": inactive_ports}
|
||||
raise exception.NetworkBindException(msg)
|
||||
|
||||
def _get_port_create_args(self, share_server, share_network,
|
||||
device_owner):
|
||||
arguments = super(
|
||||
NeutronBindNetworkPlugin, self)._get_port_create_args(
|
||||
share_network, share_network, device_owner)
|
||||
arguments['host_id'] = self.config.neutron_host_id
|
||||
arguments['binding:vnic_type'] = self.config.neutron_vnic_type
|
||||
return arguments
|
||||
|
||||
def allocate_network(self, context, share_server, share_network=None,
|
||||
**kwargs):
|
||||
ports = super(NeutronBindNetworkPlugin, self).allocate_network(
|
||||
context, share_server, share_network, **kwargs)
|
||||
# If vnic type is 'normal' we expect a neutron agent to bind the
|
||||
# ports. This action requires a vnic to be spawned by the driver.
|
||||
# Therefore we do not wait for the port binding here, but
|
||||
# return the unbound ports and expect the share manager to call
|
||||
# update_network_allocation after the share server was created, in
|
||||
# order to update the ports with the correct binding.
|
||||
if self.config.neutron_vnic_type != 'normal':
|
||||
self._wait_for_ports_bind(ports, share_server)
|
||||
return ports
|
||||
|
||||
|
||||
class NeutronBindSingleNetworkPlugin(NeutronSingleNetworkPlugin,
|
||||
NeutronBindNetworkPlugin):
|
||||
pass
|
||||
|
@ -100,7 +100,7 @@ _global_opt_lists = [
|
||||
manila.network.linux.interface.OPTS,
|
||||
manila.network.network_opts,
|
||||
manila.network.neutron.neutron_network_plugin.
|
||||
neutron_network_plugin_opts,
|
||||
neutron_bind_network_plugin_opts,
|
||||
manila.network.neutron.neutron_network_plugin.
|
||||
neutron_single_network_plugin_opts,
|
||||
manila.network.nova_network_plugin.nova_single_network_plugin_opts,
|
||||
|
@ -578,6 +578,17 @@ class ShareDriver(object):
|
||||
def get_admin_network_allocations_number(self):
|
||||
return 0
|
||||
|
||||
def update_network_allocation(self, context, share_server):
|
||||
"""Update network allocation after share server creation."""
|
||||
self.network_api.update_network_allocation(context, share_server)
|
||||
|
||||
def update_admin_network_allocation(self, context, share_server):
|
||||
"""Update admin network allocation after share server creation."""
|
||||
if (self.get_admin_network_allocations_number() and
|
||||
self.admin_network_api):
|
||||
self.admin_network_api.update_network_allocation(context,
|
||||
share_server)
|
||||
|
||||
def allocate_network(self, context, share_server, share_network,
|
||||
count=None, **kwargs):
|
||||
"""Allocate network resources using given network information."""
|
||||
|
@ -2377,6 +2377,9 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
server_info = self.driver.setup_server(
|
||||
network_info, metadata=metadata)
|
||||
|
||||
self.driver.update_network_allocation(context, share_server)
|
||||
self.driver.update_admin_network_allocation(context, share_server)
|
||||
|
||||
if server_info and isinstance(server_info, dict):
|
||||
self.db.share_server_backend_details_set(
|
||||
context, share_server['id'], server_info)
|
||||
|
@ -164,6 +164,25 @@ class NeutronApiTest(test.TestCase):
|
||||
self.neutron_api._has_port_binding_extension.assert_called_once_with()
|
||||
self.assertTrue(clientv20.Client.called)
|
||||
|
||||
def test_create_port_with_additional_kwargs(self):
|
||||
# Set up test data
|
||||
self.mock_object(self.neutron_api, '_has_port_binding_extension',
|
||||
mock.Mock(return_value=True))
|
||||
port_args = {'tenant_id': 'test tenant', 'network_id': 'test net',
|
||||
'binding_arg': 'foo'}
|
||||
|
||||
# Execute method 'create_port'
|
||||
port = self.neutron_api.create_port(**port_args)
|
||||
|
||||
# Verify results
|
||||
self.assertEqual(port_args['tenant_id'], port['tenant_id'])
|
||||
self.assertEqual(port_args['network_id'],
|
||||
port['network_id'])
|
||||
self.assertEqual(port_args['binding_arg'],
|
||||
port['binding_arg'])
|
||||
self.neutron_api._has_port_binding_extension.assert_called_once_with()
|
||||
self.assertTrue(clientv20.Client.called)
|
||||
|
||||
@mock.patch.object(neutron_api.LOG, 'exception', mock.Mock())
|
||||
def test_create_port_exception(self):
|
||||
# Set up test data
|
||||
|
@ -14,8 +14,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
import ddt
|
||||
import mock
|
||||
import time
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from manila.common import constants
|
||||
@ -31,7 +34,7 @@ from manila.tests import utils as test_utils
|
||||
CONF = cfg.CONF
|
||||
|
||||
fake_neutron_port = {
|
||||
"status": "test_port_status",
|
||||
"status": "ACTIVE",
|
||||
"allowed_address_pairs": [],
|
||||
"admin_state_up": True,
|
||||
"network_id": "test_net_id",
|
||||
@ -132,7 +135,8 @@ class NeutronNetworkPluginTest(test.TestCase):
|
||||
fake_share_network['project_id'],
|
||||
network_id=fake_share_network['neutron_net_id'],
|
||||
subnet_id=fake_share_network['neutron_subnet_id'],
|
||||
device_owner='manila:share', host_id=None)
|
||||
device_owner='manila:share',
|
||||
device_id=fake_share_network['id'])
|
||||
db_api.network_allocation_create.assert_called_once_with(
|
||||
self.fake_context,
|
||||
fake_network_allocation)
|
||||
@ -141,54 +145,6 @@ class NeutronNetworkPluginTest(test.TestCase):
|
||||
save_nw_data.stop()
|
||||
save_subnet_data.stop()
|
||||
|
||||
@mock.patch.object(db_api, 'network_allocation_create',
|
||||
mock.Mock(return_values=fake_network_allocation))
|
||||
@mock.patch.object(db_api, 'share_network_get',
|
||||
mock.Mock(return_value=fake_share_network))
|
||||
@mock.patch.object(db_api, 'share_server_get',
|
||||
mock.Mock(return_value=fake_share_server))
|
||||
def test_allocate_network_host_id_prconfigured(self):
|
||||
has_provider_nw_ext = mock.patch.object(
|
||||
self.plugin, '_has_provider_network_extension').start()
|
||||
has_provider_nw_ext.return_value = True
|
||||
save_nw_data = mock.patch.object(self.plugin,
|
||||
'_save_neutron_network_data').start()
|
||||
save_subnet_data = mock.patch.object(
|
||||
self.plugin,
|
||||
'_save_neutron_subnet_data').start()
|
||||
|
||||
config_data = {
|
||||
'DEFAULT': {
|
||||
'neutron_host_id': 'fake_host_id',
|
||||
}
|
||||
}
|
||||
with test_utils.create_temp_config_with_opts(config_data):
|
||||
with mock.patch.object(self.plugin.neutron_api, 'create_port',
|
||||
mock.Mock(return_value=fake_neutron_port)):
|
||||
self.plugin.allocate_network(
|
||||
self.fake_context,
|
||||
fake_share_server,
|
||||
fake_share_network,
|
||||
allocation_info={'count': 1})
|
||||
|
||||
has_provider_nw_ext.assert_any_call()
|
||||
save_nw_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
save_subnet_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
self.plugin.neutron_api.create_port.assert_called_once_with(
|
||||
fake_share_network['project_id'],
|
||||
network_id=fake_share_network['neutron_net_id'],
|
||||
subnet_id=fake_share_network['neutron_subnet_id'],
|
||||
device_owner='manila:share', host_id='fake_host_id')
|
||||
db_api.network_allocation_create.assert_called_once_with(
|
||||
self.fake_context,
|
||||
fake_network_allocation)
|
||||
|
||||
has_provider_nw_ext.stop()
|
||||
save_nw_data.stop()
|
||||
save_subnet_data.stop()
|
||||
|
||||
@mock.patch.object(db_api, 'network_allocation_create',
|
||||
mock.Mock(return_values=fake_network_allocation))
|
||||
@mock.patch.object(db_api, 'share_network_get',
|
||||
@ -217,11 +173,13 @@ class NeutronNetworkPluginTest(test.TestCase):
|
||||
mock.call(fake_share_network['project_id'],
|
||||
network_id=fake_share_network['neutron_net_id'],
|
||||
subnet_id=fake_share_network['neutron_subnet_id'],
|
||||
device_owner='manila:share', host_id=None),
|
||||
device_owner='manila:share',
|
||||
device_id=fake_share_network['id']),
|
||||
mock.call(fake_share_network['project_id'],
|
||||
network_id=fake_share_network['neutron_net_id'],
|
||||
subnet_id=fake_share_network['neutron_subnet_id'],
|
||||
device_owner='manila:share', host_id=None),
|
||||
device_owner='manila:share',
|
||||
device_id=fake_share_network['id']),
|
||||
]
|
||||
db_api_calls = [
|
||||
mock.call(self.fake_context, fake_network_allocation),
|
||||
@ -541,3 +499,559 @@ class NeutronSingleNetworkPluginTest(test.TestCase):
|
||||
plugin.NeutronNetworkPlugin.allocate_network.assert_called_once_with(
|
||||
self.context, share_server, share_network_upd, count=count,
|
||||
device_owner=device_owner)
|
||||
plugin.NeutronNetworkPlugin.allocate_network.reset_mock()
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class NeutronBindNetworkPluginTest(test.TestCase):
|
||||
def setUp(self):
|
||||
super(NeutronBindNetworkPluginTest, self).setUp()
|
||||
self.fake_context = context.RequestContext(user_id='fake user',
|
||||
project_id='fake project',
|
||||
is_admin=False)
|
||||
self.has_binding_ext_mock = self.mock_object(
|
||||
neutron_api.API, '_has_port_binding_extension')
|
||||
self.has_binding_ext_mock.return_value = True
|
||||
self.bind_plugin = plugin.NeutronBindNetworkPlugin()
|
||||
self.bind_plugin.db = db_api
|
||||
self.sleep_mock = self.mock_object(time, 'sleep')
|
||||
|
||||
def test_wait_for_bind(self):
|
||||
self.mock_object(self.bind_plugin.neutron_api, 'show_port')
|
||||
self.bind_plugin.neutron_api.show_port.return_value = fake_neutron_port
|
||||
|
||||
self.bind_plugin._wait_for_ports_bind([fake_neutron_port],
|
||||
fake_share_server)
|
||||
|
||||
self.bind_plugin.neutron_api.show_port.assert_called_once_with(
|
||||
fake_neutron_port['id'])
|
||||
self.sleep_mock.assert_not_called()
|
||||
|
||||
def test_wait_for_bind_error(self):
|
||||
fake_neut_port = copy.copy(fake_neutron_port)
|
||||
fake_neut_port['status'] = 'ERROR'
|
||||
self.mock_object(self.bind_plugin.neutron_api, 'show_port')
|
||||
self.bind_plugin.neutron_api.show_port.return_value = fake_neut_port
|
||||
|
||||
self.assertRaises(exception.ManilaException,
|
||||
self.bind_plugin._wait_for_ports_bind,
|
||||
[fake_neut_port, fake_neut_port],
|
||||
fake_share_server)
|
||||
|
||||
self.bind_plugin.neutron_api.show_port.assert_called_once_with(
|
||||
fake_neutron_port['id'])
|
||||
self.sleep_mock.assert_not_called()
|
||||
|
||||
@ddt.data(('DOWN', 'ACTIVE'), ('DOWN', 'DOWN'), ('ACTIVE', 'DOWN'))
|
||||
@mock.patch.object(time, 'time', side_effect=[1, 1, 3])
|
||||
def test_wait_for_bind_two_ports_no_bind(self, state, time_mock):
|
||||
fake_neut_port1 = copy.copy(fake_neutron_port)
|
||||
fake_neut_port1['status'] = state[0]
|
||||
fake_neut_port2 = copy.copy(fake_neutron_port)
|
||||
fake_neut_port2['status'] = state[1]
|
||||
self.mock_object(self.bind_plugin.neutron_api, 'show_port')
|
||||
self.bind_plugin.neutron_api.show_port.side_effect = [fake_neut_port1,
|
||||
fake_neut_port2]
|
||||
|
||||
self.assertRaises(exception.ManilaException,
|
||||
self.bind_plugin._wait_for_ports_bind.__wrapped__,
|
||||
self.bind_plugin,
|
||||
[fake_neut_port1, fake_neut_port2],
|
||||
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.Mock(return_value=fake_share_network))
|
||||
@mock.patch.object(db_api, 'share_server_get',
|
||||
mock.Mock(return_value=fake_share_server))
|
||||
def test_allocate_network_one_allocation(self):
|
||||
self.mock_object(self.bind_plugin, '_has_provider_network_extension')
|
||||
self.bind_plugin._has_provider_network_extension.return_value = True
|
||||
save_nw_data = self.mock_object(self.bind_plugin,
|
||||
'_save_neutron_network_data')
|
||||
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')
|
||||
|
||||
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,
|
||||
fake_share_network,
|
||||
allocation_info={'count': 1})
|
||||
|
||||
self.bind_plugin._has_provider_network_extension.assert_any_call()
|
||||
save_nw_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
save_subnet_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
expected_kwargs = {
|
||||
'binding:vnic_type': 'baremetal',
|
||||
'host_id': 'foohost1',
|
||||
'network_id': fake_share_network['neutron_net_id'],
|
||||
'subnet_id': fake_share_network['neutron_subnet_id'],
|
||||
'device_owner': 'manila:share',
|
||||
'device_id': fake_share_network['id'],
|
||||
}
|
||||
self.bind_plugin.neutron_api.create_port.assert_called_once_with(
|
||||
fake_share_network['project_id'], **expected_kwargs)
|
||||
db_api.network_allocation_create.assert_called_once_with(
|
||||
self.fake_context,
|
||||
fake_network_allocation)
|
||||
self.bind_plugin._wait_for_ports_bind.assert_called_once_with(
|
||||
[db_api.network_allocation_create()], fake_share_server)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class NeutronBindSingleNetworkPluginTest(test.TestCase):
|
||||
def setUp(self):
|
||||
super(NeutronBindSingleNetworkPluginTest, self).setUp()
|
||||
self.context = 'fake_context'
|
||||
self.fake_context = context.RequestContext(user_id='fake user',
|
||||
project_id='fake project',
|
||||
is_admin=False)
|
||||
self.has_binding_ext_mock = self.mock_object(
|
||||
neutron_api.API, '_has_port_binding_extension')
|
||||
self.has_binding_ext_mock.return_value = True
|
||||
self.bind_plugin = plugin.NeutronBindNetworkPlugin()
|
||||
self.bind_plugin.db = db_api
|
||||
self.sleep_mock = self.mock_object(time, 'sleep')
|
||||
fake_net_id = 'fake net id'
|
||||
fake_subnet_id = 'fake subnet id'
|
||||
config_data = {
|
||||
'DEFAULT': {
|
||||
'neutron_net_id': fake_net_id,
|
||||
'neutron_subnet_id': fake_subnet_id,
|
||||
}
|
||||
}
|
||||
fake_net = {'subnets': ['fake1', 'fake2', fake_subnet_id]}
|
||||
self.mock_object(
|
||||
neutron_api.API, 'get_network', mock.Mock(return_value=fake_net))
|
||||
|
||||
with test_utils.create_temp_config_with_opts(config_data):
|
||||
self.bind_plugin = plugin.NeutronBindSingleNetworkPlugin()
|
||||
self.bind_plugin.db = db_api
|
||||
|
||||
def test_init_valid(self):
|
||||
fake_net_id = 'fake_net_id'
|
||||
fake_subnet_id = 'fake_subnet_id'
|
||||
config_data = {
|
||||
'DEFAULT': {
|
||||
'neutron_net_id': fake_net_id,
|
||||
'neutron_subnet_id': fake_subnet_id,
|
||||
}
|
||||
}
|
||||
fake_net = {'subnets': ['fake1', 'fake2', fake_subnet_id]}
|
||||
self.mock_object(
|
||||
neutron_api.API, 'get_network', mock.Mock(return_value=fake_net))
|
||||
|
||||
with test_utils.create_temp_config_with_opts(config_data):
|
||||
instance = plugin.NeutronSingleNetworkPlugin()
|
||||
|
||||
self.assertEqual(fake_net_id, instance.net)
|
||||
self.assertEqual(fake_subnet_id, instance.subnet)
|
||||
neutron_api.API.get_network.assert_called_once_with(fake_net_id)
|
||||
|
||||
@ddt.data(
|
||||
{'net': None, 'subnet': None},
|
||||
{'net': 'fake_net_id', 'subnet': None},
|
||||
{'net': None, 'subnet': 'fake_subnet_id'})
|
||||
@ddt.unpack
|
||||
def test_init_invalid(self, net, subnet):
|
||||
config_data = dict()
|
||||
# Simulate absence of set values
|
||||
if net:
|
||||
config_data['neutron_net_id'] = net
|
||||
if subnet:
|
||||
config_data['neutron_subnet_id'] = subnet
|
||||
config_data = dict(DEFAULT=config_data)
|
||||
|
||||
with test_utils.create_temp_config_with_opts(config_data):
|
||||
self.assertRaises(
|
||||
exception.NetworkBadConfigurationException,
|
||||
plugin.NeutronSingleNetworkPlugin)
|
||||
|
||||
@ddt.data({}, {'subnets': []}, {'subnets': ['different_foo_subnet']})
|
||||
def test_init_subnet_does_not_belong_to_net(self, fake_net):
|
||||
fake_net_id = 'fake_net_id'
|
||||
config_data = {
|
||||
'DEFAULT': {
|
||||
'neutron_net_id': fake_net_id,
|
||||
'neutron_subnet_id': 'fake_subnet_id',
|
||||
}
|
||||
}
|
||||
self.mock_object(
|
||||
neutron_api.API, 'get_network', mock.Mock(return_value=fake_net))
|
||||
|
||||
with test_utils.create_temp_config_with_opts(config_data):
|
||||
self.assertRaises(
|
||||
exception.NetworkBadConfigurationException,
|
||||
plugin.NeutronSingleNetworkPlugin)
|
||||
neutron_api.API.get_network.assert_called_once_with(fake_net_id)
|
||||
|
||||
def _get_neutron_single_network_plugin_instance(self):
|
||||
fake_subnet_id = 'fake_subnet_id'
|
||||
config_data = {
|
||||
'DEFAULT': {
|
||||
'neutron_net_id': 'fake_net_id',
|
||||
'neutron_subnet_id': fake_subnet_id,
|
||||
}
|
||||
}
|
||||
fake_net = {'subnets': [fake_subnet_id]}
|
||||
self.mock_object(
|
||||
neutron_api.API, 'get_network', mock.Mock(return_value=fake_net))
|
||||
with test_utils.create_temp_config_with_opts(config_data):
|
||||
instance = plugin.NeutronSingleNetworkPlugin()
|
||||
return instance
|
||||
|
||||
def test___update_share_network_net_data_same_values(self):
|
||||
instance = self._get_neutron_single_network_plugin_instance()
|
||||
share_network = {
|
||||
'neutron_net_id': instance.net,
|
||||
'neutron_subnet_id': instance.subnet,
|
||||
}
|
||||
|
||||
result = instance._update_share_network_net_data(
|
||||
self.context, share_network)
|
||||
|
||||
self.assertEqual(share_network, result)
|
||||
|
||||
def test___update_share_network_net_data_different_values_empty(self):
|
||||
instance = self._get_neutron_single_network_plugin_instance()
|
||||
share_network_input = {
|
||||
'id': 'fake_share_network_id',
|
||||
}
|
||||
share_network_result = {
|
||||
'neutron_net_id': instance.net,
|
||||
'neutron_subnet_id': instance.subnet,
|
||||
}
|
||||
self.mock_object(
|
||||
instance.db, 'share_network_update',
|
||||
mock.Mock(return_value='foo'))
|
||||
|
||||
instance._update_share_network_net_data(
|
||||
self.context, share_network_input)
|
||||
|
||||
instance.db.share_network_update.assert_called_once_with(
|
||||
self.context, share_network_input['id'], share_network_result)
|
||||
|
||||
@ddt.data(
|
||||
{'n': 'fake_net_id', 's': 'bar'},
|
||||
{'n': 'foo', 's': 'fake_subnet_id'})
|
||||
@ddt.unpack
|
||||
def test___update_share_network_net_data_different_values(self, n, s):
|
||||
instance = self._get_neutron_single_network_plugin_instance()
|
||||
share_network = {
|
||||
'id': 'fake_share_network_id',
|
||||
'neutron_net_id': n,
|
||||
'neutron_subnet_id': s,
|
||||
}
|
||||
self.mock_object(
|
||||
instance.db, 'share_network_update',
|
||||
mock.Mock(return_value=share_network))
|
||||
|
||||
self.assertRaises(
|
||||
exception.NetworkBadConfigurationException,
|
||||
instance._update_share_network_net_data,
|
||||
self.context, share_network)
|
||||
self.assertFalse(instance.db.share_network_update.called)
|
||||
|
||||
def test___update_share_network_net_data_nova_net_id_present(self):
|
||||
instance = self._get_neutron_single_network_plugin_instance()
|
||||
share_network = {
|
||||
'id': 'fake_share_network_id',
|
||||
'nova_net_id': 'foo',
|
||||
}
|
||||
self.mock_object(
|
||||
instance.db, 'share_network_update',
|
||||
mock.Mock(return_value=share_network))
|
||||
|
||||
self.assertRaises(
|
||||
exception.NetworkBadConfigurationException,
|
||||
instance._update_share_network_net_data,
|
||||
self.context, share_network)
|
||||
self.assertFalse(instance.db.share_network_update.called)
|
||||
|
||||
@mock.patch.object(
|
||||
plugin.NeutronNetworkPlugin, "allocate_network", mock.Mock())
|
||||
def test_allocate_network(self):
|
||||
instance = self._get_neutron_single_network_plugin_instance()
|
||||
share_server = 'fake_share_server'
|
||||
share_network = 'fake_share_network'
|
||||
share_network_upd = 'updated_fake_share_network'
|
||||
count = 2
|
||||
device_owner = 'fake_device_owner'
|
||||
self.mock_object(
|
||||
instance, '_update_share_network_net_data',
|
||||
mock.Mock(return_value=share_network_upd))
|
||||
|
||||
instance.allocate_network(
|
||||
self.context, share_server, share_network, count=count,
|
||||
device_owner=device_owner)
|
||||
|
||||
instance._update_share_network_net_data.assert_called_once_with(
|
||||
self.context, share_network)
|
||||
plugin.NeutronNetworkPlugin.allocate_network.assert_called_once_with(
|
||||
self.context, share_server, share_network_upd, count=count,
|
||||
device_owner=device_owner)
|
||||
plugin.NeutronNetworkPlugin.allocate_network.reset_mock()
|
||||
|
||||
def test_wait_for_bind(self):
|
||||
self.mock_object(self.bind_plugin.neutron_api, 'show_port')
|
||||
self.bind_plugin.neutron_api.show_port.return_value = fake_neutron_port
|
||||
|
||||
self.bind_plugin._wait_for_ports_bind([fake_neutron_port],
|
||||
fake_share_server)
|
||||
|
||||
self.bind_plugin.neutron_api.show_port.assert_called_once_with(
|
||||
fake_neutron_port['id'])
|
||||
self.sleep_mock.assert_not_called()
|
||||
|
||||
def test_wait_for_bind_error(self):
|
||||
fake_neut_port = copy.copy(fake_neutron_port)
|
||||
fake_neut_port['status'] = 'ERROR'
|
||||
self.mock_object(self.bind_plugin.neutron_api, 'show_port')
|
||||
self.bind_plugin.neutron_api.show_port.return_value = fake_neut_port
|
||||
|
||||
self.assertRaises(exception.ManilaException,
|
||||
self.bind_plugin._wait_for_ports_bind,
|
||||
[fake_neut_port, fake_neut_port],
|
||||
fake_share_server)
|
||||
|
||||
self.bind_plugin.neutron_api.show_port.assert_called_once_with(
|
||||
fake_neutron_port['id'])
|
||||
self.sleep_mock.assert_not_called()
|
||||
|
||||
@ddt.data(('DOWN', 'ACTIVE'), ('DOWN', 'DOWN'), ('ACTIVE', 'DOWN'))
|
||||
@mock.patch.object(time, 'time', side_effect=[1, 1, 3])
|
||||
def test_wait_for_bind_two_ports_no_bind(self, state, time_mock):
|
||||
fake_neut_port1 = copy.copy(fake_neutron_port)
|
||||
fake_neut_port1['status'] = state[0]
|
||||
fake_neut_port2 = copy.copy(fake_neutron_port)
|
||||
fake_neut_port2['status'] = state[1]
|
||||
self.mock_object(self.bind_plugin.neutron_api, 'show_port')
|
||||
self.bind_plugin.neutron_api.show_port.side_effect = [fake_neut_port1,
|
||||
fake_neut_port2]
|
||||
|
||||
self.assertRaises(exception.NetworkBindException,
|
||||
self.bind_plugin._wait_for_ports_bind.__wrapped__,
|
||||
self.bind_plugin,
|
||||
[fake_neut_port1, fake_neut_port2],
|
||||
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.Mock(return_value=fake_share_network))
|
||||
@mock.patch.object(db_api, 'share_server_get',
|
||||
mock.Mock(return_value=fake_share_server))
|
||||
def test_allocate_network_one_allocation(self):
|
||||
self.mock_object(self.bind_plugin, '_has_provider_network_extension')
|
||||
self.bind_plugin._has_provider_network_extension.return_value = True
|
||||
save_nw_data = self.mock_object(self.bind_plugin,
|
||||
'_save_neutron_network_data')
|
||||
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')
|
||||
|
||||
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,
|
||||
fake_share_network,
|
||||
allocation_info={'count': 1})
|
||||
|
||||
self.bind_plugin._has_provider_network_extension.assert_any_call()
|
||||
save_nw_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
save_subnet_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
expected_kwargs = {
|
||||
'binding:vnic_type': 'baremetal',
|
||||
'host_id': 'foohost1',
|
||||
'network_id': fake_share_network['neutron_net_id'],
|
||||
'subnet_id': fake_share_network['neutron_subnet_id'],
|
||||
'device_owner': 'manila:share',
|
||||
'device_id': fake_share_network['id'],
|
||||
}
|
||||
self.bind_plugin.neutron_api.create_port.assert_called_once_with(
|
||||
fake_share_network['project_id'], **expected_kwargs)
|
||||
db_api.network_allocation_create.assert_called_once_with(
|
||||
self.fake_context,
|
||||
fake_network_allocation)
|
||||
self.bind_plugin._wait_for_ports_bind.assert_called_once_with(
|
||||
[db_api.network_allocation_create()], fake_share_server)
|
||||
|
||||
|
||||
class NeutronBindNetworkPluginWithNormalTypeTest(test.TestCase):
|
||||
def setUp(self):
|
||||
super(NeutronBindNetworkPluginWithNormalTypeTest, self).setUp()
|
||||
config_data = {
|
||||
'DEFAULT': {
|
||||
'neutron_vnic_type': 'normal',
|
||||
}
|
||||
}
|
||||
self.plugin = plugin.NeutronNetworkPlugin()
|
||||
self.plugin.db = db_api
|
||||
self.fake_context = context.RequestContext(user_id='fake user',
|
||||
project_id='fake project',
|
||||
is_admin=False)
|
||||
|
||||
with test_utils.create_temp_config_with_opts(config_data):
|
||||
self.bind_plugin = plugin.NeutronBindNetworkPlugin()
|
||||
self.bind_plugin.db = db_api
|
||||
|
||||
@mock.patch.object(db_api, 'network_allocation_create',
|
||||
mock.Mock(return_values=fake_network_allocation))
|
||||
@mock.patch.object(db_api, 'share_network_get',
|
||||
mock.Mock(return_value=fake_share_network))
|
||||
@mock.patch.object(db_api, 'share_server_get',
|
||||
mock.Mock(return_value=fake_share_server))
|
||||
def test_allocate_network_one_allocation(self):
|
||||
self.mock_object(self.bind_plugin, '_has_provider_network_extension')
|
||||
self.bind_plugin._has_provider_network_extension.return_value = True
|
||||
save_nw_data = self.mock_object(self.bind_plugin,
|
||||
'_save_neutron_network_data')
|
||||
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')
|
||||
|
||||
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,
|
||||
fake_share_network,
|
||||
allocation_info={'count': 1})
|
||||
|
||||
self.bind_plugin._has_provider_network_extension.assert_any_call()
|
||||
save_nw_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
save_subnet_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
expected_kwargs = {
|
||||
'binding:vnic_type': 'normal',
|
||||
'host_id': 'foohost1',
|
||||
'network_id': fake_share_network['neutron_net_id'],
|
||||
'subnet_id': fake_share_network['neutron_subnet_id'],
|
||||
'device_owner': 'manila:share',
|
||||
'device_id': fake_share_network['id'],
|
||||
}
|
||||
self.bind_plugin.neutron_api.create_port.assert_called_once_with(
|
||||
fake_share_network['project_id'], **expected_kwargs)
|
||||
db_api.network_allocation_create.assert_called_once_with(
|
||||
self.fake_context,
|
||||
fake_network_allocation)
|
||||
self.bind_plugin._wait_for_ports_bind.assert_not_called()
|
||||
|
||||
def test_update_network_allocation(self):
|
||||
self.mock_object(self.bind_plugin, '_wait_for_ports_bind')
|
||||
self.mock_object(db_api, 'network_allocations_get_for_share_server')
|
||||
db_api.network_allocations_get_for_share_server.return_value = [
|
||||
fake_neutron_port]
|
||||
|
||||
self.bind_plugin.update_network_allocation(self.fake_context,
|
||||
fake_share_server)
|
||||
|
||||
self.bind_plugin._wait_for_ports_bind.assert_called_once_with(
|
||||
[fake_neutron_port], fake_share_server)
|
||||
|
||||
|
||||
class NeutronBindSingleNetworkPluginWithNormalTypeTest(test.TestCase):
|
||||
def setUp(self):
|
||||
super(NeutronBindSingleNetworkPluginWithNormalTypeTest, self).setUp()
|
||||
fake_net_id = 'fake net id'
|
||||
fake_subnet_id = 'fake subnet id'
|
||||
config_data = {
|
||||
'DEFAULT': {
|
||||
'neutron_net_id': fake_net_id,
|
||||
'neutron_subnet_id': fake_subnet_id,
|
||||
'neutron_vnic_type': 'normal',
|
||||
}
|
||||
}
|
||||
fake_net = {'subnets': ['fake1', 'fake2', fake_subnet_id]}
|
||||
self.mock_object(
|
||||
neutron_api.API, 'get_network', mock.Mock(return_value=fake_net))
|
||||
self.plugin = plugin.NeutronNetworkPlugin()
|
||||
self.plugin.db = db_api
|
||||
self.fake_context = context.RequestContext(user_id='fake user',
|
||||
project_id='fake project',
|
||||
is_admin=False)
|
||||
|
||||
with test_utils.create_temp_config_with_opts(config_data):
|
||||
self.bind_plugin = plugin.NeutronBindSingleNetworkPlugin()
|
||||
self.bind_plugin.db = db_api
|
||||
|
||||
@mock.patch.object(db_api, 'network_allocation_create',
|
||||
mock.Mock(return_values=fake_network_allocation))
|
||||
@mock.patch.object(db_api, 'share_network_get',
|
||||
mock.Mock(return_value=fake_share_network))
|
||||
@mock.patch.object(db_api, 'share_server_get',
|
||||
mock.Mock(return_value=fake_share_server))
|
||||
def test_allocate_network_one_allocation(self):
|
||||
self.mock_object(self.bind_plugin, '_has_provider_network_extension')
|
||||
self.bind_plugin._has_provider_network_extension.return_value = True
|
||||
save_nw_data = self.mock_object(self.bind_plugin,
|
||||
'_save_neutron_network_data')
|
||||
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')
|
||||
|
||||
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,
|
||||
fake_share_network,
|
||||
allocation_info={'count': 1})
|
||||
|
||||
self.bind_plugin._has_provider_network_extension.assert_any_call()
|
||||
save_nw_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
save_subnet_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
expected_kwargs = {
|
||||
'binding:vnic_type': 'normal',
|
||||
'host_id': 'foohost1',
|
||||
'network_id': fake_share_network['neutron_net_id'],
|
||||
'subnet_id': fake_share_network['neutron_subnet_id'],
|
||||
'device_owner': 'manila:share',
|
||||
'device_id': fake_share_network['id'],
|
||||
}
|
||||
self.bind_plugin.neutron_api.create_port.assert_called_once_with(
|
||||
fake_share_network['project_id'], **expected_kwargs)
|
||||
db_api.network_allocation_create.assert_called_once_with(
|
||||
self.fake_context,
|
||||
fake_network_allocation)
|
||||
self.bind_plugin._wait_for_ports_bind.assert_not_called()
|
||||
|
||||
def test_update_network_allocation(self):
|
||||
self.mock_object(self.bind_plugin, '_wait_for_ports_bind')
|
||||
self.mock_object(db_api, 'network_allocations_get_for_share_server')
|
||||
db_api.network_allocations_get_for_share_server.return_value = [
|
||||
fake_neutron_port]
|
||||
|
||||
self.bind_plugin.update_network_allocation(self.fake_context,
|
||||
fake_share_server)
|
||||
|
||||
self.bind_plugin._wait_for_ports_bind.assert_called_once_with(
|
||||
[fake_neutron_port], fake_share_server)
|
||||
|
@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- Added neutron driver for port bind actions.
|
Loading…
x
Reference in New Issue
Block a user