Implement admin network in generic driver

Implemented admin network support in generic driver
by creating extra ports in service instance.
In order to implement admin export location, Admin must
specify admin_network_id and admin_subnet_id
in driver configuration in manila.conf to create ports
between host and network of choice.

Possible scenarios are covered by this change:
*1: service network.
*2: service network and tenant network.
*3: service network and admin network.
*4: tenant network and admin network.

Admin network and tenant network configurations have
higher priority than service network. If both are
present, service network is not used.

Only admin network export locations are
is_admin_only = True.

Included additional admin_only export location
when creating shares and creating shares from
snapshots.

Removed deprecated 'service_ip' property of
server backend details.

Implements: blueprint admin-network-generic-driver
Change-Id: I8d8694ac3d83aa12a756112dfefebd7e17e32383
This commit is contained in:
Rodrigo Barbieri 2016-02-10 18:30:12 -02:00
parent 86c05e9bf7
commit 447f2b1656
11 changed files with 586 additions and 258 deletions

View File

@ -268,25 +268,39 @@ function create_manila_service_keypair {
# driver, and only if it is configured to mode without handling of share servers.
function create_service_share_servers {
private_net_id=$(nova net-list | grep ' private ' | get_field 1)
created_admin_network=false
for BE in ${MANILA_ENABLED_BACKENDS//,/ }; do
driver_handles_share_servers=$(iniget $MANILA_CONF $BE driver_handles_share_servers)
share_driver=$(iniget $MANILA_CONF $BE share_driver)
generic_driver='manila.share.drivers.generic.GenericShareDriver'
if [[ $(trueorfalse False driver_handles_share_servers) == False && $share_driver == $generic_driver ]]; then
vm_name='manila_service_share_server_'$BE
nova boot $vm_name \
--flavor $MANILA_SERVICE_VM_FLAVOR_NAME \
--image $MANILA_SERVICE_IMAGE_NAME \
--nic net-id=$private_net_id \
--security-groups $MANILA_SERVICE_SECGROUP \
--key-name $MANILA_SERVICE_KEYPAIR_NAME
if [[ $share_driver == $generic_driver ]]; then
if [[ $(trueorfalse False driver_handles_share_servers) == False ]]; then
vm_name='manila_service_share_server_'$BE
nova boot $vm_name \
--flavor $MANILA_SERVICE_VM_FLAVOR_NAME \
--image $MANILA_SERVICE_IMAGE_NAME \
--nic net-id=$private_net_id \
--security-groups $MANILA_SERVICE_SECGROUP \
--key-name $MANILA_SERVICE_KEYPAIR_NAME
vm_id=$(nova show $vm_name | grep ' id ' | get_field 2)
vm_id=$(nova show $vm_name | grep ' id ' | get_field 2)
iniset $MANILA_CONF $BE service_instance_name_or_id $vm_id
iniset $MANILA_CONF $BE service_net_name_or_ip private
iniset $MANILA_CONF $BE tenant_net_name_or_ip private
iniset $MANILA_CONF $BE migration_data_copy_node_ip $PUBLIC_NETWORK_GATEWAY
iniset $MANILA_CONF $BE service_instance_name_or_id $vm_id
iniset $MANILA_CONF $BE service_net_name_or_ip private
iniset $MANILA_CONF $BE tenant_net_name_or_ip private
iniset $MANILA_CONF $BE migration_data_copy_node_ip $PUBLIC_NETWORK_GATEWAY
else
if is_service_enabled neutron; then
if [ $created_admin_network == false ]; then
admin_net_id=$(neutron net-create --tenant-id $TENANT_ID admin_net | grep ' id ' | get_field 2)
admin_subnet_id=$(neutron subnet-create --tenant-id $TENANT_ID --ip_version 4 --no-gateway --name admin_subnet --subnetpool None $admin_net_id $FIXED_RANGE | grep ' id ' | get_field 2)
created_admin_network=true
fi
iniset $MANILA_CONF $BE admin_network_id $admin_net_id
iniset $MANILA_CONF $BE admin_subnet_id $admin_subnet_id
iniset $MANILA_CONF $BE migration_data_copy_node_ip $FIXED_RANGE
fi
fi
fi
done
}

View File

@ -237,7 +237,11 @@ class ShareMigrationFailed(ManilaException):
class ServiceIPNotFound(ManilaException):
message = _("Share migration failed: %(reason)s")
message = _("Service IP for instance not found: %(reason)s")
class AdminIPNotFound(ManilaException):
message = _("Admin port IP for service instance not found: %(reason)s")
class ShareServerNotCreated(ManilaException):

View File

@ -376,6 +376,52 @@ class IpRouteCommand(IpDeviceCommandBase):
self._as_root('append', subnet, 'proto', 'kernel',
'dev', device)
def clear_outdated_routes(self, cidr):
"""Removes duplicated routes for a certain network CIDR.
Removes all routes related to supplied CIDR except for the one
related to this interface device.
:param cidr: The network CIDR to be cleared.
"""
routes = self.list()
items = [x for x in routes
if x['Destination'] == cidr and x.get('Device') and
x['Device'] != self.name]
for item in items:
self.delete_net_route(item['Destination'], item['Device'])
def list(self):
"""List all routes
:return: A dictionary with field 'Destination' and 'Device' for each
route entry. 'Gateway' field is included if route has a gateway.
"""
routes = []
output = self._as_root('list')
lines = output.split('\n')
for line in lines:
items = line.split()
if len(items) > 0:
item = {'Destination': items[0]}
if len(items) > 1:
if items[1] == 'via':
item['Gateway'] = items[2]
if len(items) > 3 and items[3] == 'dev':
item['Device'] = items[4]
if items[1] == 'dev':
item['Device'] = items[2]
routes.append(item)
return routes
def delete_net_route(self, cidr, device):
"""Deletes a route according to suplied CIDR and interface device.
:param cidr: The network CIDR to be removed.
:param device: The network interface device to be removed.
"""
self._as_root('delete', cidr, 'dev', device)
class IpNetnsCommand(IpCommandBase):
COMMAND = 'netns'

View File

@ -340,21 +340,30 @@ class ShareDriver(object):
"""
return None, None
def get_driver_migration_info(self, context, share_instance, share_server):
"""Is called to provide necessary driver migration logic."""
def get_driver_migration_info(self, context, share, share_server):
"""Is called to provide necessary driver migration logic.
:param context: The 'context.RequestContext' object for the request.
:param share: Reference to the share being migrated.
:param share_server: Share server model or None.
:return: A dictionary with migration information.
"""
return None
def get_migration_info(self, context, share_instance, share_server):
"""Is called to provide necessary generic migration logic."""
def get_migration_info(self, context, share, share_server):
"""Is called to provide necessary generic migration logic.
mount_cmd = self._get_mount_command(context, share_instance,
share_server)
:param context: The 'context.RequestContext' object for the request.
:param share: Reference to the share being migrated.
:param share_server: Share server model or None.
:return: A dictionary with migration information.
"""
mount_cmd = self._get_mount_command(context, share, share_server)
umount_cmd = self._get_unmount_command(context, share_instance,
share_server)
umount_cmd = self._get_unmount_command(context, share, share_server)
access = self._get_access_rule_for_data_copy(
context, share_instance, share_server)
context, share, share_server)
return {'mount': mount_cmd,
'umount': umount_cmd,
'access': access}
@ -382,17 +391,18 @@ class ShareDriver(object):
return ['mount', '-t', share_instance['share_proto'].lower()]
def _get_mount_ip(self, share_instance, share_server):
# Note(ganso): DHSS = true drivers may need to override this method
# and use information saved in share_server structure.
mount_ip = self.configuration.safe_get('migration_mounting_backend_ip')
old_ip = share_instance['export_locations'][0]['path']
if mount_ip:
# NOTE(ganso): Does not currently work with hostnames and ipv6.
p = re.compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}")
new_ip = p.sub(mount_ip, old_ip)
return new_ip
else:
return old_ip
path = next((x['path'] for x in share_instance['export_locations']
if x['is_admin_only']), None)
if not path:
mount_ip = self.configuration.safe_get(
'migration_mounting_backend_ip')
path = share_instance['export_locations'][0]['path']
if mount_ip:
# NOTE(ganso): Does not currently work with hostnames and ipv6.
p = re.compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}")
path = p.sub(mount_ip, path)
return path
def _get_unmount_command(self, context, share_instance, share_server):
return ['umount',

View File

@ -215,16 +215,6 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
"No protocol helpers selected for Generic Driver. "
"Please specify using config option 'share_helpers'.")
def _get_access_rule_for_data_copy(self, context, share, share_server):
if not self.driver_handles_share_servers:
service_ip = self.configuration.safe_get(
'migration_data_copy_node_ip')
else:
service_ip = share_server['backend_details']['service_ip']
return {'access_type': 'ip',
'access_level': 'rw',
'access_to': service_ip}
@ensure_server
def create_share(self, context, share, share_server=None):
"""Creates share."""
@ -241,15 +231,28 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
location = helper.create_export(
server_details,
share['name'])
return {
export_list = [{
"path": location,
"is_admin_only": False,
"metadata": {
# TODO(vponomaryov): remove this fake metadata when proper
# appears.
# TODO(vponomaryov): remove this fake metadata when
# proper appears.
"export_location_metadata_example": "example",
},
}
}]
if server_details.get('admin_ip'):
admin_location = location.replace(
server_details['public_address'], server_details['admin_ip'])
export_list.append({
"path": admin_location,
"is_admin_only": True,
"metadata": {
# TODO(vponomaryov): remove this fake metadata when
# proper appears.
"export_location_metadata_example": "example",
},
})
return export_list
@utils.retry(exception.ProcessExecutionError, backoff_rate=1)
def _is_device_file_available(self, server_details, volume):
@ -618,6 +621,7 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
share_server=None):
"""Is called to create share from snapshot."""
helper = self._get_helper(share)
server_details = share_server['backend_details']
volume = self._allocate_container(self.admin_context, share, snapshot)
volume = self._attach_volume(
self.admin_context, share,
@ -625,7 +629,28 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
self._mount_device(share, share_server['backend_details'], volume)
location = helper.create_export(share_server['backend_details'],
share['name'])
return location
export_list = [{
"path": location,
"is_admin_only": False,
"metadata": {
# TODO(vponomaryov): remove this fake metadata when
# proper appears.
"export_location_metadata_example": "example",
},
}]
if server_details.get('admin_ip'):
admin_location = location.replace(
server_details['public_address'], server_details['admin_ip'])
export_list.append({
"path": admin_location,
"is_admin_only": True,
"metadata": {
# TODO(vponomaryov): remove this fake metadata when
# proper appears.
"export_location_metadata_example": "example",
},
})
return export_list
@ensure_server
def extend_share(self, share, new_size, share_server=None):

View File

@ -106,7 +106,16 @@ share_servers_handling_mode_opts = [
"service_instance_network_helper_type",
default=NEUTRON_NAME,
help="Allowed values are %s. " % [NOVA_NAME, NEUTRON_NAME] +
"Only used if driver_handles_share_servers=True.")
"Only used if driver_handles_share_servers=True."),
cfg.StrOpt(
"admin_network_id",
help="ID of neutron network used to communicate with admin network,"
" to create additional admin export locations on."),
cfg.StrOpt(
"admin_subnet_id",
help="ID of neutron subnet used to communicate with admin network,"
" to create additional admin export locations on. "
"Related to 'admin_network_id'."),
]
no_share_servers_handling_mode_opts = [
@ -431,14 +440,18 @@ class ServiceInstanceManager(object):
'password': self.get_config_option('service_instance_password'),
'username': self.get_config_option('service_instance_user'),
'public_address': server['public_address'],
'service_ip': server['service_ip'],
}
if server.get('admin_ip'):
instance_details['admin_ip'] = server['admin_ip']
if server.get('router_id'):
instance_details['router_id'] = server['router_id']
if server.get('service_port_id'):
instance_details['service_port_id'] = server['service_port_id']
if server.get('public_port_id'):
instance_details['public_port_id'] = server['public_port_id']
if server.get('admin_port_id'):
instance_details['admin_port_id'] = server['admin_port_id']
for key in ('password', 'pk_path', 'subnet_id'):
if not instance_details[key]:
instance_details.pop(key)
@ -520,6 +533,9 @@ class ServiceInstanceManager(object):
if network_data.get('public_port'):
fail_safe_data['public_port_id'] = (
network_data['public_port']['id'])
if network_data.get('admin_port'):
fail_safe_data['admin_port_id'] = (
network_data['admin_port']['id'])
try:
create_kwargs = self._get_service_instance_create_kwargs()
service_instance = self.compute_api.server_create(
@ -553,11 +569,13 @@ class ServiceInstanceManager(object):
context, service_instance["id"], sg_id)
if self.network_helper.NAME == NEUTRON_NAME:
service_instance['ip'] = self._get_server_ip(
service_instance,
self.get_config_option("service_network_name"))
public_ip = network_data.get(
'public_port', network_data['service_port'])['fixed_ips']
ip = (network_data.get('service_port',
network_data.get(
'admin_port'))['fixed_ips'])
service_instance['ip'] = ip[0]['ip_address']
public_ip = (network_data.get(
'public_port', network_data.get(
'service_port'))['fixed_ips'])
service_instance['public_address'] = public_ip[0]['ip_address']
else:
net_name = self.network_helper.get_network_name(network_info)
@ -575,7 +593,15 @@ class ServiceInstanceManager(object):
if pair[0] in network_data and 'id' in network_data[pair[0]]:
service_instance[pair[1]] = network_data[pair[0]]['id']
service_instance['service_ip'] = network_data.get('service_ip')
admin_port = network_data.get('admin_port')
if admin_port:
try:
service_instance['admin_ip'] = (
admin_port['fixed_ips'][0]['ip_address'])
except Exception:
msg = _("Admin port is being used but Admin IP was not found.")
LOG.exception(msg)
raise exception.AdminIPNotFound(reason=msg)
return service_instance
@ -700,11 +726,21 @@ class NeutronNetworkHelper(BaseNetworkhelper):
else:
self._network_config_group = None
self.use_admin_port = False
self.use_service_network = True
self._neutron_api = None
self._service_network_id = None
self.connect_share_server_to_tenant_network = (
self.get_config_option('connect_share_server_to_tenant_network'))
self.admin_network_id = self.get_config_option('admin_network_id')
self.admin_subnet_id = self.get_config_option('admin_subnet_id')
if self.admin_network_id and self.admin_subnet_id:
self.use_admin_port = True
if self.use_admin_port and self.connect_share_server_to_tenant_network:
self.use_service_network = False
@property
def NAME(self):
return NEUTRON_NAME
@ -759,7 +795,8 @@ class NeutronNetworkHelper(BaseNetworkhelper):
service_port_id = server_details.get("service_port_id")
public_port_id = server_details.get("public_port_id")
for port_id in (service_port_id, public_port_id):
admin_port_id = server_details.get("admin_port_id")
for port_id in (service_port_id, public_port_id, admin_port_id):
if port_id:
try:
self.neutron_api.delete_port(port_id)
@ -810,11 +847,16 @@ class NeutronNetworkHelper(BaseNetworkhelper):
subnet_name = ('service_subnet_for_handling_of_share_server_for_'
'tenant_subnet_%s' % neutron_subnet_id)
network_data['service_subnet'] = self._get_service_subnet(subnet_name)
if not network_data['service_subnet']:
network_data['service_subnet'] = self.neutron_api.subnet_create(
self.admin_project_id, self.service_network_id, subnet_name,
self._get_cidr_for_subnet())
if self.use_service_network:
network_data['service_subnet'] = self._get_service_subnet(
subnet_name)
if not network_data['service_subnet']:
network_data['service_subnet'] = (
self.neutron_api.subnet_create(
self.admin_project_id, self.service_network_id,
subnet_name, self._get_cidr_for_subnet()))
network_data['ports'] = []
if not self.connect_share_server_to_tenant_network:
network_data['router'] = self._get_private_router(
@ -830,24 +872,28 @@ class NeutronNetworkHelper(BaseNetworkhelper):
'router %(router_id)s.',
{'subnet_id': network_data['service_subnet']['id'],
'router_id': network_data['router']['id']})
network_data['service_port'] = self.neutron_api.create_port(
self.admin_project_id, self.service_network_id,
subnet_id=network_data['service_subnet']['id'],
device_owner='manila')
network_data['ports'] = [network_data['service_port']]
if self.connect_share_server_to_tenant_network:
else:
network_data['public_port'] = self.neutron_api.create_port(
self.admin_project_id, neutron_net_id,
subnet_id=neutron_subnet_id, device_owner='manila')
network_data['ports'].append(network_data['public_port'])
if self.use_service_network:
network_data['service_port'] = self.neutron_api.create_port(
self.admin_project_id, self.service_network_id,
subnet_id=network_data['service_subnet']['id'],
device_owner='manila')
network_data['ports'].append(network_data['service_port'])
if self.use_admin_port:
network_data['admin_port'] = self.neutron_api.create_port(
self.admin_project_id, self.admin_network_id,
subnet_id=self.admin_subnet_id, device_owner='manila')
network_data['ports'].append(network_data['admin_port'])
try:
port = self.setup_connectivity_with_service_instances()
service_ip = self._get_service_ip(
port, network_data['service_subnet']['id'])
except Exception as e:
self.setup_connectivity_with_service_instances()
except Exception:
for port in network_data['ports']:
self.neutron_api.delete_port(port['id'])
raise
@ -855,19 +901,11 @@ class NeutronNetworkHelper(BaseNetworkhelper):
network_data['nics'] = [
{'port-id': port['id']} for port in network_data['ports']]
public_ip = network_data.get(
'public_port', network_data['service_port'])
'public_port', network_data.get('service_port'))
network_data['ip_address'] = public_ip['fixed_ips'][0]['ip_address']
network_data['service_ip'] = service_ip
return network_data
def _get_service_ip(self, port, subnet_id):
for fixed_ips in port['fixed_ips']:
if subnet_id == fixed_ips['subnet_id']:
return fixed_ips['ip_address']
msg = _("Service IP not found for Share Server.")
raise exception.ServiceIPNotFound(reason=msg)
def _get_cidr_for_subnet(self):
"""Returns not used cidr for service subnet creating."""
subnets = self._get_all_service_subnets()
@ -885,12 +923,30 @@ class NeutronNetworkHelper(BaseNetworkhelper):
def setup_connectivity_with_service_instances(self):
"""Sets up connectivity with service instances.
Creates creating port in service network, creating and setting up
required network devices.
Creates host port in service network and/or admin network, creating
and setting up required network devices.
"""
port = self._get_service_port()
port = self._add_fixed_ips_to_service_port(port)
interface_name = self.vif_driver.get_device_name(port)
if self.use_service_network:
port = self._get_service_port(
self.service_network_id, None, 'manila-share')
port = self._add_fixed_ips_to_service_port(port)
interface_name = self.vif_driver.get_device_name(port)
device = ip_lib.IPDevice(interface_name)
self._plug_interface_in_host(interface_name, device, port)
if self.use_admin_port:
port = self._get_service_port(
self.admin_network_id, self.admin_subnet_id,
'manila-admin-share')
interface_name = self.vif_driver.get_device_name(port)
device = ip_lib.IPDevice(interface_name)
for fixed_ip in port['fixed_ips']:
subnet = self.neutron_api.get_subnet(fixed_ip['subnet_id'])
device.route.clear_outdated_routes(subnet['cidr'])
self._plug_interface_in_host(interface_name, device, port)
def _plug_interface_in_host(self, interface_name, device, port):
self.vif_driver.plug(interface_name, port['id'], port['mac_address'])
ip_cidrs = []
for fixed_ip in port['fixed_ips']:
@ -902,14 +958,11 @@ class NeutronNetworkHelper(BaseNetworkhelper):
self.vif_driver.init_l3(interface_name, ip_cidrs)
# ensure that interface is first in the list
device = ip_lib.IPDevice(interface_name)
device.route.pullup_route(interface_name)
# here we are checking for garbage devices from removed service port
self._remove_outdated_interfaces(device)
return port
@utils.synchronized(
"service_instance_remove_outdated_interfaces", external=True)
def _remove_outdated_interfaces(self, device):
@ -940,13 +993,13 @@ class NeutronNetworkHelper(BaseNetworkhelper):
return cidrs
@utils.synchronized("service_instance_get_service_port", external=True)
def _get_service_port(self):
def _get_service_port(self, network_id, subnet_id, device_id):
"""Find or creates service neutron port.
This port will be used for connectivity with service instances.
"""
host = socket.gethostname()
search_opts = {'device_id': 'manila-share',
search_opts = {'device_id': device_id,
'binding:host_id': host}
ports = [port for port in self.neutron_api.
list_ports(**search_opts)]
@ -955,9 +1008,8 @@ class NeutronNetworkHelper(BaseNetworkhelper):
_('Error. Ambiguous service ports.'))
elif not ports:
port = self.neutron_api.create_port(
self.admin_project_id, self.service_network_id,
device_id='manila-share', device_owner='manila:share',
host_id=host)
self.admin_project_id, network_id, subnet_id=subnet_id,
device_id=device_id, device_owner='manila:share', host_id=host)
else:
port = ports[0]
return port
@ -1056,7 +1108,6 @@ class NovaNetworkHelper(BaseNetworkhelper):
def setup_network(self, network_info):
net = self._get_nova_network(network_info['nova_net_id'])
network_info['nics'] = [{'net-id': net['id']}]
network_info['service_ip'] = net['gateway']
return network_info
def get_network_name(self, network_info):

View File

@ -90,6 +90,14 @@ GATEWAY_SAMPLE4 = ("""
default via 10.35.19.254
""")
GATEWAY_SAMPLE5 = ("""
default via 172.24.47.1 dev eth0
10.0.0.0/24 dev tapc226b810-a0 proto kernel scope link src 10.0.0.3
10.254.0.0/28 dev tap6de90453-1c proto kernel scope link src 10.254.0.4
10.35.16.0/22 proto kernel scope link src 10.35.17.97
172.24.4.0/24 via 10.35.19.254 metric 100
""")
DEVICE_ROUTE_SAMPLE = ("10.0.0.0/24 scope link src 10.0.0.2")
SUBNET_SAMPLE1 = ("10.0.0.0/24 dev qr-23380d11-d2 scope link src 10.0.0.1\n"
@ -619,6 +627,42 @@ class TestIpRouteCommand(TestIPCmdBase):
# Check two calls - device get and subnet get
self.assertEqual(2, len(self.parent._run.mock_calls))
def test_list(self):
self.route_cmd._as_root = mock.Mock(return_value=GATEWAY_SAMPLE5)
expected = [{'Destination': 'default',
'Device': 'eth0',
'Gateway': '172.24.47.1'},
{'Destination': '10.0.0.0/24',
'Device': 'tapc226b810-a0'},
{'Destination': '10.254.0.0/28',
'Device': 'tap6de90453-1c'},
{'Destination': '10.35.16.0/22'},
{'Destination': '172.24.4.0/24',
'Gateway': '10.35.19.254'}]
result = self.route_cmd.list()
self.assertEqual(expected, result)
self.route_cmd._as_root.assert_called_once_with('list')
def test_delete_net_route(self):
self.route_cmd._as_root = mock.Mock()
self.route_cmd.delete_net_route('10.0.0.0/24', 'br-ex')
self.route_cmd._as_root.assert_called_once_with(
'delete', '10.0.0.0/24', 'dev', 'br-ex')
def test_clear_outdated_routes(self):
self.route_cmd.delete_net_route = mock.Mock()
list_result = [{'Destination': 'default',
'Device': 'eth0',
'Gateway': '172.24.47.1'},
{'Destination': '10.0.0.0/24',
'Device': 'eth0'},
{'Destination': '10.0.0.0/24',
'Device': 'br-ex'}]
self.route_cmd.list = mock.Mock(return_value=list_result)
self.route_cmd.clear_outdated_routes('10.0.0.0/24')
self.route_cmd.delete_net_route.assert_called_once_with(
'10.0.0.0/24', 'br-ex')
class TestIpNetnsCommand(TestIPCmdBase):
def setUp(self):

View File

@ -313,29 +313,6 @@ class GenericShareDriverTestCase(test.TestCase):
self.assertRaises(exception.ManilaException,
self._driver._setup_helpers)
def test__get_access_rule_for_data_copy_dhss_true(self):
get_access_return = {
'access_level': 'rw',
'access_to': 'fake_ip',
'access_type': 'ip'
}
result = self._driver._get_access_rule_for_data_copy(
self._context, self.share, self.server)
self.assertEqual(get_access_return, result)
def test__get_access_rule_for_data_copy_dhss_false(self):
get_access_return = {
'access_level': 'rw',
'access_to': 'fake_ip',
'access_type': 'ip'
}
CONF.set_default('driver_handles_share_servers', False)
CONF.set_default('migration_data_copy_node_ip', 'fake_ip')
result = self._driver._get_access_rule_for_data_copy(
self._context, self.share, self.server)
self.assertEqual(get_access_return, result)
def test_create_share(self):
volume = 'fake_volume'
volume2 = 'fake_volume2'
@ -346,11 +323,11 @@ class GenericShareDriverTestCase(test.TestCase):
mock.Mock(return_value=volume2))
self.mock_object(self._driver, '_format_device')
self.mock_object(self._driver, '_mount_device')
expected_el = {
expected_el = [{
'is_admin_only': False,
'path': 'fakelocation',
'metadata': {'export_location_metadata_example': 'example'},
}
}]
result = self._driver.create_share(
self._context, self.share, share_server=self.server)
@ -999,6 +976,11 @@ class GenericShareDriverTestCase(test.TestCase):
vol1 = 'fake_vol1'
vol2 = 'fake_vol2'
self._helper_nfs.create_export.return_value = 'fakelocation'
expected_el = [{
'is_admin_only': False,
'path': 'fakelocation',
'metadata': {'export_location_metadata_example': 'example'},
}]
self.mock_object(self._driver, '_allocate_container',
mock.Mock(return_value=vol1))
self.mock_object(self._driver, '_attach_volume',
@ -1011,7 +993,7 @@ class GenericShareDriverTestCase(test.TestCase):
self.snapshot,
share_server=self.server)
self.assertEqual('fakelocation', result)
self.assertEqual(expected_el, result)
self._driver._allocate_container.assert_called_once_with(
self._driver.admin_context, self.share, self.snapshot)
self._driver._attach_volume.assert_called_once_with(

View File

@ -73,6 +73,10 @@ def fake_get_config_option(key):
return 'fake_service_network_name'
elif key == 'interface_driver':
return 'i.am.fake.VifDriver'
elif key == 'admin_network_id':
return None
elif key == 'admin_subnet_id':
return None
else:
return mock.Mock()
@ -493,13 +497,14 @@ class ServiceInstanceManagerTestCase(test.TestCase):
public_port_id='fake_public_port_id'),
)
def test_set_up_service_instance(self, update_data):
fake_network_info = dict(foo='bar', server_id='fake_server_id',
service_ip='fake_ip')
fake_server = dict(
id='fake', ip='1.2.3.4', public_address='1.2.3.4', pk_path=None,
subnet_id='fake-subnet-id', router_id='fake-router-id',
username=self._manager.get_config_option('service_instance_user'),
service_ip='fake_ip')
fake_network_info = {'foo': 'bar', 'server_id': 'fake_server_id'}
fake_server = {
'id': 'fake', 'ip': '1.2.3.4', 'public_address': '1.2.3.4',
'pk_path': None, 'subnet_id': 'fake-subnet-id',
'router_id': 'fake-router-id',
'username': self._manager.get_config_option(
'service_instance_user'),
'admin_ip': 'admin_ip'}
fake_server.update(update_data)
expected_details = fake_server.copy()
expected_details.pop('pk_path')
@ -519,13 +524,14 @@ class ServiceInstanceManagerTestCase(test.TestCase):
self.assertEqual(expected_details, result)
def test_set_up_service_instance_not_available(self):
fake_network_info = dict(foo='bar', server_id='fake_server_id',
service_ip='fake_ip')
fake_server = dict(
id='fake', ip='1.2.3.4', public_address='1.2.3.4', pk_path=None,
subnet_id='fake-subnet-id', router_id='fake-router-id',
username=self._manager.get_config_option('service_instance_user'),
service_ip='fake_ip')
fake_network_info = {'foo': 'bar', 'server_id': 'fake_server_id'}
fake_server = {
'id': 'fake', 'ip': '1.2.3.4', 'public_address': '1.2.3.4',
'pk_path': None, 'subnet_id': 'fake-subnet-id',
'router_id': 'fake-router-id',
'username': self._manager.get_config_option(
'service_instance_user'),
'admin_ip': 'admin_ip'}
expected_details = fake_server.copy()
expected_details.pop('pk_path')
expected_details['instance_id'] = expected_details.pop('id')
@ -958,8 +964,7 @@ class ServiceInstanceManagerTestCase(test.TestCase):
key_data = 'fake_key_name', 'fake_key_path'
instance_name = 'fake_instance_name'
network_info = dict()
network_data = dict(nics=['fake_nic1', 'fake_nic2'],
service_ip='fake_ip')
network_data = {'nics': ['fake_nic1', 'fake_nic2']}
if helper_type == service_instance.NEUTRON_NAME:
network_data['router'] = dict(id='fake_router_id')
server_get = dict(
@ -970,7 +975,9 @@ class ServiceInstanceManagerTestCase(test.TestCase):
public_port=dict(id='fake_public_port',
fixed_ips=[dict(ip_address=ip_address)]),
service_port=dict(id='fake_service_port',
fixed_ips=[dict(ip_address=ip_address)])))
fixed_ips=[{'ip_address': ip_address}]),
admin_port={'id': 'fake_admin_port',
'fixed_ips': [{'ip_address': ip_address}]}))
self.mock_object(service_instance.time, 'time',
mock.Mock(return_value=5))
self.mock_object(self._manager.network_helper, 'setup_network',
@ -989,21 +996,22 @@ class ServiceInstanceManagerTestCase(test.TestCase):
mock.Mock(return_value=server_get))
self.mock_object(self._manager.compute_api,
'add_security_group_to_server')
expected = dict(
id=server_get['id'],
status=server_get['status'],
pk_path=key_data[1],
public_address=ip_address,
router_id=network_data.get('router_id'),
subnet_id=network_data.get('subnet_id'),
instance_id=server_get['id'],
ip=ip_address,
networks=server_get['networks'],
service_ip='fake_ip')
expected = {
'id': server_get['id'],
'status': server_get['status'],
'pk_path': key_data[1],
'public_address': ip_address,
'router_id': network_data.get('router_id'),
'subnet_id': network_data.get('subnet_id'),
'instance_id': server_get['id'],
'ip': ip_address,
'networks': server_get['networks']}
if helper_type == service_instance.NEUTRON_NAME:
expected['router_id'] = network_data['router']['id']
expected['public_port_id'] = 'fake_public_port'
expected['service_port_id'] = 'fake_service_port'
expected['admin_port_id'] = 'fake_admin_port'
expected['admin_ip'] = 'fake_ip_address'
result = self._manager._create_service_instance(
self._manager.admin_context, instance_name, network_info)
@ -1037,6 +1045,83 @@ class ServiceInstanceManagerTestCase(test.TestCase):
self._manager.network_helper.get_network_name.\
assert_called_once_with(network_info)
def test___create_service_instance_neutron_no_admin_ip(self):
self.mock_object(service_instance, 'NeutronNetworkHelper',
mock.Mock(side_effect=FakeNetworkHelper))
config_data = {'DEFAULT': {
'driver_handles_share_servers': True,
'service_instance_user': 'fake_user',
'service_instance_network_helper_type': (
service_instance.NEUTRON_NAME)}}
with test_utils.create_temp_config_with_opts(config_data):
self._manager = service_instance.ServiceInstanceManager()
server_create = {'id': 'fakeid', 'status': 'CREATING', 'networks': {}}
net_name = self._manager.get_config_option("service_network_name")
sg = type('FakeSG', (object, ), {'id': 'fakeid', 'name': 'fakename'})
ip_address = 'fake_ip_address'
service_image_id = 'fake_service_image_id'
key_data = 'fake_key_name', 'fake_key_path'
instance_name = 'fake_instance_name'
network_info = {}
network_data = {
'nics': ['fake_nic1', 'fake_nic2'],
'router_id': 'fake_router_id', 'subnet_id': 'fake_subnet_id',
'public_port': {'id': 'fake_public_port',
'fixed_ips': [{'ip_address': ip_address}]},
'service_port': {'id': 'fake_service_port',
'fixed_ips': [{'ip_address': ip_address}]},
'admin_port': {'id': 'fake_admin_port',
'fixed_ips': []},
'router': {'id': 'fake_router_id'}}
server_get = {
'id': 'fakeid', 'status': 'ACTIVE', 'networks':
{net_name: [ip_address]}}
self.mock_object(service_instance.time, 'time',
mock.Mock(return_value=5))
self.mock_object(self._manager.network_helper, 'setup_network',
mock.Mock(return_value=network_data))
self.mock_object(self._manager.network_helper, 'get_network_name',
mock.Mock(return_value=net_name))
self.mock_object(self._manager, '_get_service_image',
mock.Mock(return_value=service_image_id))
self.mock_object(self._manager, '_get_key',
mock.Mock(return_value=key_data))
self.mock_object(self._manager, '_get_or_create_security_group',
mock.Mock(return_value=sg))
self.mock_object(self._manager.compute_api, 'server_create',
mock.Mock(return_value=server_create))
self.mock_object(self._manager.compute_api, 'server_get',
mock.Mock(return_value=server_get))
self.mock_object(self._manager.compute_api,
'add_security_group_to_server')
self.assertRaises(
exception.AdminIPNotFound, self._manager._create_service_instance,
self._manager.admin_context, instance_name, network_info)
self.assertTrue(service_instance.time.time.called)
self._manager.network_helper.setup_network.assert_called_once_with(
network_info)
self._manager._get_service_image.assert_called_once_with(
self._manager.admin_context)
self._manager._get_key.assert_called_once_with(
self._manager.admin_context)
self._manager._get_or_create_security_group.assert_called_once_with(
self._manager.admin_context)
self._manager.compute_api.server_create.assert_called_once_with(
self._manager.admin_context, name=instance_name,
image=service_image_id, flavor=100,
key_name=key_data[0], nics=network_data['nics'],
availability_zone=service_instance.CONF.storage_availability_zone)
self._manager.compute_api.server_get.assert_called_once_with(
self._manager.admin_context, server_create['id'])
self._manager.compute_api.add_security_group_to_server.\
assert_called_once_with(
self._manager.admin_context, server_get['id'], sg.id)
self._manager.network_helper.get_network_name.assert_has_calls([])
@ddt.data(
dict(
instance_id_included=False,
@ -1652,15 +1737,14 @@ class NeutronNetworkHelperTestCase(test.TestCase):
instance, '_get_cidr_for_subnet', mock.Mock(return_value=cidr))
self.mock_object(
instance, '_get_service_subnet', mock.Mock(return_value=None))
self.mock_object(
instance, '_get_service_ip', mock.Mock(return_value='fake_ip'))
expected = dict(
ip_address=self.public_port['fixed_ips'][0]['ip_address'],
public_port=self.public_port, service_ip='fake_ip',
service_port=self.service_port, service_subnet=service_subnet,
ports=[self.service_port, self.public_port],
nics=[{'port-id': self.service_port['id']},
{'port-id': self.public_port['id']}])
expected = {
'ip_address': self.public_port['fixed_ips'][0]['ip_address'],
'public_port': self.public_port,
'service_port': self.service_port,
'service_subnet': service_subnet,
'ports': [self.public_port, self.service_port],
'nics': [{'port-id': self.public_port['id']},
{'port-id': self.service_port['id']}]}
result = instance.setup_network(network_info)
@ -1671,7 +1755,54 @@ class NeutronNetworkHelperTestCase(test.TestCase):
instance._get_cidr_for_subnet.assert_called_once_with()
self.assertTrue(service_instance.neutron.API.subnet_create.called)
self.assertTrue(service_instance.neutron.API.create_port.called)
self.assertTrue(instance._get_service_ip.called)
def test_setup_network_and_connect_share_server_to_tenant_net_admin(self):
def fake_create_port(*aargs, **kwargs):
if aargs[1] == 'fake_admin_network_id':
return self.admin_port
elif aargs[1] == 'fake_tenant_network_id':
return self.public_port
else:
raise exception.ManilaException('Got unexpected data')
admin_project_id = 'fake_admin_project_id'
network_info = {
'neutron_net_id': 'fake_tenant_network_id',
'neutron_subnet_id': 'fake_tenant_subnet_id'}
self.admin_port = {
'id': 'fake_admin_port_id',
'fixed_ips': [{'ip_address': 'fake_admin_port_ip_address'}]}
self.public_port = {
'id': 'fake_tenant_port_id',
'fixed_ips': [{'ip_address': 'fake_public_port_ip_address'}]}
instance = self._init_neutron_network_plugin()
instance.use_admin_port = True
instance.use_service_network = False
instance.admin_network_id = 'fake_admin_network_id'
instance.admin_subnet_id = 'fake_admin_subnet_id'
instance.connect_share_server_to_tenant_network = True
self.mock_object(
service_instance.neutron.API, 'admin_project_id',
mock.Mock(return_value=admin_project_id))
self.mock_object(
service_instance.neutron.API, 'create_port',
mock.Mock(side_effect=fake_create_port))
self.mock_object(
instance, 'setup_connectivity_with_service_instances')
expected = {
'ip_address': self.public_port['fixed_ips'][0]['ip_address'],
'public_port': self.public_port,
'admin_port': self.admin_port,
'ports': [self.public_port, self.admin_port],
'nics': [{'port-id': self.public_port['id']},
{'port-id': self.admin_port['id']}]}
result = instance.setup_network(network_info)
self.assertEqual(expected, result)
instance.setup_connectivity_with_service_instances.\
assert_called_once_with()
self.assertTrue(service_instance.neutron.API.create_port.called)
@ddt.data(None, exception.NetworkException(code=400))
def test_setup_network_using_router_success(self, return_obj):
@ -1680,11 +1811,17 @@ class NeutronNetworkHelperTestCase(test.TestCase):
neutron_net_id='fake_tenant_network_id',
neutron_subnet_id='fake_tenant_subnet_id')
cidr = '13.0.0.0/24'
self.admin_port = {
'id': 'fake_admin_port_id',
'fixed_ips': [{'ip_address': 'fake_admin_port_ip_address'}]}
self.service_port = dict(
id='fake_service_port_id',
fixed_ips=[dict(ip_address='fake_service_port_ip_address')])
service_subnet = dict(id='fake_service_subnet')
instance = self._init_neutron_network_plugin()
instance.use_admin_port = True
instance.admin_network_id = 'fake_admin_network_id'
instance.admin_subnet_id = 'fake_admin_subnet_id'
instance.connect_share_server_to_tenant_network = False
self.mock_object(instance, '_get_service_network_id',
mock.Mock(return_value='fake_service_network_id'))
@ -1694,7 +1831,7 @@ class NeutronNetworkHelperTestCase(test.TestCase):
mock.Mock(return_value=admin_project_id))
self.mock_object(
service_instance.neutron.API, 'create_port',
mock.Mock(return_value=self.service_port))
mock.Mock(side_effect=[self.service_port, self.admin_port]))
self.mock_object(
service_instance.neutron.API, 'subnet_create',
mock.Mock(return_value=service_subnet))
@ -1708,13 +1845,14 @@ class NeutronNetworkHelperTestCase(test.TestCase):
instance, '_get_cidr_for_subnet', mock.Mock(return_value=cidr))
self.mock_object(
instance, '_get_service_subnet', mock.Mock(return_value=None))
self.mock_object(
instance, '_get_service_ip', mock.Mock(return_value='fake_ip'))
expected = dict(
ip_address=self.service_port['fixed_ips'][0]['ip_address'],
service_port=self.service_port, service_subnet=service_subnet,
ports=[self.service_port], router=router, service_ip='fake_ip',
nics=[{'port-id': self.service_port['id']}])
expected = {
'ip_address': self.service_port['fixed_ips'][0]['ip_address'],
'service_port': self.service_port,
'service_subnet': service_subnet,
'admin_port': self.admin_port, 'router': router,
'ports': [self.service_port, self.admin_port],
'nics': [{'port-id': self.service_port['id']},
{'port-id': self.admin_port['id']}]}
result = instance.setup_network(network_info)
@ -1729,7 +1867,6 @@ class NeutronNetworkHelperTestCase(test.TestCase):
network_info['neutron_net_id'], network_info['neutron_subnet_id'])
service_instance.neutron.API.router_add_interface.\
assert_called_once_with(router['id'], service_subnet['id'])
self.assertTrue(instance._get_service_ip.called)
def test_setup_network_using_router_addon_of_interface_failed(self):
network_info = dict(
@ -1813,36 +1950,6 @@ class NeutronNetworkHelperTestCase(test.TestCase):
service_instance.neutron.API.delete_port.assert_has_calls([
mock.call(self.service_port['id'])])
def test__get_service_ip(self):
fake_division_mask = fake_get_config_option(
'service_network_division_mask')
fake_subnet = fake_network.FakeSubnet(
cidr='10.254.0.0/%s' % fake_division_mask)
fake_port = fake_network.FakePort(fixed_ips=[
{'subnet_id': fake_subnet['id'], 'ip_address': '10.254.0.2'}],
mac_address='fake_mac_address')
instance = self._init_neutron_network_plugin()
result = instance._get_service_ip(fake_port, fake_subnet['id'])
# result should be equal to fake_port.fixed_ips[0]['ip_address']
self.assertEqual(fake_port.fixed_ips[0]['ip_address'], result)
def test__get_service_ip_exception(self):
fake_division_mask = fake_get_config_option(
'service_network_division_mask')
fake_subnet = fake_network.FakeSubnet(
cidr='10.254.0.0/%s' % fake_division_mask)
fake_port = fake_network.FakePort(fixed_ips=[
{'subnet_id': 'another_fake_id', 'ip_address': '10.254.0.2'}],
mac_address='fake_mac_address')
instance = self._init_neutron_network_plugin()
self.assertRaises(
exception.ServiceIPNotFound,
instance._get_service_ip, fake_port, fake_subnet['id'])
def test__get_cidr_for_subnet_success(self):
expected = (
fake_get_config_option('service_network_cidr').split('/')[0] +
@ -1877,47 +1984,70 @@ class NeutronNetworkHelperTestCase(test.TestCase):
def test_setup_connectivity_with_service_instances(self):
instance = self._init_neutron_network_plugin()
interface_name = 'fake_interface_name'
instance.use_admin_port = True
instance.admin_network_id = 'fake_admin_network_id'
instance.admin_subnet_id = 'fake_admin_subnet_id'
interface_name_service = 'fake_interface_name_service'
interface_name_admin = 'fake_interface_name_admin'
fake_division_mask = fake_get_config_option(
'service_network_division_mask')
fake_subnet = fake_network.FakeSubnet(
fake_subnet_service = fake_network.FakeSubnet(
cidr='10.254.0.0/%s' % fake_division_mask)
fake_port = fake_network.FakePort(fixed_ips=[
{'subnet_id': fake_subnet['id'], 'ip_address': '10.254.0.2'}],
fake_subnet_admin = fake_network.FakeSubnet(id='fake_admin_subnet_id',
cidr='10.0.0.0/24')
fake_service_port = fake_network.FakePort(fixed_ips=[
{'subnet_id': fake_subnet_service['id'],
'ip_address': '10.254.0.2'}], mac_address='fake_mac_address')
fake_admin_port = fake_network.FakePort(fixed_ips=[
{'subnet_id': fake_subnet_admin['id'], 'ip_address': '10.0.0.4'}],
mac_address='fake_mac_address')
self.mock_object(instance, '_get_service_port',
mock.Mock(return_value=fake_port))
mock.Mock(side_effect=[fake_service_port,
fake_admin_port]))
self.mock_object(instance, '_add_fixed_ips_to_service_port',
mock.Mock(return_value=fake_port))
mock.Mock(return_value=fake_service_port))
self.mock_object(instance.vif_driver, 'get_device_name',
mock.Mock(return_value=interface_name))
mock.Mock(side_effect=[interface_name_service,
interface_name_admin]))
self.mock_object(instance.neutron_api, 'get_subnet',
mock.Mock(return_value=fake_subnet))
mock.Mock(side_effect=[fake_subnet_service,
fake_subnet_admin,
fake_subnet_admin]))
self.mock_object(instance, '_remove_outdated_interfaces')
self.mock_object(instance.vif_driver, 'plug')
device_mock = mock.Mock()
self.mock_object(service_instance.ip_lib, 'IPDevice',
mock.Mock(return_value=device_mock))
result = instance.setup_connectivity_with_service_instances()
instance.setup_connectivity_with_service_instances()
instance._get_service_port.assert_called_once_with()
instance.vif_driver.get_device_name.assert_called_once_with(fake_port)
instance.vif_driver.plug.assert_called_once_with(
interface_name, fake_port['id'], fake_port['mac_address'])
instance.neutron_api.get_subnet.assert_called_once_with(
fake_subnet['id'])
instance.vif_driver.init_l3.assert_called_once_with(
interface_name, ['10.254.0.2/%s' % fake_division_mask])
service_instance.ip_lib.IPDevice.assert_called_once_with(
interface_name)
device_mock.route.pullup_route.assert_called_once_with(interface_name)
instance._remove_outdated_interfaces.assert_called_once_with(
device_mock)
# result should be equal to fake_port
self.assertEqual(fake_port, result)
instance._get_service_port.assert_has_calls([
mock.call(instance.service_network_id, None, 'manila-share'),
mock.call('fake_admin_network_id', 'fake_admin_subnet_id',
'manila-admin-share')])
instance.vif_driver.get_device_name.assert_has_calls([
mock.call(fake_service_port), mock.call(fake_admin_port)])
instance.vif_driver.plug.assert_has_calls([
mock.call(interface_name_service, fake_service_port['id'],
fake_service_port['mac_address']),
mock.call(interface_name_admin, fake_admin_port['id'],
fake_admin_port['mac_address'])])
instance.neutron_api.get_subnet.assert_has_calls([
mock.call(fake_subnet_service['id']),
mock.call(fake_subnet_admin['id']),
mock.call(fake_subnet_admin['id'])])
instance.vif_driver.init_l3.assert_has_calls([
mock.call(interface_name_service,
['10.254.0.2/%s' % fake_division_mask]),
mock.call(interface_name_admin, ['10.0.0.4/24'])])
service_instance.ip_lib.IPDevice.assert_has_calls([
mock.call(interface_name_service),
mock.call(interface_name_admin)])
device_mock.route.pullup_route.assert_has_calls([
mock.call(interface_name_service),
mock.call(interface_name_admin)])
instance._remove_outdated_interfaces.assert_called_with(device_mock)
def test__get_set_of_device_cidrs(self):
device = fake_network.FakeDevice('foo')
@ -1970,14 +2100,15 @@ class NeutronNetworkHelperTestCase(test.TestCase):
self.mock_object(instance.neutron_api, 'update_port_fixed_ips',
mock.Mock(return_value=fake_service_port))
result = instance._get_service_port()
result = instance._get_service_port(instance.service_network_id,
None, 'manila-share')
instance.neutron_api.list_ports.assert_called_once_with(
**fake_port_values)
instance.neutron_api.create_port.assert_called_once_with(
instance.admin_project_id, instance.service_network_id,
device_id='manila-share', device_owner='manila:share',
host_id='fake_host')
host_id='fake_host', subnet_id=None)
service_instance.socket.gethostname.assert_called_once_with()
self.assertFalse(instance.neutron_api.update_port_fixed_ips.called)
self.assertEqual(fake_service_port, result)
@ -1996,7 +2127,8 @@ class NeutronNetworkHelperTestCase(test.TestCase):
self.mock_object(instance.neutron_api, 'update_port_fixed_ips',
mock.Mock(return_value=fake_service_port))
result = instance._get_service_port()
result = instance._get_service_port(instance.service_network_id,
None, 'manila-share')
instance.neutron_api.list_ports.assert_called_once_with(
**fake_port_values)
@ -2022,14 +2154,15 @@ class NeutronNetworkHelperTestCase(test.TestCase):
self.mock_object(instance.neutron_api, 'update_port_fixed_ips',
mock.Mock(return_value=fake_service_port))
result = instance._get_service_port()
result = instance._get_service_port(instance.service_network_id,
None, 'manila-share')
instance.neutron_api.list_ports.assert_called_once_with(
**fake_port)
instance.neutron_api.create_port.assert_called_once_with(
instance.admin_project_id, instance.service_network_id,
device_id='manila-share', device_owner='manila:share',
host_id='fake_host')
host_id='fake_host', subnet_id=None)
service_instance.socket.gethostname.assert_called_once_with()
self.assertFalse(instance.neutron_api.update_port_fixed_ips.called)
self.assertEqual(fake_service_port, result)
@ -2046,7 +2179,8 @@ class NeutronNetworkHelperTestCase(test.TestCase):
self.mock_object(instance.neutron_api, 'create_port',
mock.Mock(return_value=fake_service_port))
self.assertRaises(
exception.ServiceInstanceException, instance._get_service_port)
exception.ServiceInstanceException, instance._get_service_port,
instance.service_network_id, None, 'manila-share')
self.assertFalse(instance.neutron_api.create_port.called)
def test__add_fixed_ips_to_service_port(self):
@ -2244,10 +2378,9 @@ class NovaNetworkHelperTestCase(test.TestCase):
instance = service_instance.NovaNetworkHelper(self.fake_manager)
self.mock_object(instance.compute_api, 'network_get',
mock.Mock(return_value=network))
expected = dict(
nova_net_id=network_info['nova_net_id'],
nics=[{'net-id': network['id']}],
service_ip='fake_gateway_ip')
expected = {
'nova_net_id': network_info['nova_net_id'],
'nics': [{'net-id': network['id']}]}
result = instance.setup_network(network_info)

View File

@ -492,7 +492,8 @@ class ShareDriverTestCase(test.TestCase):
'access_to': None}}
fake_share = {'id': 'fake_id',
'share_proto': 'fake_proto',
'export_locations': [{'path': '/fake/fake_id'}]}
'export_locations': [{'path': '/fake/fake_id',
'is_admin_only': True}]}
driver.CONF.set_default('driver_handles_share_servers', False)
share_driver = driver.ShareDriver(False)
@ -514,7 +515,9 @@ class ShareDriverTestCase(test.TestCase):
'access_to': '100.100.100.100'}}
fake_share = {'id': 'fake_id',
'export_locations': [{'path': '/5.5.5.5/fake_id'}]}
'share_proto': 'fake_proto',
'export_locations': [{'path': '/5.5.5.5/fake_id',
'is_admin_only': False}]}
driver.CONF.set_default('driver_handles_share_servers', False)
driver.CONF.set_default('migration_protocol_mount_command',

View File

@ -175,7 +175,15 @@ class ShareBasicOpsBase(manager.ShareScenarioTest):
instance = self.boot_instance()
self.allow_access_ip(self.share['id'], instance=instance)
ssh_client = self.init_ssh(instance)
for location in self.share['export_locations']:
if utils.is_microversion_lt(CONF.share.max_api_microversion, "2.9"):
locations = self.share['export_locations']
else:
exports = self.shares_v2_client.list_share_export_locations(
self.share['id'])
locations = [x['path'] for x in exports]
for location in locations:
self.mount_share(location, ssh_client)
self.umount_share(ssh_client)
self.servers_client.delete_server(instance['id'])
@ -192,10 +200,14 @@ class ShareBasicOpsBase(manager.ShareScenarioTest):
self.allow_access_ip(self.share['id'], instance=instance1)
ssh_client_inst1 = self.init_ssh(instance1)
# TODO(vponomaryov): use separate API for getting export location for
# share when "v2" client is used.
first_location = self.share['export_locations'][0]
self.mount_share(first_location, ssh_client_inst1)
if utils.is_microversion_lt(CONF.share.max_api_microversion, "2.9"):
locations = self.share['export_locations']
else:
exports = self.shares_v2_client.list_share_export_locations(
self.share['id'])
locations = [x['path'] for x in exports]
self.mount_share(locations[0], ssh_client_inst1)
self.addCleanup(self.umount_share,
ssh_client_inst1)
self.write_data(test_data, ssh_client_inst1)
@ -204,7 +216,7 @@ class ShareBasicOpsBase(manager.ShareScenarioTest):
instance2 = self.boot_instance()
self.allow_access_ip(self.share['id'], instance=instance2)
ssh_client_inst2 = self.init_ssh(instance2)
self.mount_share(first_location, ssh_client_inst2)
self.mount_share(locations[0], ssh_client_inst2)
self.addCleanup(self.umount_share,
ssh_client_inst2)
data = self.read_data(ssh_client_inst2)
@ -244,10 +256,14 @@ class ShareBasicOpsBase(manager.ShareScenarioTest):
cleanup=False)
ssh_client = self.init_ssh(instance1)
# TODO(vponomaryov): use separate API for getting export location for
# share when "v2" client is used.
first_location = self.share['export_locations'][0]
self.mount_share(first_location, ssh_client)
if utils.is_microversion_lt(CONF.share.max_api_microversion, "2.9"):
locations = self.share['export_locations']
else:
exports = self.shares_v2_client.list_share_export_locations(
self.share['id'])
locations = [x['path'] for x in exports]
self.mount_share(locations[0], ssh_client)
ssh_client.exec_command("mkdir -p /mnt/f1")
ssh_client.exec_command("mkdir -p /mnt/f2")
@ -271,20 +287,20 @@ class ShareBasicOpsBase(manager.ShareScenarioTest):
self.umount_share(ssh_client)
share = self.migrate_share(share['id'], dest_pool)
if utils.is_microversion_supported("2.9"):
second_location = (
self.shares_v2_client.list_share_export_locations(
share['id'])[0]['path'])
if utils.is_microversion_lt(CONF.share.max_api_microversion, "2.9"):
new_locations = self.share['export_locations']
else:
# NOTE(vponomaryov): following approach is valid for picking up
# export location only using microversions lower than '2.9'.
second_location = share['export_locations'][0]
new_exports = self.shares_v2_client.list_share_export_locations(
self.share['id'])
new_locations = [x['path'] for x in new_exports]
self.assertEqual(dest_pool, share['host'])
self.assertNotEqual(first_location, second_location)
locations.sort()
new_locations.sort()
self.assertNotEqual(locations, new_locations)
self.assertEqual('migration_success', share['task_state'])
self.mount_share(second_location, ssh_client)
self.mount_share(new_locations[0], ssh_client)
output = ssh_client.exec_command("ls -lRA --ignore=lost+found /mnt")
@ -301,7 +317,7 @@ class TestShareBasicOpsNFS(ShareBasicOpsBase):
protocol = "NFS"
def mount_share(self, location, ssh_client):
ssh_client.exec_command("sudo mount \"%s\" /mnt" % location)
ssh_client.exec_command("sudo mount -vt nfs \"%s\" /mnt" % location)
class TestShareBasicOpsCIFS(ShareBasicOpsBase):