Implement additional driver mode for Generic driver

Add possibility to run Generic driver without handling of share servers. It
allows us to create shares, without share-networks defined, on one specific
Nova VM.
Added three (3) new config options that are used only with new mode:
- 'service_instance_name_or_id' expects string with name or id of Nova VM.
- 'service_net_name_or_ip' expects name of network that Nova VM is switched to
  or IP itself. Used for handle operation of share.
- 'tenant_net_name_or_ip' expects name of network that Nova VM is switched to
  or IP itself. Used for exporting share to end users.
All three new config options are required if new mode is enabled.
They will be skipped if driver mode with handling of share servers is enabled.

Implements bp single-svm-mode-for-generic-driver

Change-Id: I48864b002e4174728136d093b1a17dad2edec605
This commit is contained in:
Valeriy Ponomaryov 2015-01-22 15:40:28 +02:00 committed by vponomaryov
parent d52cdf237d
commit 53b40423f4
8 changed files with 446 additions and 95 deletions

View File

@ -20,6 +20,7 @@ import sys
from novaclient import exceptions as nova_exception
from novaclient import service_catalog
from novaclient import utils
from novaclient.v1_1 import client as nova_client
from novaclient.v1_1.contrib import assisted_volume_snapshots
from novaclient.v1_1 import servers as nova_servers
@ -27,6 +28,7 @@ from oslo_config import cfg
from manila.db import base
from manila import exception
from manila.i18n import _
from manila.openstack.common import log as logging
@ -181,6 +183,15 @@ class API(base.Base):
novaclient(context).servers.get(instance_id)
)
def server_get_by_name_or_id(self, context, instance_name_or_id):
try:
server = utils.find_resource(
novaclient(context).servers, instance_name_or_id)
except nova_exception.CommandError as e:
msg = _("Failed to get Nova VM. %s") % e
raise exception.ManilaException(msg)
return _untranslate_server_summary_view(server)
def server_list(self, context, search_opts=None, all_tenants=False):
if search_opts is None:
search_opts = {}

View File

