Merge "NetApp: Refactor unit tests"
This commit is contained in:
commit
3a614935fe
@ -38,6 +38,12 @@ FLEXVOL = 'openstack-flexvol'
|
||||
NFS_FILE_PATH = 'nfsvol'
|
||||
PATH = '/vol/%s/%s' % (POOL_NAME, LUN_NAME)
|
||||
IMAGE_FILE_ID = 'img-cache-imgid'
|
||||
PROVIDER_LOCATION = 'fake_provider_location'
|
||||
NFS_HOST = 'nfs-host1'
|
||||
NFS_SHARE_PATH = '/export'
|
||||
NFS_EXPORT_1 = '%s:%s' % (NFS_HOST, NFS_SHARE_PATH)
|
||||
NFS_EXPORT_2 = 'nfs-host2:/export'
|
||||
MOUNT_POINT = '/mnt/nfs'
|
||||
LUN_METADATA = {
|
||||
'OsType': None,
|
||||
'SpaceReserved': 'true',
|
||||
@ -56,10 +62,74 @@ NFS_VOLUME = {
|
||||
'size': SIZE,
|
||||
'id': VOLUME_ID,
|
||||
'host': NFS_HOST_STRING,
|
||||
'provider_location': PROVIDER_LOCATION,
|
||||
}
|
||||
|
||||
FAKE_MANAGE_VOLUME = {
|
||||
'name': 'volume-new-managed-123',
|
||||
'id': 'volume-new-managed-123',
|
||||
}
|
||||
|
||||
FAKE_IMAGE_LOCATION = (
|
||||
None,
|
||||
[
|
||||
# valid metadata
|
||||
{
|
||||
'metadata': {
|
||||
'share_location': 'nfs://host/path',
|
||||
'mountpoint': '/opt/stack/data/glance',
|
||||
'id': 'abc-123',
|
||||
'type': 'nfs'
|
||||
},
|
||||
'url': 'file:///opt/stack/data/glance/image-id-0'
|
||||
},
|
||||
# missing metadata
|
||||
{
|
||||
'metadata': {},
|
||||
'url': 'file:///opt/stack/data/glance/image-id-1'
|
||||
},
|
||||
# missing location_type
|
||||
{
|
||||
'metadata': {'location_type': None},
|
||||
'url': 'file:///opt/stack/data/glance/image-id-2'
|
||||
},
|
||||
# non-nfs location_type
|
||||
{
|
||||
'metadata': {'location_type': 'not-NFS'},
|
||||
'url': 'file:///opt/stack/data/glance/image-id-3'
|
||||
},
|
||||
# missing share_location
|
||||
{
|
||||
'metadata': {'location_type': 'nfs', 'share_location': None},
|
||||
'url': 'file:///opt/stack/data/glance/image-id-4'},
|
||||
# missing mountpoint
|
||||
{
|
||||
'metadata': {
|
||||
'location_type': 'nfs',
|
||||
'share_location': 'nfs://host/path',
|
||||
# Pre-kilo we documented "mount_point"
|
||||
'mount_point': '/opt/stack/data/glance'
|
||||
},
|
||||
'url': 'file:///opt/stack/data/glance/image-id-5'
|
||||
},
|
||||
# Valid metadata
|
||||
{
|
||||
'metadata':
|
||||
{
|
||||
'share_location': 'nfs://host/path',
|
||||
'mountpoint': '/opt/stack/data/glance',
|
||||
'id': 'abc-123',
|
||||
'type': 'nfs',
|
||||
},
|
||||
'url': 'file:///opt/stack/data/glance/image-id-6'
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
NETAPP_VOLUME = 'fake_netapp_volume'
|
||||
|
||||
VFILER = 'fake_netapp_vfiler'
|
||||
|
||||
UUID1 = '12345678-1234-5678-1234-567812345678'
|
||||
LUN_PATH = '/vol/vol0/%s' % LUN_NAME
|
||||
|
||||
@ -211,14 +281,18 @@ CLONE_DESTINATION = {
|
||||
'id': CLONE_DESTINATION_ID,
|
||||
}
|
||||
|
||||
VOLUME_NAME = 'volume-fake_volume_id'
|
||||
MOUNT_PATH = '168.10.16.11:/' + VOLUME_ID
|
||||
SNAPSHOT_NAME = 'fake_snapshot_name'
|
||||
SNAPSHOT_LUN_HANDLE = 'fake_snapshot_lun_handle'
|
||||
SNAPSHOT_MOUNT = '/fake/mount/path'
|
||||
|
||||
SNAPSHOT = {
|
||||
'name': SNAPSHOT_NAME,
|
||||
'volume_name': 'volume-fake_volume_id',
|
||||
'volume_size': SIZE,
|
||||
'volume_id': 'fake_volume_id',
|
||||
'volume_id': VOLUME_ID,
|
||||
'volume_name': VOLUME_NAME,
|
||||
'busy': False,
|
||||
}
|
||||
|
||||
@ -407,9 +481,30 @@ class test_snapshot(object):
|
||||
def __getitem__(self, key):
|
||||
return getattr(self, key)
|
||||
|
||||
PROVIDER_LOCATION = 'fake_provider_location'
|
||||
test_snapshot = test_snapshot()
|
||||
test_snapshot.id = 'fake_snap_id'
|
||||
test_snapshot.name = 'snapshot-%s' % test_snapshot.id
|
||||
test_snapshot.volume_id = 'fake_volume_id'
|
||||
test_snapshot.provider_location = PROVIDER_LOCATION
|
||||
|
||||
|
||||
def get_fake_net_interface_get_iter_response():
|
||||
return etree.XML("""<results status="passed">
|
||||
<num-records>1</num-records>
|
||||
<attributes-list>
|
||||
<net-interface-info></net-interface-info>
|
||||
<address>FAKE_IP</address>
|
||||
</attributes-list>
|
||||
</results>""")
|
||||
|
||||
|
||||
def get_fake_ifs():
|
||||
list_of_ifs = [
|
||||
etree.XML("""<net-interface-info>
|
||||
<address>FAKE_IP</address></net-interface-info>"""),
|
||||
etree.XML("""<net-interface-info>
|
||||
<address>FAKE_IP2</address></net-interface-info>"""),
|
||||
etree.XML("""<net-interface-info>
|
||||
<address>FAKE_IP3</address></net-interface-info>"""),
|
||||
]
|
||||
return [netapp_api.NaElement(el) for el in list_of_ifs]
|
||||
|
@ -24,6 +24,8 @@ import ddt
|
||||
from lxml import etree
|
||||
import mock
|
||||
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from cinder import exception
|
||||
from cinder import test
|
||||
import cinder.tests.unit.volume.drivers.netapp.dataontap.client.fakes \
|
||||
@ -127,11 +129,25 @@ class NetAppBlockStorage7modeLibraryTestCase(test.TestCase):
|
||||
self.assertRaises(exception.NetAppDriverException,
|
||||
self.library.check_for_setup_error)
|
||||
|
||||
def test_check_for_setup_error_too_old(self):
|
||||
self.zapi_client.get_ontapi_version.return_value = (1, 8)
|
||||
@ddt.data(None, (1, 8))
|
||||
def test_check_for_setup_error_unsupported_or_no_version(self, version):
|
||||
self.zapi_client.get_ontapi_version.return_value = version
|
||||
self.assertRaises(exception.VolumeBackendAPIException,
|
||||
self.library.check_for_setup_error)
|
||||
|
||||
@ddt.data(None, fake.VFILER)
|
||||
def test__get_owner(self, vfiler):
|
||||
self.library.configuration.netapp_server_hostname = 'openstack'
|
||||
self.library.vfiler = vfiler
|
||||
expected_owner = 'openstack'
|
||||
|
||||
retval = self.library._get_owner()
|
||||
|
||||
if vfiler:
|
||||
expected_owner += ':' + vfiler
|
||||
|
||||
self.assertEqual(expected_owner, retval)
|
||||
|
||||
def test_find_mapped_lun_igroup(self):
|
||||
response = netapp_api.NaElement(etree.XML("""
|
||||
<results status="passed">
|
||||
@ -635,6 +651,78 @@ class NetAppBlockStorage7modeLibraryTestCase(test.TestCase):
|
||||
|
||||
self.assertListEqual([], pools)
|
||||
|
||||
@ddt.data((None, False, False),
|
||||
(30, True, False),
|
||||
(30, False, True))
|
||||
@ddt.unpack
|
||||
def test__refresh_volume_info_already_running(self,
|
||||
vol_refresh_time,
|
||||
vol_refresh_voluntary,
|
||||
is_newer):
|
||||
mock_warning_log = self.mock_object(block_7mode.LOG, 'warning')
|
||||
self.library.vol_refresh_time = vol_refresh_time
|
||||
self.library.vol_refresh_voluntary = vol_refresh_voluntary
|
||||
self.library.vol_refresh_interval = 30
|
||||
self.mock_object(timeutils, 'is_newer_than', mock.Mock(
|
||||
return_value=is_newer))
|
||||
self.mock_object(na_utils, 'set_safe_attr', mock.Mock(
|
||||
return_value=False))
|
||||
|
||||
retval = self.library._refresh_volume_info()
|
||||
|
||||
self.assertIsNone(retval)
|
||||
# Assert no values are unset by the method
|
||||
self.assertEqual(vol_refresh_voluntary,
|
||||
self.library.vol_refresh_voluntary)
|
||||
self.assertEqual(vol_refresh_time, self.library.vol_refresh_time)
|
||||
if timeutils.is_newer_than.called:
|
||||
timeutils.is_newer_than.assert_called_once_with(
|
||||
vol_refresh_time, self.library.vol_refresh_interval)
|
||||
na_utils.set_safe_attr.assert_has_calls([
|
||||
mock.call(self.library, 'vol_refresh_running', True),
|
||||
mock.call(self.library, 'vol_refresh_running', False)])
|
||||
self.assertEqual(1, mock_warning_log.call_count)
|
||||
|
||||
def test__refresh_volume_info(self):
|
||||
mock_warning_log = self.mock_object(block_7mode.LOG, 'warning')
|
||||
self.library.vol_refresh_time = None
|
||||
self.library.vol_refresh_voluntary = True
|
||||
self.mock_object(timeutils, 'is_newer_than')
|
||||
self.mock_object(self.library.zapi_client, 'get_filer_volumes')
|
||||
self.mock_object(self.library, '_get_filtered_pools', mock.Mock(
|
||||
return_value=['vol1', 'vol2']))
|
||||
self.mock_object(na_utils, 'set_safe_attr', mock.Mock(
|
||||
return_value=True))
|
||||
|
||||
retval = self.library._refresh_volume_info()
|
||||
|
||||
self.assertIsNone(retval)
|
||||
self.assertEqual(False, self.library.vol_refresh_voluntary)
|
||||
self.assertEqual(['vol1', 'vol2'], self.library.volume_list)
|
||||
self.assertIsNotNone(self.library.vol_refresh_time)
|
||||
na_utils.set_safe_attr.assert_has_calls([
|
||||
mock.call(self.library, 'vol_refresh_running', True),
|
||||
mock.call(self.library, 'vol_refresh_running', False)])
|
||||
self.assertFalse(mock_warning_log.called)
|
||||
|
||||
def test__refresh_volume_info_exception(self):
|
||||
mock_warning_log = self.mock_object(block_7mode.LOG, 'warning')
|
||||
self.library.vol_refresh_time = None
|
||||
self.library.vol_refresh_voluntary = True
|
||||
self.mock_object(timeutils, 'is_newer_than')
|
||||
self.mock_object(na_utils, 'set_safe_attr', mock.Mock(
|
||||
return_value=True))
|
||||
self.mock_object(
|
||||
self.library.zapi_client, 'get_filer_volumes',
|
||||
mock.Mock(side_effect=exception.NetAppDriverException))
|
||||
self.mock_object(self.library, '_get_filtered_pools')
|
||||
|
||||
retval = self.library._refresh_volume_info()
|
||||
|
||||
self.assertIsNone(retval)
|
||||
self.assertFalse(self.library._get_filtered_pools.called)
|
||||
self.assertEqual(1, mock_warning_log.call_count)
|
||||
|
||||
def test_delete_volume(self):
|
||||
self.library.vol_refresh_voluntary = False
|
||||
mock_super_delete_volume = self.mock_object(
|
||||
|
@ -16,23 +16,30 @@
|
||||
"""
|
||||
Unit tests for the NetApp NFS storage driver
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
import copy
|
||||
import os
|
||||
import threading
|
||||
import time
|
||||
|
||||
import ddt
|
||||
import mock
|
||||
from os_brick.remotefs import remotefs as remotefs_brick
|
||||
from oslo_concurrency import processutils
|
||||
from oslo_utils import units
|
||||
import shutil
|
||||
|
||||
from cinder import context
|
||||
from cinder import exception
|
||||
from cinder import test
|
||||
from cinder.tests.unit import fake_snapshot
|
||||
from cinder.tests.unit import fake_volume
|
||||
from cinder.tests.unit.volume.drivers.netapp.dataontap import fakes as fake
|
||||
from cinder import utils
|
||||
from cinder.volume.drivers.netapp.dataontap.client import api as netapp_api
|
||||
from cinder.volume.drivers.netapp.dataontap import nfs_base
|
||||
from cinder.volume.drivers.netapp import utils as na_utils
|
||||
from cinder.volume.drivers import nfs
|
||||
from cinder.volume.drivers import remotefs
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@ -44,6 +51,10 @@ class NetAppNfsDriverTestCase(test.TestCase):
|
||||
configuration.nfs_mount_point_base = '/mnt/test'
|
||||
configuration.reserved_percentage = 0
|
||||
configuration.max_over_subscription_ratio = 1.1
|
||||
self.fake_nfs_export_1 = fake.NFS_EXPORT_1
|
||||
self.fake_nfs_export_2 = fake.NFS_EXPORT_2
|
||||
self.fake_mount_point = fake.MOUNT_POINT
|
||||
self.ctxt = context.RequestContext('fake', 'fake', auth_token=True)
|
||||
|
||||
kwargs = {'configuration': configuration}
|
||||
|
||||
@ -105,6 +116,11 @@ class NetAppNfsDriverTestCase(test.TestCase):
|
||||
get_capacity.assert_has_calls([
|
||||
mock.call(flexvol_path=fake.EXPORT_PATH)])
|
||||
|
||||
def test_get_pool(self):
|
||||
pool = self.driver.get_pool({'provider_location': 'fake-share'})
|
||||
|
||||
self.assertEqual('fake-share', pool)
|
||||
|
||||
def test_create_volume(self):
|
||||
self.mock_object(self.driver, '_ensure_shares_mounted')
|
||||
self.mock_object(na_utils, 'get_volume_extra_specs')
|
||||
@ -135,17 +151,6 @@ class NetAppNfsDriverTestCase(test.TestCase):
|
||||
self.driver.create_volume,
|
||||
fake.NFS_VOLUME)
|
||||
|
||||
def test_create_volume_from_snapshot(self):
|
||||
provider_location = fake.POOL_NAME
|
||||
snapshot = fake.CLONE_SOURCE
|
||||
self.mock_object(self.driver, '_clone_source_to_destination_volume',
|
||||
mock.Mock(return_value=provider_location))
|
||||
|
||||
result = self.driver.create_cloned_volume(fake.NFS_VOLUME,
|
||||
snapshot)
|
||||
|
||||
self.assertEqual(provider_location, result)
|
||||
|
||||
def test_clone_source_to_destination_volume(self):
|
||||
self.mock_object(self.driver, '_get_volume_location', mock.Mock(
|
||||
return_value=fake.POOL_NAME))
|
||||
@ -243,6 +248,22 @@ class NetAppNfsDriverTestCase(test.TestCase):
|
||||
fake.CLONE_SOURCE,
|
||||
fake.NFS_VOLUME)
|
||||
|
||||
def test_create_volume_from_snapshot(self):
|
||||
volume = fake.VOLUME
|
||||
expected_source = {
|
||||
'name': fake.SNAPSHOT_NAME,
|
||||
'size': fake.SIZE,
|
||||
'id': fake.VOLUME_ID,
|
||||
}
|
||||
mock_clone_call = self.mock_object(
|
||||
self.driver, '_clone_source_to_destination_volume',
|
||||
mock.Mock(return_value='fake'))
|
||||
|
||||
retval = self.driver.create_volume_from_snapshot(volume, fake.SNAPSHOT)
|
||||
|
||||
self.assertEqual('fake', retval)
|
||||
mock_clone_call.assert_called_once_with(expected_source, volume)
|
||||
|
||||
def test_create_cloned_volume(self):
|
||||
provider_location = fake.POOL_NAME
|
||||
src_vref = fake.CLONE_SOURCE
|
||||
@ -270,6 +291,188 @@ class NetAppNfsDriverTestCase(test.TestCase):
|
||||
fake.SNAPSHOT['volume_name'], fake.SNAPSHOT['name'],
|
||||
fake.SNAPSHOT['volume_id'], is_snapshot=True)
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_delete_snapshot(self, volume_present):
|
||||
updates = {
|
||||
'name': fake.SNAPSHOT_NAME,
|
||||
'volume_size': fake.SIZE,
|
||||
'volume_id': fake.VOLUME_ID,
|
||||
'volume_name': fake.VOLUME_NAME,
|
||||
'busy': False,
|
||||
}
|
||||
snapshot = fake_snapshot.fake_snapshot_obj(self.ctxt, **updates)
|
||||
self.mock_object(self.driver, '_get_provider_location',
|
||||
mock.Mock(return_value=fake.SNAPSHOT_MOUNT))
|
||||
self.mock_object(self.driver, '_volume_not_present',
|
||||
mock.Mock(return_value=volume_present))
|
||||
self.mock_object(self.driver, '_execute')
|
||||
self.mock_object(self.driver, '_get_volume_path',
|
||||
mock.Mock(return_value='fake'))
|
||||
self.driver._execute_as_root = True
|
||||
|
||||
retval = self.driver.delete_snapshot(snapshot)
|
||||
|
||||
if volume_present:
|
||||
self.assertTrue(retval)
|
||||
self.driver._execute.assert_not_called()
|
||||
else:
|
||||
self.assertIsNone(retval)
|
||||
self.driver._execute.assert_called_once_with(
|
||||
'rm', 'fake', run_as_root=True)
|
||||
|
||||
def test__get_volume_location(self):
|
||||
volume_id = fake.VOLUME_ID
|
||||
self.mock_object(self.driver, '_get_host_ip',
|
||||
mock.Mock(return_value='168.124.10.12'))
|
||||
self.mock_object(self.driver, '_get_export_path',
|
||||
mock.Mock(return_value='/fake_mount_path'))
|
||||
|
||||
retval = self.driver._get_volume_location(volume_id)
|
||||
|
||||
self.assertEqual('168.124.10.12:/fake_mount_path', retval)
|
||||
self.driver._get_host_ip.assert_called_once_with(volume_id)
|
||||
self.driver._get_export_path.assert_called_once_with(volume_id)
|
||||
|
||||
def test__clone_backing_file_for_volume(self):
|
||||
self.assertRaises(NotImplementedError,
|
||||
self.driver._clone_backing_file_for_volume,
|
||||
fake.VOLUME_NAME, fake.CLONE_SOURCE_NAME,
|
||||
fake.VOLUME_ID, share=None)
|
||||
|
||||
def test__get_provider_location(self):
|
||||
updates = {'provider_location': fake.PROVIDER_LOCATION}
|
||||
volume = fake_volume.fake_volume_obj(self.ctxt, **updates)
|
||||
self.mock_object(self.driver.db, 'volume_get', mock.Mock(
|
||||
return_value=volume))
|
||||
|
||||
retval = self.driver._get_provider_location(fake.VOLUME_ID)
|
||||
|
||||
self.assertEqual(fake.PROVIDER_LOCATION, retval)
|
||||
|
||||
@ddt.data(None, processutils.ProcessExecutionError)
|
||||
def test__volume_not_present(self, side_effect):
|
||||
self.mock_object(self.driver, '_get_volume_path')
|
||||
self.mock_object(self.driver, '_try_execute',
|
||||
mock.Mock(side_effect=side_effect))
|
||||
|
||||
retval = self.driver._volume_not_present(
|
||||
fake.MOUNT_PATH, fake.VOLUME_NAME)
|
||||
|
||||
self.assertEqual(side_effect is not None, retval)
|
||||
|
||||
@mock.patch.object(time, 'sleep')
|
||||
def test__try_execute_exception(self, patched_sleep):
|
||||
self.mock_object(self.driver, '_execute', mock.Mock(
|
||||
side_effect=processutils.ProcessExecutionError))
|
||||
mock_exception_log = self.mock_object(nfs_base.LOG, 'exception')
|
||||
self.driver.configuration.num_shell_tries = 3
|
||||
|
||||
self.assertRaises(processutils.ProcessExecutionError,
|
||||
self.driver._try_execute,
|
||||
'fake-command', attr1='val1', attr2='val2')
|
||||
self.assertEqual(2, mock_exception_log.call_count)
|
||||
self.driver._execute.assert_has_calls([
|
||||
mock.call('fake-command', attr1='val1', attr2='val2'),
|
||||
mock.call('fake-command', attr1='val1', attr2='val2'),
|
||||
mock.call('fake-command', attr1='val1', attr2='val2')])
|
||||
self.assertEqual(2, time.sleep.call_count)
|
||||
patched_sleep.assert_has_calls([mock.call(1), mock.call(4)])
|
||||
|
||||
def test__update_volume_stats(self):
|
||||
self.assertRaises(NotImplementedError,
|
||||
self.driver._update_volume_stats)
|
||||
|
||||
def test_copy_image_to_volume_base_exception(self):
|
||||
updates = {
|
||||
'name': fake.VOLUME_NAME,
|
||||
'id': fake.VOLUME_ID,
|
||||
'provider_location': fake.PROVIDER_LOCATION,
|
||||
}
|
||||
mock_info_log = self.mock_object(nfs_base.LOG, 'info')
|
||||
fake_vol = fake_volume.fake_volume_obj(self.ctxt, **updates)
|
||||
self.mock_object(remotefs.RemoteFSDriver, 'copy_image_to_volume',
|
||||
mock.Mock(side_effect=exception.NfsException))
|
||||
|
||||
self.assertRaises(exception.NfsException,
|
||||
self.driver.copy_image_to_volume,
|
||||
'fake_context', fake_vol,
|
||||
'fake_img_service', fake.IMAGE_FILE_ID)
|
||||
mock_info_log.assert_not_called()
|
||||
|
||||
@ddt.data(None, Exception)
|
||||
def test_copy_image_to_volume(self, exc):
|
||||
mock_log = self.mock_object(nfs_base, 'LOG')
|
||||
self.mock_object(remotefs.RemoteFSDriver, 'copy_image_to_volume')
|
||||
self.mock_object(self.driver, '_do_clone_rel_img_cache',
|
||||
mock.Mock(side_effect=exc))
|
||||
|
||||
retval = self.driver.copy_image_to_volume(
|
||||
'fake_context', fake.NFS_VOLUME, 'fake_img_service',
|
||||
fake.IMAGE_FILE_ID)
|
||||
|
||||
self.assertIsNone(retval)
|
||||
self.assertEqual(exc is not None, mock_log.warning.called)
|
||||
self.assertEqual(2, mock_log.info.call_count)
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_do_clone_rel_img_cache(self, path_exists):
|
||||
self.mock_object(nfs_base.LOG, 'info')
|
||||
self.mock_object(utils, 'synchronized',
|
||||
mock.Mock(return_value=lambda f: f))
|
||||
self.mock_object(self.driver, '_get_mount_point_for_share',
|
||||
mock.Mock(return_value='dir'))
|
||||
self.mock_object(os.path, 'exists',
|
||||
mock.Mock(return_value=path_exists))
|
||||
self.mock_object(self.driver, '_clone_backing_file_for_volume')
|
||||
|
||||
retval = self.driver._do_clone_rel_img_cache(
|
||||
fake.CLONE_SOURCE_NAME, fake.CLONE_DESTINATION_NAME,
|
||||
fake.NFS_SHARE, 'fake_cache_file')
|
||||
|
||||
self.assertIsNone(retval)
|
||||
self.assertTrue(self.driver._get_mount_point_for_share.called)
|
||||
if not path_exists:
|
||||
self.driver._clone_backing_file_for_volume.assert_called_once_with(
|
||||
fake.CLONE_SOURCE_NAME, fake.CLONE_DESTINATION_NAME,
|
||||
share=fake.NFS_SHARE, volume_id=None)
|
||||
else:
|
||||
self.driver._clone_backing_file_for_volume.assert_not_called()
|
||||
os.path.exists.assert_called_once_with(
|
||||
'dir/' + fake.CLONE_DESTINATION_NAME)
|
||||
|
||||
def test__spawn_clean_cache_job_clean_job_setup(self):
|
||||
self.driver.cleaning = True
|
||||
mock_debug_log = self.mock_object(nfs_base.LOG, 'debug')
|
||||
self.mock_object(utils, 'synchronized',
|
||||
mock.Mock(return_value=lambda f: f))
|
||||
|
||||
retval = self.driver._spawn_clean_cache_job()
|
||||
|
||||
self.assertIsNone(retval)
|
||||
self.assertEqual(1, mock_debug_log.call_count)
|
||||
|
||||
def test__spawn_clean_cache_job_new_clean_job(self):
|
||||
|
||||
class FakeTimer(object):
|
||||
def start(self):
|
||||
pass
|
||||
|
||||
fake_timer = FakeTimer()
|
||||
self.mock_object(utils, 'synchronized',
|
||||
mock.Mock(return_value=lambda f: f))
|
||||
self.mock_object(fake_timer, 'start')
|
||||
self.mock_object(nfs_base.LOG, 'debug')
|
||||
self.mock_object(self.driver, '_clean_image_cache')
|
||||
self.mock_object(threading, 'Timer',
|
||||
mock.Mock(return_value=fake_timer))
|
||||
|
||||
retval = self.driver._spawn_clean_cache_job()
|
||||
|
||||
self.assertIsNone(retval)
|
||||
threading.Timer.assert_called_once_with(
|
||||
0, self.driver._clean_image_cache)
|
||||
fake_timer.start.assert_called_once_with()
|
||||
|
||||
def test_cleanup_volume_on_failure(self):
|
||||
path = '%s/%s' % (fake.NFS_SHARE, fake.NFS_VOLUME['name'])
|
||||
mock_local_path = self.mock_object(self.driver, 'local_path')
|
||||
@ -352,6 +555,22 @@ class NetAppNfsDriverTestCase(test.TestCase):
|
||||
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
def test_construct_image_url_loc(self):
|
||||
img_loc = fake.FAKE_IMAGE_LOCATION
|
||||
|
||||
locations = self.driver._construct_image_nfs_url(img_loc)
|
||||
|
||||
self.assertIn("nfs://host/path/image-id-0", locations)
|
||||
self.assertIn("nfs://host/path/image-id-6", locations)
|
||||
self.assertEqual(2, len(locations))
|
||||
|
||||
def test_construct_image_url_direct(self):
|
||||
img_loc = ("nfs://host/path/image-id", None)
|
||||
|
||||
locations = self.driver._construct_image_nfs_url(img_loc)
|
||||
|
||||
self.assertIn("nfs://host/path/image-id", locations)
|
||||
|
||||
def test_extend_volume(self):
|
||||
|
||||
new_size = 100
|
||||
@ -499,3 +718,185 @@ class NetAppNfsDriverTestCase(test.TestCase):
|
||||
size,
|
||||
thin=thin)
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
def test_get_share_mount_and_vol_from_vol_ref(self):
|
||||
self.mock_object(na_utils, 'resolve_hostname',
|
||||
mock.Mock(return_value='10.12.142.11'))
|
||||
self.mock_object(os.path, 'isfile', mock.Mock(return_value=True))
|
||||
self.driver._mounted_shares = [self.fake_nfs_export_1]
|
||||
vol_path = "%s/%s" % (self.fake_nfs_export_1, 'test_file_name')
|
||||
vol_ref = {'source-name': vol_path}
|
||||
self.driver._ensure_shares_mounted = mock.Mock()
|
||||
self.driver._get_mount_point_for_share = mock.Mock(
|
||||
return_value=self.fake_mount_point)
|
||||
|
||||
(share, mount, file_path) = (
|
||||
self.driver._get_share_mount_and_vol_from_vol_ref(vol_ref))
|
||||
|
||||
self.assertEqual(self.fake_nfs_export_1, share)
|
||||
self.assertEqual(self.fake_mount_point, mount)
|
||||
self.assertEqual('test_file_name', file_path)
|
||||
|
||||
def test_get_share_mount_and_vol_from_vol_ref_with_bad_ref(self):
|
||||
self.mock_object(na_utils, 'resolve_hostname',
|
||||
mock.Mock(return_value='10.12.142.11'))
|
||||
self.driver._mounted_shares = [self.fake_nfs_export_1]
|
||||
vol_ref = {'source-id': '1234546'}
|
||||
|
||||
self.driver._ensure_shares_mounted = mock.Mock()
|
||||
self.driver._get_mount_point_for_share = mock.Mock(
|
||||
return_value=self.fake_mount_point)
|
||||
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver._get_share_mount_and_vol_from_vol_ref,
|
||||
vol_ref)
|
||||
|
||||
def test_get_share_mount_and_vol_from_vol_ref_where_not_found(self):
|
||||
self.mock_object(na_utils, 'resolve_hostname',
|
||||
mock.Mock(return_value='10.12.142.11'))
|
||||
self.driver._mounted_shares = [self.fake_nfs_export_1]
|
||||
vol_path = "%s/%s" % (self.fake_nfs_export_2, 'test_file_name')
|
||||
vol_ref = {'source-name': vol_path}
|
||||
|
||||
self.driver._ensure_shares_mounted = mock.Mock()
|
||||
self.driver._get_mount_point_for_share = mock.Mock(
|
||||
return_value=self.fake_mount_point)
|
||||
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver._get_share_mount_and_vol_from_vol_ref,
|
||||
vol_ref)
|
||||
|
||||
def test_get_share_mount_and_vol_from_vol_ref_where_is_dir(self):
|
||||
self.mock_object(na_utils, 'resolve_hostname',
|
||||
mock.Mock(return_value='10.12.142.11'))
|
||||
self.driver._mounted_shares = [self.fake_nfs_export_1]
|
||||
vol_ref = {'source-name': self.fake_nfs_export_2}
|
||||
|
||||
self.driver._ensure_shares_mounted = mock.Mock()
|
||||
self.driver._get_mount_point_for_share = mock.Mock(
|
||||
return_value=self.fake_mount_point)
|
||||
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver._get_share_mount_and_vol_from_vol_ref,
|
||||
vol_ref)
|
||||
|
||||
def test_manage_existing(self):
|
||||
self.mock_object(utils, 'get_file_size',
|
||||
mock.Mock(return_value=1074253824))
|
||||
self.driver._mounted_shares = [self.fake_nfs_export_1]
|
||||
test_file = 'test_file_name'
|
||||
volume = fake.FAKE_MANAGE_VOLUME
|
||||
vol_path = "%s/%s" % (self.fake_nfs_export_1, test_file)
|
||||
vol_ref = {'source-name': vol_path}
|
||||
self.driver._check_volume_type = mock.Mock()
|
||||
shutil.move = mock.Mock()
|
||||
self.stubs.Set(self.driver, '_execute', mock.Mock())
|
||||
self.driver._ensure_shares_mounted = mock.Mock()
|
||||
self.driver._get_mount_point_for_share = mock.Mock(
|
||||
return_value=self.fake_mount_point)
|
||||
self.driver._get_share_mount_and_vol_from_vol_ref = mock.Mock(
|
||||
return_value=(self.fake_nfs_export_1, self.fake_mount_point,
|
||||
test_file))
|
||||
mock_get_specs = self.mock_object(na_utils, 'get_volume_extra_specs')
|
||||
mock_get_specs.return_value = {}
|
||||
self.mock_object(self.driver, '_do_qos_for_volume')
|
||||
|
||||
location = self.driver.manage_existing(volume, vol_ref)
|
||||
|
||||
self.assertEqual(self.fake_nfs_export_1, location['provider_location'])
|
||||
self.driver._check_volume_type.assert_called_once_with(
|
||||
volume, self.fake_nfs_export_1, test_file, {})
|
||||
|
||||
def test_manage_existing_move_fails(self):
|
||||
self.mock_object(utils, 'get_file_size',
|
||||
mock.Mock(return_value=1074253824))
|
||||
self.driver._mounted_shares = [self.fake_nfs_export_1]
|
||||
test_file = 'test_file_name'
|
||||
volume = fake.FAKE_MANAGE_VOLUME
|
||||
vol_path = "%s/%s" % (self.fake_nfs_export_1, test_file)
|
||||
vol_ref = {'source-name': vol_path}
|
||||
mock_check_volume_type = self.driver._check_volume_type = mock.Mock()
|
||||
self.driver._ensure_shares_mounted = mock.Mock()
|
||||
self.driver._get_mount_point_for_share = mock.Mock(
|
||||
return_value=self.fake_mount_point)
|
||||
self.driver._get_share_mount_and_vol_from_vol_ref = mock.Mock(
|
||||
return_value=(self.fake_nfs_export_1, self.fake_mount_point,
|
||||
test_file))
|
||||
self.driver._execute = mock.Mock(side_effect=OSError)
|
||||
mock_get_specs = self.mock_object(na_utils, 'get_volume_extra_specs')
|
||||
mock_get_specs.return_value = {}
|
||||
self.mock_object(self.driver, '_do_qos_for_volume')
|
||||
|
||||
self.assertRaises(exception.VolumeBackendAPIException,
|
||||
self.driver.manage_existing, volume, vol_ref)
|
||||
|
||||
mock_check_volume_type.assert_called_once_with(
|
||||
volume, self.fake_nfs_export_1, test_file, {})
|
||||
|
||||
def test_unmanage(self):
|
||||
mock_log = self.mock_object(nfs_base, 'LOG')
|
||||
volume = {'id': '123', 'provider_location': '/share'}
|
||||
|
||||
retval = self.driver.unmanage(volume)
|
||||
|
||||
self.assertIsNone(retval)
|
||||
self.assertEqual(1, mock_log.info.call_count)
|
||||
|
||||
def test_manage_existing_get_size(self):
|
||||
test_file = 'test_file_name'
|
||||
self.driver._get_share_mount_and_vol_from_vol_ref = mock.Mock(
|
||||
return_value=(self.fake_nfs_export_1, self.fake_mount_point,
|
||||
test_file))
|
||||
self.mock_object(utils, 'get_file_size',
|
||||
mock.Mock(return_value=1073741824))
|
||||
self.driver._mounted_shares = [self.fake_nfs_export_1]
|
||||
volume = fake.FAKE_MANAGE_VOLUME
|
||||
vol_path = "%s/%s" % (self.fake_nfs_export_1, test_file)
|
||||
vol_ref = {'source-name': vol_path}
|
||||
|
||||
self.driver._ensure_shares_mounted = mock.Mock()
|
||||
self.driver._get_mount_point_for_share = mock.Mock(
|
||||
return_value=self.fake_mount_point)
|
||||
|
||||
vol_size = self.driver.manage_existing_get_size(volume, vol_ref)
|
||||
|
||||
self.assertEqual(1, vol_size)
|
||||
|
||||
def test_manage_existing_get_size_round_up(self):
|
||||
test_file = 'test_file_name'
|
||||
self.driver._get_share_mount_and_vol_from_vol_ref = mock.Mock(
|
||||
return_value=(self.fake_nfs_export_1, self.fake_mount_point,
|
||||
test_file))
|
||||
self.mock_object(utils, 'get_file_size',
|
||||
mock.Mock(return_value=1073760270))
|
||||
self.driver._mounted_shares = [self.fake_nfs_export_1]
|
||||
volume = fake.FAKE_MANAGE_VOLUME
|
||||
vol_path = "%s/%s" % (self.fake_nfs_export_1, test_file)
|
||||
vol_ref = {'source-name': vol_path}
|
||||
|
||||
self.driver._ensure_shares_mounted = mock.Mock()
|
||||
self.driver._get_mount_point_for_share = mock.Mock(
|
||||
return_value=self.fake_mount_point)
|
||||
|
||||
vol_size = self.driver.manage_existing_get_size(volume, vol_ref)
|
||||
|
||||
self.assertEqual(2, vol_size)
|
||||
|
||||
def test_manage_existing_get_size_error(self):
|
||||
test_file = 'test_file_name'
|
||||
self.driver._get_share_mount_and_vol_from_vol_ref = mock.Mock(
|
||||
return_value=(self.fake_nfs_export_1, self.fake_mount_point,
|
||||
test_file))
|
||||
self.driver._mounted_shares = [self.fake_nfs_export_1]
|
||||
volume = fake.FAKE_MANAGE_VOLUME
|
||||
vol_path = "%s/%s" % (self.fake_nfs_export_1, test_file)
|
||||
vol_ref = {'source-name': vol_path}
|
||||
|
||||
self.driver._ensure_shares_mounted = mock.Mock()
|
||||
self.driver._get_mount_point_for_share = mock.Mock(
|
||||
return_value=self.fake_mount_point)
|
||||
|
||||
self.assertRaises(exception.VolumeBackendAPIException,
|
||||
self.driver.manage_existing_get_size,
|
||||
volume,
|
||||
vol_ref)
|
||||
|
@ -23,6 +23,7 @@ from oslo_service import loopingcall
|
||||
from oslo_utils import units
|
||||
|
||||
from cinder import exception
|
||||
from cinder.image import image_utils
|
||||
from cinder import test
|
||||
from cinder.tests.unit.volume.drivers.netapp.dataontap import fakes as fake
|
||||
from cinder.tests.unit.volume.drivers.netapp.dataontap.utils import fakes as \
|
||||
@ -81,6 +82,30 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
||||
self.assertTrue(mock_check_flags.called)
|
||||
self.assertTrue(mock_super_do_setup.called)
|
||||
|
||||
def test__update_volume_stats(self):
|
||||
mock_debug_log = self.mock_object(nfs_cmode.LOG, 'debug')
|
||||
self.mock_object(self.driver, 'get_filter_function')
|
||||
self.mock_object(self.driver, 'get_goodness_function')
|
||||
self.mock_object(self.driver, '_spawn_clean_cache_job')
|
||||
self.driver.zapi_client = mock.Mock()
|
||||
self.mock_object(
|
||||
self.driver, '_get_pool_stats', mock.Mock(return_value={}))
|
||||
expected_stats = {
|
||||
'driver_version': self.driver.VERSION,
|
||||
'pools': {},
|
||||
'sparse_copy_volume': True,
|
||||
'storage_protocol': 'nfs',
|
||||
'vendor_name': 'NetApp',
|
||||
'volume_backend_name': 'NetApp_NFS_Cluster_direct',
|
||||
}
|
||||
|
||||
retval = self.driver._update_volume_stats()
|
||||
|
||||
self.assertIsNone(retval)
|
||||
self.assertTrue(self.driver._spawn_clean_cache_job.called)
|
||||
self.assertEqual(1, mock_debug_log.call_count)
|
||||
self.assertEqual(expected_stats, self.driver._stats)
|
||||
|
||||
def test_get_pool_stats(self):
|
||||
|
||||
self.driver.zapi_client = mock.Mock()
|
||||
@ -252,6 +277,68 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
||||
|
||||
self.assertEqual({}, result)
|
||||
|
||||
@ddt.data(['/mnt/img-id1', '/mnt/img-id2'], [])
|
||||
def test__shortlist_del_eligible_files(self, old_files):
|
||||
self.driver.zapi_client = mock.Mock()
|
||||
self.driver.zapi_client.get_file_usage = mock.Mock(return_value='1000')
|
||||
mock_debug_log = self.mock_object(nfs_cmode.LOG, 'debug')
|
||||
self.mock_object(self.driver, '_get_vserver_and_exp_vol',
|
||||
mock.Mock(return_value=('openstack', 'fake_share')))
|
||||
expected_list = [(o, '1000') for o in old_files]
|
||||
|
||||
observed_list = self.driver._shortlist_del_eligible_files(
|
||||
'fake_ip:fake_share', old_files)
|
||||
|
||||
self.assertEqual(expected_list, observed_list)
|
||||
self.assertEqual(1, mock_debug_log.call_count)
|
||||
|
||||
@ddt.data({'ip': None, 'shares': None},
|
||||
{'ip': 'fake_ip', 'shares': ['fip:/fsh1']})
|
||||
@ddt.unpack
|
||||
def test__share_match_for_ip_no_match(self, ip, shares):
|
||||
def side_effect(arg):
|
||||
if arg == 'fake_ip':
|
||||
return 'openstack'
|
||||
return None
|
||||
|
||||
self.mock_object(self.driver, '_get_vserver_for_ip',
|
||||
mock.Mock(side_effect=side_effect))
|
||||
mock_debug_log = self.mock_object(nfs_cmode.LOG, 'debug')
|
||||
|
||||
retval = self.driver._share_match_for_ip(ip, shares)
|
||||
|
||||
self.assertIsNone(retval)
|
||||
self.assertEqual(1, mock_debug_log.call_count)
|
||||
|
||||
def test__share_match_for_ip(self):
|
||||
shares = ['fip:/fsh1']
|
||||
self.mock_object(self.driver, '_get_vserver_for_ip',
|
||||
mock.Mock(return_value='openstack'))
|
||||
mock_debug_log = self.mock_object(nfs_cmode.LOG, 'debug')
|
||||
|
||||
retval = self.driver._share_match_for_ip('fip', shares)
|
||||
|
||||
self.assertEqual('fip:/fsh1', retval)
|
||||
self.assertEqual(1, mock_debug_log.call_count)
|
||||
|
||||
def test__get_vserver_for_ip_ignores_zapi_exception(self):
|
||||
self.driver.zapi_client = mock.Mock()
|
||||
self.driver.zapi_client.get_if_info_by_ip = mock.Mock(
|
||||
side_effect=exception.NotFound)
|
||||
|
||||
vserver = self.driver._get_vserver_for_ip('FAKE_IP')
|
||||
|
||||
self.assertIsNone(vserver)
|
||||
|
||||
def test__get_vserver_for_ip(self):
|
||||
self.driver.zapi_client = mock.Mock()
|
||||
self.driver.zapi_client.get_if_info_by_ip = mock.Mock(
|
||||
return_value=fake.get_fake_ifs())
|
||||
|
||||
vserver = self.driver._get_vserver_for_ip('FAKE_IP')
|
||||
|
||||
self.assertIsNone(vserver)
|
||||
|
||||
def test_check_for_setup_error(self):
|
||||
super_check_for_setup_error = self.mock_object(
|
||||
nfs_base.NetAppNfsDriver, 'check_for_setup_error')
|
||||
@ -290,7 +377,10 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
||||
self.mock_object(na_utils,
|
||||
'get_valid_qos_policy_group_info',
|
||||
mock.Mock(return_value='fake_qos_policy_group_info'))
|
||||
self.driver.zapi_client = mock.Mock(side_effect=Exception)
|
||||
self.mock_object(
|
||||
self.driver.zapi_client,
|
||||
'mark_qos_policy_group_for_deletion',
|
||||
mock.Mock(side_effect=exception.NetAppDriverException))
|
||||
|
||||
self.driver.delete_volume(fake_volume)
|
||||
|
||||
@ -312,17 +402,23 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
||||
mock_filer_delete.assert_called_once_with(fake.NFS_VOLUME)
|
||||
self.assertEqual(0, mock_super_delete.call_count)
|
||||
|
||||
def test_delete_backing_file_for_volume_exception_path(self):
|
||||
@ddt.data(True, False)
|
||||
def test_delete_backing_file_for_volume_exception_path(self, super_exc):
|
||||
mock_exception_log = self.mock_object(nfs_cmode.LOG, 'exception')
|
||||
exception_call_count = 2 if super_exc else 1
|
||||
mock_filer_delete = self.mock_object(self.driver,
|
||||
'_delete_volume_on_filer')
|
||||
mock_filer_delete.side_effect = [Exception]
|
||||
mock_super_delete = self.mock_object(nfs_base.NetAppNfsDriver,
|
||||
'delete_volume')
|
||||
if super_exc:
|
||||
mock_super_delete.side_effect = [Exception]
|
||||
|
||||
self.driver._delete_backing_file_for_volume(fake.NFS_VOLUME)
|
||||
|
||||
mock_filer_delete.assert_called_once_with(fake.NFS_VOLUME)
|
||||
mock_super_delete.assert_called_once_with(fake.NFS_VOLUME)
|
||||
self.assertEqual(exception_call_count, mock_exception_log.call_count)
|
||||
|
||||
def test_delete_volume_on_filer(self):
|
||||
mock_get_vs_ip = self.mock_object(self.driver, '_get_export_ip_path')
|
||||
@ -356,17 +452,23 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
||||
mock_filer_delete.assert_called_once_with(fake.test_snapshot)
|
||||
self.assertEqual(0, mock_super_delete.call_count)
|
||||
|
||||
def test_delete_backing_file_for_snapshot_exception_path(self):
|
||||
@ddt.data(True, False)
|
||||
def test_delete_backing_file_for_snapshot_exception_path(self, super_exc):
|
||||
mock_exception_log = self.mock_object(nfs_cmode.LOG, 'exception')
|
||||
exception_call_count = 2 if super_exc else 1
|
||||
mock_filer_delete = self.mock_object(
|
||||
self.driver, '_delete_snapshot_on_filer')
|
||||
mock_filer_delete.side_effect = [Exception]
|
||||
mock_super_delete = self.mock_object(nfs_base.NetAppNfsDriver,
|
||||
'delete_snapshot')
|
||||
if super_exc:
|
||||
mock_super_delete.side_effect = [Exception]
|
||||
|
||||
self.driver._delete_backing_file_for_snapshot(fake.test_snapshot)
|
||||
|
||||
mock_filer_delete.assert_called_once_with(fake.test_snapshot)
|
||||
mock_super_delete.assert_called_once_with(fake.test_snapshot)
|
||||
self.assertEqual(exception_call_count, mock_exception_log.call_count)
|
||||
|
||||
def test_delete_snapshot_on_filer(self):
|
||||
mock_get_vs_ip = self.mock_object(self.driver, '_get_export_ip_path')
|
||||
@ -547,6 +649,164 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
||||
fake.FLEXVOL, fake.FLEXVOL, 'fake_clone', fake.VSERVER_NAME,
|
||||
is_snapshot=is_snapshot)
|
||||
|
||||
def test__clone_backing_file_for_volume(self):
|
||||
body = fake.get_fake_net_interface_get_iter_response()
|
||||
self.driver.zapi_client.get_if_info_by_ip = mock.Mock(
|
||||
return_value=[netapp_api.NaElement(body)])
|
||||
self.driver.zapi_client.get_vol_by_junc_vserver = mock.Mock(
|
||||
return_value='nfsvol')
|
||||
self.mock_object(self.driver, '_get_export_ip_path',
|
||||
mock.Mock(return_value=('127.0.0.1', 'fakepath')))
|
||||
|
||||
retval = self.driver._clone_backing_file_for_volume(
|
||||
'vol', 'clone', 'vol_id', share='share', is_snapshot=True)
|
||||
|
||||
self.assertIsNone(retval)
|
||||
self.driver.zapi_client.clone_file.assert_called_once_with(
|
||||
'nfsvol', 'vol', 'clone', None, is_snapshot=True)
|
||||
|
||||
def test__copy_from_img_service_copyoffload_nonexistent_binary_path(self):
|
||||
self.mock_object(nfs_cmode.LOG, 'debug')
|
||||
drv = self.driver
|
||||
context = object()
|
||||
volume = {'id': 'vol_id', 'name': 'name'}
|
||||
image_service = mock.Mock()
|
||||
image_service.get_location.return_value = (mock.Mock(), mock.Mock())
|
||||
image_service.show.return_value = {'size': 0}
|
||||
image_id = 'image_id'
|
||||
drv._client = mock.Mock()
|
||||
drv._client.get_api_version = mock.Mock(return_value=(1, 20))
|
||||
drv._find_image_in_cache = mock.Mock(return_value=[])
|
||||
drv._construct_image_nfs_url = mock.Mock(return_value=["nfs://1"])
|
||||
drv._check_get_nfs_path_segs = mock.Mock(
|
||||
return_value=("test:test", "dr"))
|
||||
drv._get_ip_verify_on_cluster = mock.Mock(return_value="192.128.1.1")
|
||||
drv._get_mount_point_for_share = mock.Mock(return_value='mnt_point')
|
||||
drv._get_host_ip = mock.Mock()
|
||||
drv._get_provider_location = mock.Mock()
|
||||
drv._get_export_path = mock.Mock(return_value="dr")
|
||||
drv._check_share_can_hold_size = mock.Mock()
|
||||
# Raise error as if the copyoffload file can not be found
|
||||
drv._clone_file_dst_exists = mock.Mock(side_effect=OSError())
|
||||
drv._discover_file_till_timeout = mock.Mock()
|
||||
|
||||
# Verify the original error is propagated
|
||||
self.assertRaises(OSError, drv._copy_from_img_service,
|
||||
context, volume, image_service, image_id)
|
||||
|
||||
drv._discover_file_till_timeout.assert_not_called()
|
||||
|
||||
@mock.patch.object(image_utils, 'qemu_img_info')
|
||||
def test__copy_from_img_service_raw_copyoffload_workflow_success(
|
||||
self, mock_qemu_img_info):
|
||||
drv = self.driver
|
||||
volume = {'id': 'vol_id', 'name': 'name', 'size': 1}
|
||||
image_id = 'image_id'
|
||||
context = object()
|
||||
image_service = mock.Mock()
|
||||
image_service.get_location.return_value = ('nfs://ip1/openstack/img',
|
||||
None)
|
||||
image_service.show.return_value = {'size': 1, 'disk_format': 'raw'}
|
||||
|
||||
drv._check_get_nfs_path_segs =\
|
||||
mock.Mock(return_value=('ip1', '/openstack'))
|
||||
drv._get_ip_verify_on_cluster = mock.Mock(return_value='ip1')
|
||||
drv._get_host_ip = mock.Mock(return_value='ip2')
|
||||
drv._get_export_path = mock.Mock(return_value='/exp_path')
|
||||
drv._get_provider_location = mock.Mock(return_value='share')
|
||||
drv._execute = mock.Mock()
|
||||
drv._get_mount_point_for_share = mock.Mock(return_value='mnt_point')
|
||||
drv._discover_file_till_timeout = mock.Mock(return_value=True)
|
||||
img_inf = mock.Mock()
|
||||
img_inf.file_format = 'raw'
|
||||
mock_qemu_img_info.return_value = img_inf
|
||||
drv._check_share_can_hold_size = mock.Mock()
|
||||
drv._move_nfs_file = mock.Mock(return_value=True)
|
||||
drv._delete_file_at_path = mock.Mock()
|
||||
drv._clone_file_dst_exists = mock.Mock()
|
||||
drv._post_clone_image = mock.Mock()
|
||||
|
||||
retval = drv._copy_from_img_service(
|
||||
context, volume, image_service, image_id)
|
||||
|
||||
self.assertIsNone(retval)
|
||||
drv._get_ip_verify_on_cluster.assert_any_call('ip1')
|
||||
drv._get_export_path.assert_called_with('vol_id')
|
||||
drv._check_share_can_hold_size.assert_called_with('share', 1)
|
||||
drv._post_clone_image.assert_called_with(volume)
|
||||
self.assertEqual(1, drv._execute.call_count)
|
||||
|
||||
@mock.patch.object(image_utils, 'convert_image')
|
||||
@mock.patch.object(image_utils, 'qemu_img_info')
|
||||
@mock.patch('os.path.exists')
|
||||
def test__copy_from_img_service_qcow2_copyoffload_workflow_success(
|
||||
self, mock_exists, mock_qemu_img_info, mock_cvrt_image):
|
||||
drv = self.driver
|
||||
volume = {'id': 'vol_id', 'name': 'name', 'size': 1}
|
||||
image_id = 'image_id'
|
||||
context = object()
|
||||
image_service = mock.Mock()
|
||||
image_service.get_location.return_value = ('nfs://ip1/openstack/img',
|
||||
None)
|
||||
image_service.show.return_value = {'size': 1,
|
||||
'disk_format': 'qcow2'}
|
||||
drv._check_get_nfs_path_segs =\
|
||||
mock.Mock(return_value=('ip1', '/openstack'))
|
||||
|
||||
drv._get_ip_verify_on_cluster = mock.Mock(return_value='ip1')
|
||||
drv._get_host_ip = mock.Mock(return_value='ip2')
|
||||
drv._get_export_path = mock.Mock(return_value='/exp_path')
|
||||
drv._get_provider_location = mock.Mock(return_value='share')
|
||||
drv._execute = mock.Mock()
|
||||
drv._get_mount_point_for_share = mock.Mock(return_value='mnt_point')
|
||||
img_inf = mock.Mock()
|
||||
img_inf.file_format = 'raw'
|
||||
mock_qemu_img_info.return_value = img_inf
|
||||
drv._check_share_can_hold_size = mock.Mock()
|
||||
|
||||
drv._move_nfs_file = mock.Mock(return_value=True)
|
||||
drv._delete_file_at_path = mock.Mock()
|
||||
drv._clone_file_dst_exists = mock.Mock()
|
||||
drv._post_clone_image = mock.Mock()
|
||||
|
||||
retval = drv._copy_from_img_service(
|
||||
context, volume, image_service, image_id)
|
||||
|
||||
self.assertIsNone(retval)
|
||||
drv._get_ip_verify_on_cluster.assert_any_call('ip1')
|
||||
drv._get_export_path.assert_called_with('vol_id')
|
||||
drv._check_share_can_hold_size.assert_called_with('share', 1)
|
||||
drv._post_clone_image.assert_called_with(volume)
|
||||
self.assertEqual(1, mock_cvrt_image.call_count)
|
||||
self.assertEqual(1, drv._execute.call_count)
|
||||
self.assertEqual(2, drv._delete_file_at_path.call_count)
|
||||
self.assertEqual(1, drv._clone_file_dst_exists.call_count)
|
||||
|
||||
def test__copy_from_cache_copyoffload_success(self):
|
||||
drv = self.driver
|
||||
volume = {'id': 'vol_id', 'name': 'name', 'size': 1}
|
||||
image_id = 'image_id'
|
||||
cache_result = [('ip1:/openstack', 'img-cache-imgid')]
|
||||
drv._get_ip_verify_on_cluster = mock.Mock(return_value='ip1')
|
||||
drv._get_host_ip = mock.Mock(return_value='ip2')
|
||||
drv._get_export_path = mock.Mock(return_value='/exp_path')
|
||||
drv._execute = mock.Mock()
|
||||
drv._register_image_in_cache = mock.Mock()
|
||||
drv._get_provider_location = mock.Mock(return_value='/share')
|
||||
drv._post_clone_image = mock.Mock()
|
||||
|
||||
copied = drv._copy_from_cache(volume, image_id, cache_result)
|
||||
|
||||
self.assertTrue(copied)
|
||||
drv._get_ip_verify_on_cluster.assert_any_call('ip1')
|
||||
drv._get_export_path.assert_called_with('vol_id')
|
||||
drv._execute.assert_called_once_with(
|
||||
'copyoffload_tool_path', 'ip1', 'ip1',
|
||||
'/openstack/img-cache-imgid', '/exp_path/name',
|
||||
run_as_root=False, check_exit_code=0)
|
||||
drv._post_clone_image.assert_called_with(volume)
|
||||
drv._get_provider_location.assert_called_with('vol_id')
|
||||
|
||||
def test_unmanage(self):
|
||||
mock_get_info = self.mock_object(na_utils,
|
||||
'get_valid_qos_policy_group_info')
|
||||
@ -782,6 +1042,95 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
||||
self.driver._get_host_ip.assert_called_once_with(fake.VOLUME_ID)
|
||||
self.driver._get_export_path.assert_called_once_with(fake.VOLUME_ID)
|
||||
|
||||
def test_copy_image_to_volume_copyoffload_non_cached_ssc_update(self):
|
||||
mock_log = self.mock_object(nfs_cmode, 'LOG')
|
||||
drv = self.driver
|
||||
context = object()
|
||||
volume = {'id': 'vol_id', 'name': 'name'}
|
||||
image_service = object()
|
||||
image_id = 'image_id'
|
||||
drv.zapi_client = mock.Mock()
|
||||
drv.zapi_client.get_ontapi_version = mock.Mock(return_value=(1, 20))
|
||||
drv._copy_from_img_service = mock.Mock()
|
||||
drv._get_provider_location = mock.Mock(return_value='share')
|
||||
drv._get_vol_for_share = mock.Mock(return_value='vol')
|
||||
|
||||
retval = drv.copy_image_to_volume(
|
||||
context, volume, image_service, image_id)
|
||||
|
||||
self.assertIsNone(retval)
|
||||
drv._copy_from_img_service.assert_called_once_with(
|
||||
context, volume, image_service, image_id)
|
||||
self.assertEqual(1, mock_log.debug.call_count)
|
||||
self.assertEqual(1, mock_log.info.call_count)
|
||||
|
||||
def test_copy_image_to_volume_copyoffload_from_cache_success(self):
|
||||
mock_info_log = self.mock_object(nfs_cmode.LOG, 'info')
|
||||
drv = self.driver
|
||||
context = object()
|
||||
volume = {'id': 'vol_id', 'name': 'name'}
|
||||
image_service = object()
|
||||
image_id = 'image_id'
|
||||
drv.zapi_client = mock.Mock()
|
||||
drv.zapi_client.get_ontapi_version = mock.Mock(return_value=(1, 20))
|
||||
nfs_base.NetAppNfsDriver.copy_image_to_volume = mock.Mock()
|
||||
drv._get_provider_location = mock.Mock(return_value='share')
|
||||
drv._get_vol_for_share = mock.Mock(return_value='vol')
|
||||
drv._find_image_in_cache = mock.Mock(return_value=[('share', 'img')])
|
||||
drv._copy_from_cache = mock.Mock(return_value=True)
|
||||
|
||||
drv.copy_image_to_volume(context, volume, image_service, image_id)
|
||||
|
||||
drv._copy_from_cache.assert_called_once_with(
|
||||
volume, image_id, [('share', 'img')])
|
||||
self.assertEqual(1, mock_info_log.call_count)
|
||||
|
||||
def test_copy_image_to_volume_copyoffload_from_img_service(self):
|
||||
drv = self.driver
|
||||
context = object()
|
||||
volume = {'id': 'vol_id', 'name': 'name'}
|
||||
image_service = object()
|
||||
image_id = 'image_id'
|
||||
drv.zapi_client = mock.Mock()
|
||||
drv.zapi_client.get_ontapi_version = mock.Mock(return_value=(1, 20))
|
||||
nfs_base.NetAppNfsDriver.copy_image_to_volume = mock.Mock()
|
||||
drv._get_provider_location = mock.Mock(return_value='share')
|
||||
drv._get_vol_for_share = mock.Mock(return_value='vol')
|
||||
drv._find_image_in_cache = mock.Mock(return_value=False)
|
||||
drv._copy_from_img_service = mock.Mock()
|
||||
|
||||
retval = drv.copy_image_to_volume(
|
||||
context, volume, image_service, image_id)
|
||||
|
||||
self.assertIsNone(retval)
|
||||
drv._copy_from_img_service.assert_called_once_with(
|
||||
context, volume, image_service, image_id)
|
||||
|
||||
def test_copy_image_to_volume_copyoffload_failure(self):
|
||||
mock_log = self.mock_object(nfs_cmode, 'LOG')
|
||||
drv = self.driver
|
||||
context = object()
|
||||
volume = {'id': 'vol_id', 'name': 'name'}
|
||||
image_service = object()
|
||||
image_id = 'image_id'
|
||||
drv.zapi_client = mock.Mock()
|
||||
drv.zapi_client.get_ontapi_version = mock.Mock(return_value=(1, 20))
|
||||
drv._copy_from_img_service = mock.Mock(side_effect=Exception())
|
||||
nfs_base.NetAppNfsDriver.copy_image_to_volume = mock.Mock()
|
||||
drv._get_provider_location = mock.Mock(return_value='share')
|
||||
drv._get_vol_for_share = mock.Mock(return_value='vol')
|
||||
|
||||
retval = drv.copy_image_to_volume(
|
||||
context, volume, image_service, image_id)
|
||||
|
||||
self.assertIsNone(retval)
|
||||
drv._copy_from_img_service.assert_called_once_with(
|
||||
context, volume, image_service, image_id)
|
||||
nfs_base.NetAppNfsDriver.copy_image_to_volume. \
|
||||
assert_called_once_with(context, volume, image_service, image_id)
|
||||
mock_log.info.assert_not_called()
|
||||
self.assertEqual(1, mock_log.exception.call_count)
|
||||
|
||||
def test_copy_from_remote_cache(self):
|
||||
source_ip = '192.0.1.1'
|
||||
source_path = '/openstack/img-cache-imgid'
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user