@ -109,7 +109,9 @@ _global_opt_lists = [
manila.share.drivers.huawei.huawei_nas.huawei_opts,
manila.share.drivers.ibm.gpfs.gpfs_share_opts,
manila.share.drivers.netapp.cluster_mode.NETAPP_NAS_OPTS,
manila.share.drivers.service_instance.server_opts,
manila.share.drivers.service_instance.common_opts,
manila.share.drivers.service_instance.no_share_servers_handling_mode_opts,
manila.share.drivers.service_instance.share_servers_handling_mode_opts,
manila.share.drivers.zfssa.zfssashare.ZFSSA_OPTS,
manila.share.manager.share_manager_opts,
manila.volume._volume_opts,

View File

@ -85,22 +85,35 @@ CONF.register_opts(share_opts)
def ensure_server(f):
def wrap(self, *args, **kwargs):
server = kwargs.get('share_server')
context = args[0]
if not server:
# For now generic driver does not support flat networking.
# When we implement flat networking in generic driver
# we will not need share server to be passed and
# will change this logic.
raise exception.ManilaException(_('Share server not found.'))
server = kwargs.get('share_server')
if not self.driver_handles_share_servers:
if not server:
server = self.service_instance_manager.get_common_server()
kwargs['share_server'] = server
else:
raise exception.ManilaException(
_("Share server handling is not available. "
"But 'share_server' was provided. '%s'. "
"Share network should not be used.") % server['id'])
elif not server:
raise exception.ManilaException(
_("Share server handling is enabled. But 'share_server' "
"is not provided. Make sure you used 'share_network'."))
if not server.get('backend_details'):
raise exception.ManilaException(_('Share server backend '
'details missing.'))
raise exception.ManilaException(
_("Share server '%s' does not have backend details.") %
server['id'])
if not self.service_instance_manager.ensure_service_instance(
context, server['backend_details']):
raise exception.ServiceInstanceUnavailable()
return f(self, *args, **kwargs)
return wrap
@ -109,11 +122,11 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
def __init__(self, db, *args, **kwargs):
"""Do initialization."""
super(GenericShareDriver, self).__init__(True, *args, **kwargs)
super(GenericShareDriver, self).__init__(
[False, True], *args, **kwargs)
self.admin_context = context.get_admin_context()
self.db = db
self.configuration.append_config_values(share_opts)
self.configuration.append_config_values(service_instance.server_opts)
self._helpers = {}
self.backend_name = self.configuration.safe_get(
'share_backend_name') or "Cinder_Volumes"
@ -479,6 +492,8 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
def delete_share(self, context, share, share_server=None):
"""Deletes share."""
if not self.driver_handles_share_servers:
share_server = self.service_instance_manager.get_common_server()
if self._is_share_server_active(context, share_server):
self._get_helper(share).remove_export(
share_server['backend_details'], share['name'])
@ -490,7 +505,6 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
# with any reason that caused absence of Nova instances.
self._deallocate_container(self.admin_context, share)
@ensure_server
def create_snapshot(self, context, snapshot, share_server=None):
"""Creates a snapshot."""
volume = self._get_volume(self.admin_context, snapshot['share_id'])
@ -515,7 +529,6 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
'created in %ss. Giving up') %
self.configuration.max_time_to_create_volume)
@ensure_server
def delete_snapshot(self, context, snapshot, share_server=None):
"""Deletes a snapshot."""
volume_snapshot = self._get_volume_snapshot(self.admin_context,

View File

@ -1,4 +1,5 @@
# Copyright (c) 2014 NetApp, Inc.
# Copyright (c) 2015 Mirantis, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -25,7 +26,7 @@ from oslo_config import cfg
from oslo_utils import importutils
import six
from manila.common import constants
from manila.common import constants as const
from manila import compute
from manila import context
from manila import exception
@ -39,7 +40,7 @@ from manila import utils
LOG = logging.getLogger(__name__)
server_opts = [
share_servers_handling_mode_opts = [
cfg.StrOpt('service_image_name',
default='manila-service-image',
help="Name of image in glance, that will be used to create "
@ -47,11 +48,6 @@ server_opts = [
cfg.StrOpt('service_instance_name_template',
default='manila_service_instance_%s',
help="Name of service instance."),
cfg.StrOpt('service_instance_user',
help="User in service instance."),
cfg.StrOpt('service_instance_password',
default=None,
help="Password to service instance user."),
cfg.StrOpt('manila_service_keypair_name',
default='manila-service',
help="Name of keypair that will be created and used "
@ -59,12 +55,6 @@ server_opts = [
cfg.StrOpt('path_to_public_key',
default='~/.ssh/id_rsa.pub',
help="Path to hosts public key."),
cfg.StrOpt('path_to_private_key',
default='~/.ssh/id_rsa',
help="Path to hosts private key."),
cfg.IntOpt('max_time_to_build_instance',
default=300,
help="Maximum time to wait for creating service instance."),
cfg.StrOpt('service_instance_security_group',
default="manila-service",
help="Name of security group, that will be used for "
@ -93,8 +83,48 @@ server_opts = [
help='Attach share server directly to share network.'),
]
no_share_servers_handling_mode_opts = [
cfg.StrOpt(
"service_instance_name_or_id",
help="Name or ID of service instance in Nova to use for share "
"exports. Used only when share servers handling is disabled."),
cfg.StrOpt(
"service_net_name_or_ip",
help="Can be either name of network that is used by service "
"instance within Nova to get IP address or IP address itself "
"for managing shares there. "
"Used only when share servers handling is disabled."),
cfg.StrOpt(
"tenant_net_name_or_ip",
help="Can be either name of network that is used by service "
"instance within Nova to get IP address or IP address itself "
"for exporting shares. "
"Used only when share servers handling is disabled."),
]
common_opts = [
cfg.StrOpt(
"service_instance_user",
help="User in service instance that will be used for authentication."),
cfg.StrOpt(
"service_instance_password",
default=None,
secret=True,
help="Password for service instance user."),
cfg.StrOpt(
"path_to_private_key",
default="~/.ssh/id_rsa",
help="Path to host's private key."),
cfg.IntOpt(
"max_time_to_build_instance",
default=300,
help="Maximum time in seconds to wait for creating service instance."),
]
CONF = cfg.CONF
CONF.register_opts(server_opts)
CONF.register_opts(common_opts)
CONF.register_opts(no_share_servers_handling_mode_opts)
CONF.register_opts(share_servers_handling_mode_opts)
lock = threading.Lock()
@ -126,20 +156,45 @@ class ServiceInstanceManager(object):
value = CONF.get(key)
return value
def __init__(self, db, *args, **kwargs):
def __init__(self, db, driver_config):
"""Do initialization."""
super(ServiceInstanceManager, self).__init__()
self.driver_config = None
if "driver_config" in kwargs:
self.driver_config = kwargs["driver_config"]
self.db = db
self.driver_config = driver_config
self.driver_config.append_config_values(common_opts)
if self.get_config_option("driver_handles_share_servers"):
self.driver_config.append_config_values(
share_servers_handling_mode_opts)
else:
self.driver_config.append_config_values(
no_share_servers_handling_mode_opts)
if not self.get_config_option("service_instance_user"):
raise exception.ServiceInstanceException(_('Service instance user '
'is not specified'))
raise exception.ServiceInstanceException(
_('Service instance user is not specified.'))
self.admin_context = context.get_admin_context()
self._execute = utils.execute
self.compute_api = compute.API()
self.neutron_api = neutron.API()
self.db = db
self.path_to_private_key = self.get_config_option(
"path_to_private_key")
self.max_time_to_build_instance = self.get_config_option(
"max_time_to_build_instance")
if self.get_config_option("driver_handles_share_servers"):
self.neutron_api = neutron.API()
self.path_to_public_key = self.get_config_option(
"path_to_public_key")
self.connect_share_server_to_tenant_network = (
self.get_config_option(
'connect_share_server_to_tenant_network'))
self._get_service_tenant_id()
self.service_network_id = self._get_service_network()
self.vif_driver = importutils.import_class(
self.get_config_option("interface_driver"))()
self._setup_connectivity_with_service_instances()
def _get_service_tenant_id(self):
attempts = 5
while attempts:
try:
@ -152,17 +207,57 @@ class ServiceInstanceManager(object):
else:
raise exception.ServiceInstanceException(_('Can not receive '
'service tenant id.'))
self.service_network_id = self._get_service_network()
self.vif_driver = importutils.import_class(
self.get_config_option("interface_driver"))()
self._setup_connectivity_with_service_instances()
self.max_time_to_build_instance = self.get_config_option(
"max_time_to_build_instance")
self.path_to_private_key = self.get_config_option(
"path_to_private_key")
self.path_to_public_key = self.get_config_option("path_to_public_key")
self.connect_share_server_to_tenant_network = self.get_config_option(
'connect_share_server_to_tenant_network')
def get_common_server(self):
data = {
'public_address': None,
'private_address': None,
'service_net_name_or_ip': self.get_config_option(
'service_net_name_or_ip'),
'tenant_net_name_or_ip': self.get_config_option(
'tenant_net_name_or_ip'),
}
data['instance'] = self.compute_api.server_get_by_name_or_id(
self.admin_context,
self.get_config_option('service_instance_name_or_id'))
if netaddr.valid_ipv4(data['service_net_name_or_ip']):
data['private_address'] = [data['service_net_name_or_ip']]
else:
data['private_address'] = self._get_addresses_by_network_name(
data['service_net_name_or_ip'], data['instance'])
if netaddr.valid_ipv4(data['tenant_net_name_or_ip']):
data['public_address'] = [data['tenant_net_name_or_ip']]
else:
data['public_address'] = self._get_addresses_by_network_name(
data['tenant_net_name_or_ip'], data['instance'])
if not (data['public_address'] and data['private_address']):
raise exception.ManilaException(
"Can not find one of net addresses for service instance. "
"Instance: %(instance)s, "
"private_address: %(private_address)s, "
"public_address: %(public_address)s." % data)
share_server = {
'username': self.get_config_option('service_instance_user'),
'password': self.get_config_option('service_instance_password'),
'pk_path': self.path_to_private_key,
'ip': data['private_address'][0], # for handling
'public_address': data['public_address'][0], # for exports
'instance_id': data['instance']['id'],
}
return {'backend_details': share_server}
def _get_addresses_by_network_name(self, net_name, server):
net_ips = []
if 'networks' in server and net_name in server['networks']:
net_ips = server['networks'][net_name]
elif 'addresses' in server and net_name in server['addresses']:
net_ips = [addr['addr'] for addr in server['addresses'][net_name]]
return net_ips
@utils.synchronized("service_instance_get_service_network", external=True)
def _get_service_network(self):
@ -193,11 +288,7 @@ class ServiceInstanceManager(object):
def _get_server_ip(self, server):
"""Returns service vms ip address."""
net_name = self.get_config_option("service_network_name")
net_ips = []
if 'networks' in server and net_name in server['networks']:
net_ips = server['networks'][net_name]
elif 'addresses' in server and net_name in server['addresses']:
net_ips = [addr['addr'] for addr in server['addresses'][net_name]]
net_ips = self._get_addresses_by_network_name(net_name, server)
if not net_ips:
msg = _("Failed to get service instance ip address. "
"Service network name is '%(net_name)s' "
@ -234,7 +325,7 @@ class ServiceInstanceManager(object):
LOG.debug("Creating security group with name '%s'.", name)
sg = self.compute_api.security_group_create(
context, name, description)
for protocol, ports in constants.SERVICE_INSTANCE_SECGROUP_DATA:
for protocol, ports in const.SERVICE_INSTANCE_SECGROUP_DATA:
self.compute_api.security_group_rule_create(
context,
parent_group_id=sg.id,

View File

@ -14,6 +14,7 @@
import mock
from novaclient import exceptions as nova_exception
from novaclient import utils
from novaclient.v1_1 import servers as nova_servers
from manila.compute import nova
@ -87,7 +88,17 @@ class NovaApiTestCase(test.TestCase):
def test_server_get(self):
instance_id = 'instance_id1'
result = self.api.server_get(self.ctx, instance_id)
self.assertEqual(result['id'], instance_id)
self.assertEqual(instance_id, result['id'])
def test_server_get_by_name_or_id(self):
instance_id = 'instance_id1'
server = {'id': instance_id, 'fake_key': 'fake_value'}
self.stubs.Set(utils, 'find_resource', mock.Mock(return_value=server))
result = self.api.server_get_by_name_or_id(self.ctx, instance_id)
self.assertEqual(instance_id, result['id'])
utils.find_resource.assert_called_once_with(mock.ANY, instance_id)
def test_server_get_failed(self):
nova.novaclient.side_effect = nova_exception.NotFound(404)

View File

@ -89,6 +89,9 @@ class API(object):
def server_get(self, *args, **kwargs):
pass
def server_get_by_name_or_id(self, *args, **kwargs):
pass
def keypair_list(self, *args, **kwargs):
pass

View File

@ -1,4 +1,5 @@
# Copyright (c) 2014 NetApp, Inc.
# Copyright (c) 2015 Mirantis, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -624,6 +625,27 @@ class GenericShareDriverTestCase(test.TestCase):
self._helper_nfs.create_export.assert_called_once_with(
self.server['backend_details'], self.share['name'])
def test_delete_share_no_share_servers_handling(self):
self.stubs.Set(self._driver, '_deallocate_container', mock.Mock())
self.stubs.Set(
self._driver.service_instance_manager,
'get_common_server', mock.Mock(return_value=self.server))
self.stubs.Set(
self._driver.service_instance_manager,
'ensure_service_instance', mock.Mock(return_value=False))
CONF.set_default('driver_handles_share_servers', False)
self._driver.delete_share(self._context, self.share)
self._driver.service_instance_manager.get_common_server.\
assert_called_once_with()
self._driver._deallocate_container.assert_called_once_with(
self._driver.admin_context, self.share)
self._driver.service_instance_manager.ensure_service_instance.\
assert_called_once_with(
self._context, self.server['backend_details'])
def test_delete_share(self):
self.stubs.Set(self._driver, '_unmount_device', mock.Mock())
self.stubs.Set(self._driver, '_detach_volume', mock.Mock())
@ -641,6 +663,9 @@ class GenericShareDriverTestCase(test.TestCase):
self.server['backend_details'])
self._driver._deallocate_container.assert_called_once_with(
self._driver.admin_context, self.share)
self._driver.service_instance_manager.ensure_service_instance.\
assert_called_once_with(
self._context, self.server['backend_details'])
def test_delete_share_without_share_server(self):
self.stubs.Set(self._driver, '_unmount_device', mock.Mock())
@ -684,17 +709,20 @@ class GenericShareDriverTestCase(test.TestCase):
self.stubs.Set(self._driver, '_detach_volume', mock.Mock())
self.stubs.Set(self._driver, '_deallocate_container', mock.Mock())
with mock.patch.object(self._driver.service_instance_manager,
'ensure_service_instance',
mock.Mock(return_value=False)):
self._driver.delete_share(
self._context, self.share, share_server=self.server)
self.stubs.Set(
self._driver.service_instance_manager,
'ensure_service_instance', mock.Mock(return_value=False))
self._driver.delete_share(
self._context, self.share, share_server=self.server)
self.assertFalse(self._helper_nfs.remove_export.called)
self.assertFalse(self._driver._unmount_device.called)
self.assertFalse(self._driver._detach_volume.called)
self._driver._deallocate_container.assert_called_once_with(
self._driver.admin_context, self.share)
self.assertFalse(self._helper_nfs.remove_export.called)
self.assertFalse(self._driver._unmount_device.called)
self.assertFalse(self._driver._detach_volume.called)
self._driver._deallocate_container.assert_called_once_with(
self._driver.admin_context, self.share)
self._driver.service_instance_manager.ensure_service_instance.\
assert_called_once_with(
self._context, self.server['backend_details'])
def test_create_snapshot(self):
fake_vol = fake_volume.FakeVolume()
@ -787,7 +815,7 @@ class GenericShareDriverTestCase(test.TestCase):
self.assertRaises(exception.InvalidShare,
self._driver._get_helper, share)
def test_setup_network(self):
def test__setup_server(self):
sim = self._driver.instance_manager
net_info = {'server_id': 'fake',
'neutron_net_id': 'fake-net-id',
@ -799,7 +827,7 @@ class GenericShareDriverTestCase(test.TestCase):
'fake-net-id',
'fake-subnet-id')
def test_setup_network_revert(self):
def test__setup_server_revert(self):
def raise_exception(*args, **kwargs):
raise exception.ServiceInstanceException
@ -814,7 +842,7 @@ class GenericShareDriverTestCase(test.TestCase):
self._driver.setup_server,
net_info)
def test_teardown_network(self):
def test__teardown_server(self):
server_details = {
'instance_id': 'fake_instance_id',
'subnet_id': 'fake_subnet_id',
@ -929,6 +957,70 @@ class GenericShareDriverTestCase(test.TestCase):
self.assertEqual('Open Source', result['vendor_name'])
@generic.ensure_server
def fake(driver_instance, context, share_server=None):
return share_server
@ddt.ddt
class GenericDriverEnsureServerTestCase(test.TestCase):
def setUp(self):
super(GenericDriverEnsureServerTestCase, self).setUp()
self._context = context.get_admin_context()
self.server = {'id': 'fake_id', 'backend_details': {'foo': 'bar'}}
self.dhss_false = type(
'Fake', (object,), {'driver_handles_share_servers': False})
self.dhss_true = type(
'Fake', (object,), {'driver_handles_share_servers': True})
def test_share_servers_are_not_handled_server_not_provided(self):
self.dhss_false.service_instance_manager = mock.Mock()
self.dhss_false.service_instance_manager.get_common_server = (
mock.Mock(return_value=self.server))
self.dhss_false.service_instance_manager.ensure_service_instance = (
mock.Mock(return_value=True))
actual = fake(self.dhss_false, self._context)
self.assertEqual(self.server, actual)
self.dhss_false.service_instance_manager.\
get_common_server.assert_called_once_with()
self.dhss_false.service_instance_manager.ensure_service_instance.\
assert_called_once_with(
self._context, self.server['backend_details'])
@ddt.data({'id': 'without_details'},
{'id': 'with_details', 'backend_details': {'foo': 'bar'}})
def test_share_servers_are_not_handled_server_provided(self, server):
self.assertRaises(
exception.ManilaException,
fake, self.dhss_false, self._context, share_server=server)
def test_share_servers_are_handled_server_provided(self):
self.dhss_true.service_instance_manager = mock.Mock()
self.dhss_true.service_instance_manager.ensure_service_instance = (
mock.Mock(return_value=True))
actual = fake(self.dhss_true, self._context, share_server=self.server)
self.assertEqual(self.server, actual)
self.dhss_true.service_instance_manager.ensure_service_instance.\
assert_called_once_with(
self._context, self.server['backend_details'])
def test_share_servers_are_handled_invalid_server_provided(self):
server = {'id': 'without_details'}
self.assertRaises(
exception.ManilaException,
fake, self.dhss_true, self._context, share_server=server)
def test_share_servers_are_handled_server_not_provided(self):
self.assertRaises(
exception.ManilaException, fake, self.dhss_true, self._context)
class NFSHelperTestCase(test.TestCase):
"""Test case for NFS helper of generic driver."""

View File

@ -18,12 +18,15 @@
import copy
import os
import ddt
import mock
from oslo_config import cfg
from oslo_utils import importutils
import six
from manila import context
from manila import exception
from manila.share import configuration
from manila.share.drivers import service_instance
from manila import test
from manila.tests import fake_compute
@ -34,23 +37,60 @@ from manila import utils
CONF = cfg.CONF
def fake_get_config_option(key):
if key == 'driver_handles_share_servers':
return True
elif key == 'service_instance_password':
return None
elif key == 'service_instance_user':
return 'fake_user'
elif key == 'service_network_name':
return 'fake_service_network_name'
elif key == 'service_instance_flavor_id':
return 100
elif key == 'service_instance_name_template':
return 'fake_manila_service_instance_%s'
elif key == 'service_image_name':
return 'fake_service_image_name'
elif key == 'manila_service_keypair_name':
return 'fake_manila_service_keypair_name'
elif key == 'path_to_private_key':
return 'fake_path_to_private_key'
elif key == 'path_to_public_key':
return 'fake_path_to_public_key'
elif key == 'max_time_to_build_instance':
return 500
elif key == 'connect_share_server_to_tenant_network':
return False
elif key == 'service_network_cidr':
return '99.254.0.0/16'
elif key == 'service_network_division_mask':
return 25
else:
return mock.Mock()
@ddt.ddt
class ServiceInstanceManagerTestCase(test.TestCase):
"""Tests InstanceManager."""
def setUp(self):
super(ServiceInstanceManagerTestCase, self).setUp()
self._context = context.get_admin_context()
self.config = configuration.Configuration(None)
self.config.safe_get = mock.Mock(side_effect=fake_get_config_option)
self._helper_cifs = mock.Mock()
self._helper_nfs = mock.Mock()
self._db = mock.Mock()
self.stubs.Set(service_instance.neutron, 'API', fake_network.API)
self.stubs.Set(service_instance.compute, 'API', fake_compute.API)
self.stubs.Set(importutils, 'import_class', mock.Mock())
with mock.patch.object(service_instance.ServiceInstanceManager,
'_setup_connectivity_with_service_instances',
mock.Mock()):
self._manager = service_instance.ServiceInstanceManager(self._db,
{})
self._manager = service_instance.ServiceInstanceManager(
self._db, self.config)
self._manager.service_tenant_id = 'service tenant id'
self._manager.service_network_id = 'service network id'
self._manager.admin_context = self._context
@ -70,12 +110,12 @@ class ServiceInstanceManagerTestCase(test.TestCase):
def test_get_service_network_net_exists(self):
net1 = copy.copy(fake_network.API.network)
net2 = copy.copy(fake_network.API.network)
net1['name'] = CONF.service_network_name
net1['name'] = self._manager.get_config_option('service_network_name')
net1['id'] = 'fake service network id'
self.stubs.Set(self._manager.neutron_api, 'get_all_tenant_networks',
mock.Mock(return_value=[net1, net2]))
result = self._manager._get_service_network()
self.assertEqual(result, net1['id'])
self.assertEqual(net1['id'], result)
def test_get_service_network_net_does_not_exists(self):
net = fake_network.FakeNetwork()
@ -84,10 +124,11 @@ class ServiceInstanceManagerTestCase(test.TestCase):
self.stubs.Set(self._manager.neutron_api, 'network_create',
mock.Mock(return_value=net))
result = self._manager._get_service_network()
self.assertEqual(result, net['id'])
self.assertEqual(net['id'], result)
def test_get_service_network_ambiguos(self):
net = fake_network.FakeNetwork(name=CONF.service_network_name)
net = fake_network.FakeNetwork(
name=self._manager.get_config_option('service_network_name'))
self.stubs.Set(self._manager.neutron_api, 'get_all_tenant_networks',
mock.Mock(return_value=[net, net]))
self.assertRaises(exception.ManilaException,
@ -96,14 +137,14 @@ class ServiceInstanceManagerTestCase(test.TestCase):
def test_get_service_instance_name(self):
result = self._manager._get_service_instance_name(
'fake_share_network_id')
self.assertEqual(result, CONF.service_instance_name_template %
'fake_share_network_id')
self.assertEqual(
'fake_manila_service_instance_None_fake_share_network_id', result)
def test_get_server_ip_found_in_networks_section(self):
ip = '10.0.0.1'
fake_server = {
'networks': {
CONF.service_network_name: [ip],
self._manager.get_config_option('service_network_name'): [ip],
}
}
result = self._manager._get_server_ip(fake_server)
@ -113,7 +154,7 @@ class ServiceInstanceManagerTestCase(test.TestCase):
ip = '10.0.0.1'
fake_server = {
'addresses': {
CONF.service_network_name: [
self._manager.get_config_option('service_network_name'): [
{'addr': ip, 'version': 4, }
],
}
@ -311,8 +352,9 @@ class ServiceInstanceManagerTestCase(test.TestCase):
self.assertFalse(result)
def test_get_key_create_new(self):
fake_keypair = fake_compute.FakeKeypair(
name=CONF.manila_service_keypair_name)
keypair_name = self._manager.get_config_option(
'manila_service_keypair_name')
fake_keypair = fake_compute.FakeKeypair(name=keypair_name)
self.stubs.Set(self._manager.compute_api, 'keypair_list',
mock.Mock(return_value=[]))
self.stubs.Set(self._manager.compute_api, 'keypair_import',
@ -320,17 +362,20 @@ class ServiceInstanceManagerTestCase(test.TestCase):
result = self._manager._get_key(self._context)
self.assertEqual(result,
(fake_keypair.name,
os.path.expanduser(CONF.path_to_private_key)))
self.assertEqual(
(fake_keypair.name,
os.path.expanduser(self._manager.get_config_option(
'path_to_private_key'))),
result)
self._manager.compute_api.keypair_list.assert_called_once_with(
self._context)
self._manager.compute_api.keypair_import.assert_called_once_with(
self._context, 'manila-service', '')
self._context, keypair_name, '')
def test_get_key_exists(self):
fake_keypair = fake_compute.FakeKeypair(
name=CONF.manila_service_keypair_name,
name=self._manager.get_config_option(
'manila_service_keypair_name'),
public_key='fake_public_key')
self.stubs.Set(self._manager.compute_api, 'keypair_list',
mock.Mock(return_value=[fake_keypair]))
@ -344,13 +389,16 @@ class ServiceInstanceManagerTestCase(test.TestCase):
self._manager.compute_api.keypair_list.assert_called_once_with(
self._context)
self.assertFalse(self._manager.compute_api.keypair_import.called)
self.assertEqual(result,
(fake_keypair.name,
os.path.expanduser(CONF.path_to_private_key)))
self.assertEqual(
(fake_keypair.name,
os.path.expanduser(self._manager.get_config_option(
'path_to_private_key'))),
result)
def test_get_key_exists_recreate(self):
fake_keypair = fake_compute.FakeKeypair(
name=CONF.manila_service_keypair_name,
name=self._manager.get_config_option(
'manila_service_keypair_name'),
public_key='fake_public_key1')
self.stubs.Set(self._manager.compute_api, 'keypair_list',
mock.Mock(return_value=[fake_keypair]))
@ -369,9 +417,11 @@ class ServiceInstanceManagerTestCase(test.TestCase):
self._context, fake_keypair.id)
self._manager.compute_api.keypair_import.assert_called_once_with(
self._context, fake_keypair.name, 'fake_public_key2')
self.assertEqual(result,
(fake_keypair.name,
os.path.expanduser(CONF.path_to_private_key)))
self.assertEqual(
(fake_keypair.name,
os.path.expanduser(self._manager.get_config_option(
'path_to_private_key'))),
result)
def test_get_key_keypath_to_public_not_set(self):
self._manager.path_to_public_key = None
@ -414,14 +464,15 @@ class ServiceInstanceManagerTestCase(test.TestCase):
self.assertEqual(result, (None, None))
def test_get_service_image(self):
fake_image1 = fake_compute.FakeImage(name=CONF.service_image_name)
fake_image1 = fake_compute.FakeImage(
name=self._manager.get_config_option('service_image_name'))
fake_image2 = fake_compute.FakeImage(name='another-image')
self.stubs.Set(self._manager.compute_api, 'image_list',
mock.Mock(return_value=[fake_image1, fake_image2]))
result = self._manager._get_service_image(self._context)
self.assertEqual(result, fake_image1.id)
self.assertEqual(fake_image1.id, result)
def test_get_service_image_not_found(self):
self.stubs.Set(self._manager.compute_api, 'image_list',
@ -834,8 +885,9 @@ class ServiceInstanceManagerTestCase(test.TestCase):
def test_get_cidr_for_subnet(self):
serv_cidr = service_instance.netaddr.IPNetwork(
CONF.service_network_cidr)
fake_division_mask = CONF.service_network_division_mask
self._manager.get_config_option('service_network_cidr'))
fake_division_mask = self._manager.get_config_option(
'service_network_division_mask')
cidrs = serv_cidr.subnet(fake_division_mask)
cidr1 = six.text_type(next(cidrs))
cidr2 = six.text_type(next(cidrs))
@ -936,3 +988,79 @@ class ServiceInstanceManagerTestCase(test.TestCase):
self._manager.neutron_api.update_subnet.assert_has_calls([
mock.call(subnet_id, ''),
])
@ddt.data(
{'s': 'fake_net_s', 't': 'fake_net_t'},
{'s': 'fake_net_s', 't': '12.34.56.78'},
{'s': '98.76.54.123', 't': 'fake_net_t'},
{'s': '98.76.54.123', 't': '12.34.56.78'})
@ddt.unpack
def test_get_common_server_valid_cases(self, s, t):
self._get_common_server(s, t, True)
@ddt.data(
{'s': 'fake_net_s', 't': 'fake'},
{'s': 'fake', 't': 'fake_net_t'},
{'s': 'fake', 't': 'fake'},
{'s': '98.76.54.123', 't': '12.12.12.1212'},
{'s': '12.12.12.1212', 't': '12.34.56.78'},
{'s': '12.12.12.1212', 't': '12.12.12.1212'})
@ddt.unpack
def test_get_common_server_invalid_cases(self, s, t):
self._get_common_server(s, t, False)
def _get_common_server(self, s, t, is_valid=True):
fake_instance_id = 'fake_instance_id'
fake_user = 'fake_user'
fake_pass = 'fake_pass'
fake_net_s = 'fake_net_s'
fake_addr_s = '98.76.54.123'
fake_net_t = 'fake_net_t'
fake_addr_t = '12.34.56.78'
fake_server = {
'id': fake_instance_id,
'networks': {fake_net_s: [fake_addr_s], fake_net_t: [fake_addr_t]},
'addresses': {fake_net_s: {'addr': fake_addr_s},
fake_net_t: {'addr': fake_addr_t}},
}
expected = {
'backend_details': {
'username': fake_user,
'password': fake_pass,
'pk_path': self._manager.path_to_private_key,
'ip': fake_addr_s,
'public_address': fake_addr_t,
'instance_id': fake_instance_id,
}
}
def fake_get_config_option(attr):
if attr == 'service_net_name_or_ip':
return s
elif attr == 'tenant_net_name_or_ip':
return t
elif attr == 'service_instance_name_or_id':
return fake_instance_id
elif attr == 'service_instance_user':
return fake_user
elif attr == 'service_instance_password':
return fake_pass
else:
raise exception.ManilaException("Wrong test data provided.")
self.mock_object(
self._manager.compute_api, 'server_get_by_name_or_id',
mock.Mock(return_value=fake_server))
self.mock_object(
self._manager, 'get_config_option',
mock.Mock(side_effect=fake_get_config_option))
if is_valid:
actual = self._manager.get_common_server()
self.assertEqual(expected, actual)
else:
self.assertRaises(
exception.ManilaException,
self._manager.get_common_server)
self.assertTrue(
self._manager.compute_api.server_get_by_name_or_id.called)