Use versionedobjects in remotefs.py
Use versioned objects in remotefs.py, which is base classes for all drivers with an interface of remote filesystem. Update glusterfs, nfs, smbfs, quobyte, scality, vzstorage volume drivers to use versionedobjects instead of dicts. Please note that netapp_nfs driver wasn't fixed, just unit tests were adapted to pass. Change-Id: Iebd20544102672d7b7ca820c9e9005833ec2580e Depends-On: I661ef85755e9c75aaedb4f157165d2514de3e9ec
This commit is contained in:
parent
ec51a682db
commit
369572f5b2
@ -34,8 +34,9 @@ from cinder import db
|
|||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.i18n import _
|
from cinder.i18n import _
|
||||||
from cinder.image import image_utils
|
from cinder.image import image_utils
|
||||||
from cinder.objects import fields
|
|
||||||
from cinder import test
|
from cinder import test
|
||||||
|
from cinder.tests.unit import fake_snapshot
|
||||||
|
from cinder.tests.unit import fake_volume
|
||||||
from cinder import utils
|
from cinder import utils
|
||||||
from cinder.volume import driver as base_driver
|
from cinder.volume import driver as base_driver
|
||||||
from cinder.volume.drivers import glusterfs
|
from cinder.volume.drivers import glusterfs
|
||||||
@ -45,16 +46,6 @@ from cinder.volume.drivers import remotefs as remotefs_drv
|
|||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
class DumbVolume(object):
|
|
||||||
fields = {}
|
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
|
||||||
self.fields[key] = value
|
|
||||||
|
|
||||||
def __getitem__(self, item):
|
|
||||||
return self.fields[item]
|
|
||||||
|
|
||||||
|
|
||||||
class FakeDb(object):
|
class FakeDb(object):
|
||||||
msg = "Tests are broken: mock this out."
|
msg = "Tests are broken: mock this out."
|
||||||
|
|
||||||
@ -66,6 +57,17 @@ class FakeDb(object):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
class SideEffectList(object):
|
||||||
|
def __init__(self, obj, **kwargs):
|
||||||
|
self.obj = obj
|
||||||
|
self.attrs = kwargs
|
||||||
|
|
||||||
|
def __call__(self, *args, **kw):
|
||||||
|
for attr in self.attrs.keys():
|
||||||
|
setattr(self.obj, attr, self.attrs[attr].pop(0))
|
||||||
|
return self.obj
|
||||||
|
|
||||||
|
|
||||||
class GlusterFsDriverTestCase(test.TestCase):
|
class GlusterFsDriverTestCase(test.TestCase):
|
||||||
"""Test case for GlusterFS driver."""
|
"""Test case for GlusterFS driver."""
|
||||||
|
|
||||||
@ -75,12 +77,10 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
TEST_SIZE_IN_GB = 1
|
TEST_SIZE_IN_GB = 1
|
||||||
TEST_MNT_POINT = '/mnt/glusterfs'
|
TEST_MNT_POINT = '/mnt/glusterfs'
|
||||||
TEST_MNT_POINT_BASE = '/mnt/test'
|
TEST_MNT_POINT_BASE = '/mnt/test'
|
||||||
TEST_LOCAL_PATH = '/mnt/glusterfs/volume-123'
|
|
||||||
TEST_FILE_NAME = 'test.txt'
|
TEST_FILE_NAME = 'test.txt'
|
||||||
TEST_SHARES_CONFIG_FILE = '/etc/cinder/test-shares.conf'
|
TEST_SHARES_CONFIG_FILE = '/etc/cinder/test-shares.conf'
|
||||||
TEST_TMP_FILE = '/tmp/tempfile'
|
TEST_TMP_FILE = '/tmp/tempfile'
|
||||||
VOLUME_UUID = 'abcdefab-cdef-abcd-efab-cdefabcdefab'
|
VOLUME_UUID = 'abcdefab-cdef-abcd-efab-cdefabcdefab'
|
||||||
VOLUME_NAME = 'volume-%s' % VOLUME_UUID
|
|
||||||
SNAP_UUID = 'bacadaca-baca-daca-baca-dacadacadaca'
|
SNAP_UUID = 'bacadaca-baca-daca-baca-dacadacadaca'
|
||||||
SNAP_UUID_2 = 'bebedede-bebe-dede-bebe-dedebebedede'
|
SNAP_UUID_2 = 'bebedede-bebe-dede-bebe-dedebebedede'
|
||||||
|
|
||||||
@ -102,6 +102,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
db=FakeDb())
|
db=FakeDb())
|
||||||
self._driver.shares = {}
|
self._driver.shares = {}
|
||||||
compute.API = mock.MagicMock()
|
compute.API = mock.MagicMock()
|
||||||
|
self.context = context.get_admin_context()
|
||||||
|
|
||||||
def assertRaisesAndMessageMatches(
|
def assertRaisesAndMessageMatches(
|
||||||
self, excClass, msg, callableObj, *args, **kwargs):
|
self, excClass, msg, callableObj, *args, **kwargs):
|
||||||
@ -126,13 +127,12 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
self.TEST_MNT_POINT_BASE)
|
self.TEST_MNT_POINT_BASE)
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
|
|
||||||
volume = DumbVolume()
|
volume = fake_volume.fake_volume_obj(
|
||||||
volume['id'] = self.VOLUME_UUID
|
self.context,
|
||||||
volume['provider_location'] = self.TEST_EXPORT1
|
provider_location=self.TEST_EXPORT1)
|
||||||
volume['name'] = 'volume-123'
|
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'/mnt/test/ab03ab34eaca46a5fb81878f7e9b91fc/volume-123',
|
'/mnt/test/ab03ab34eaca46a5fb81878f7e9b91fc/%s' % volume.name,
|
||||||
drv.local_path(volume))
|
drv.local_path(volume))
|
||||||
|
|
||||||
def test_mount_glusterfs(self):
|
def test_mount_glusterfs(self):
|
||||||
@ -470,17 +470,20 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
drv._find_share,
|
drv._find_share,
|
||||||
self.TEST_SIZE_IN_GB)
|
self.TEST_SIZE_IN_GB)
|
||||||
|
|
||||||
def _simple_volume(self, id=None):
|
def _simple_volume(self, id=None, **updates):
|
||||||
volume = DumbVolume()
|
|
||||||
volume['provider_location'] = self.TEST_EXPORT1
|
|
||||||
if id is None:
|
if id is None:
|
||||||
volume['id'] = self.VOLUME_UUID
|
id = self.VOLUME_UUID
|
||||||
else:
|
if 'id' not in updates:
|
||||||
volume['id'] = id
|
updates['id'] = self.VOLUME_UUID
|
||||||
# volume['name'] mirrors format from db/sqlalchemy/models.py
|
if 'name' not in updates:
|
||||||
volume['name'] = 'volume-%s' % volume['id']
|
updates['name'] = 'volume-%s' % id
|
||||||
volume['size'] = 10
|
if 'status' not in updates:
|
||||||
volume['status'] = 'available'
|
updates['status'] = 'available'
|
||||||
|
if 'provider_location' not in updates:
|
||||||
|
updates['provider_location'] = self.TEST_EXPORT1
|
||||||
|
if 'size' not in updates:
|
||||||
|
updates['size'] = 10
|
||||||
|
volume = fake_volume.fake_volume_obj(self.context, **updates)
|
||||||
|
|
||||||
return volume
|
return volume
|
||||||
|
|
||||||
@ -497,7 +500,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
drv._do_create_volume(volume)
|
drv._do_create_volume(volume)
|
||||||
|
|
||||||
volume_path = drv.local_path(volume)
|
volume_path = drv.local_path(volume)
|
||||||
volume_size = volume['size']
|
volume_size = volume.size
|
||||||
mock_create_qcow2_file.assert_called_once_with(volume_path,
|
mock_create_qcow2_file.assert_called_once_with(volume_path,
|
||||||
volume_size)
|
volume_size)
|
||||||
mock_set_rw_permissions_for_all.\
|
mock_set_rw_permissions_for_all.\
|
||||||
@ -516,7 +519,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
drv._do_create_volume(volume)
|
drv._do_create_volume(volume)
|
||||||
|
|
||||||
volume_path = drv.local_path(volume)
|
volume_path = drv.local_path(volume)
|
||||||
volume_size = volume['size']
|
volume_size = volume.size
|
||||||
mock_fallocate.assert_called_once_with(volume_path,
|
mock_fallocate.assert_called_once_with(volume_path,
|
||||||
volume_size)
|
volume_size)
|
||||||
mock_set_rw_permissions_for_all.\
|
mock_set_rw_permissions_for_all.\
|
||||||
@ -539,7 +542,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
drv._do_create_volume(volume)
|
drv._do_create_volume(volume)
|
||||||
|
|
||||||
volume_path = drv.local_path(volume)
|
volume_path = drv.local_path(volume)
|
||||||
volume_size = volume['size']
|
volume_size = volume.size
|
||||||
mock_fallocate.assert_called_once_with(volume_path,
|
mock_fallocate.assert_called_once_with(volume_path,
|
||||||
volume_size)
|
volume_size)
|
||||||
mock_create_regular_file.assert_called_once_with(volume_path,
|
mock_create_regular_file.assert_called_once_with(volume_path,
|
||||||
@ -556,9 +559,10 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
mock_do_create_volume,\
|
mock_do_create_volume,\
|
||||||
mock.patch.object(drv, '_ensure_shares_mounted') as \
|
mock.patch.object(drv, '_ensure_shares_mounted') as \
|
||||||
mock_ensure_shares_mounted:
|
mock_ensure_shares_mounted:
|
||||||
volume = DumbVolume()
|
volume = fake_volume.fake_volume_obj(self.context,
|
||||||
volume['size'] = self.TEST_SIZE_IN_GB
|
size=self.TEST_SIZE_IN_GB,
|
||||||
volume['id'] = self.VOLUME_UUID
|
id=self.VOLUME_UUID)
|
||||||
|
mock_find_share.return_value = self.TEST_EXPORT2
|
||||||
drv.create_volume(volume)
|
drv.create_volume(volume)
|
||||||
self.assertTrue(mock_ensure_shares_mounted.called)
|
self.assertTrue(mock_ensure_shares_mounted.called)
|
||||||
self.assertTrue(mock_do_create_volume.called)
|
self.assertTrue(mock_do_create_volume.called)
|
||||||
@ -575,9 +579,9 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
mock_ensure_shares_mounted:
|
mock_ensure_shares_mounted:
|
||||||
mock_find_share.return_value = self.TEST_EXPORT1
|
mock_find_share.return_value = self.TEST_EXPORT1
|
||||||
|
|
||||||
volume = DumbVolume()
|
volume = fake_volume.fake_volume_obj(self.context,
|
||||||
volume['size'] = self.TEST_SIZE_IN_GB
|
size=self.TEST_SIZE_IN_GB,
|
||||||
volume['id'] = self.VOLUME_UUID
|
id=self.VOLUME_UUID)
|
||||||
result = drv.create_volume(volume)
|
result = drv.create_volume(volume)
|
||||||
self.assertEqual(self.TEST_EXPORT1, result['provider_location'])
|
self.assertEqual(self.TEST_EXPORT1, result['provider_location'])
|
||||||
self.assertTrue(mock_ensure_shares_mounted.called)
|
self.assertTrue(mock_ensure_shares_mounted.called)
|
||||||
@ -610,7 +614,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
self._driver.delete_volume(volume)
|
self._driver.delete_volume(volume)
|
||||||
|
|
||||||
mock_ensure_share_mounted.assert_called_once_with(
|
mock_ensure_share_mounted.assert_called_once_with(
|
||||||
volume['provider_location'])
|
volume.provider_location)
|
||||||
mock_local_volume_dir.assert_called_once_with(volume)
|
mock_local_volume_dir.assert_called_once_with(volume)
|
||||||
mock_active_image_from_info.assert_called_once_with(volume)
|
mock_active_image_from_info.assert_called_once_with(volume)
|
||||||
mock_execute.assert_called_once_with('rm', '-f', volume_path,
|
mock_execute.assert_called_once_with('rm', '-f', volume_path,
|
||||||
@ -827,10 +831,12 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
with mock.patch.object(drv, '_execute') as mock_execute,\
|
with mock.patch.object(drv, '_execute') as mock_execute,\
|
||||||
mock.patch.object(drv, '_ensure_share_mounted') as \
|
mock.patch.object(drv, '_ensure_share_mounted') as \
|
||||||
mock_ensure_share_mounted:
|
mock_ensure_share_mounted:
|
||||||
volume = DumbVolume()
|
|
||||||
volume['id'] = self.VOLUME_UUID
|
volume = fake_volume.fake_volume_obj(
|
||||||
volume['name'] = 'volume-123'
|
self.context,
|
||||||
volume['provider_location'] = self.TEST_EXPORT1
|
id=self.VOLUME_UUID,
|
||||||
|
display_name='volume-123',
|
||||||
|
provider_location=self.TEST_EXPORT1)
|
||||||
|
|
||||||
drv.delete_volume(volume)
|
drv.delete_volume(volume)
|
||||||
|
|
||||||
@ -845,10 +851,10 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
with mock.patch.object(drv, '_execute') as mock_execute,\
|
with mock.patch.object(drv, '_execute') as mock_execute,\
|
||||||
mock.patch.object(drv, '_ensure_share_mounted') as \
|
mock.patch.object(drv, '_ensure_share_mounted') as \
|
||||||
mock_ensure_share_mounted:
|
mock_ensure_share_mounted:
|
||||||
volume = DumbVolume()
|
volume = fake_volume.fake_volume_obj(self.context,
|
||||||
volume['id'] = self.VOLUME_UUID
|
id=self.VOLUME_UUID,
|
||||||
volume['name'] = 'volume-123'
|
name='volume-123',
|
||||||
volume['provider_location'] = None
|
provider_location=None)
|
||||||
|
|
||||||
drv.delete_volume(volume)
|
drv.delete_volume(volume)
|
||||||
|
|
||||||
@ -868,10 +874,6 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
mock_read_file.return_value = '{"%(id)s": "volume-%(id)s"}' %\
|
mock_read_file.return_value = '{"%(id)s": "volume-%(id)s"}' %\
|
||||||
{'id': self.VOLUME_UUID}
|
{'id': self.VOLUME_UUID}
|
||||||
|
|
||||||
volume = DumbVolume()
|
|
||||||
volume['id'] = self.VOLUME_UUID
|
|
||||||
volume['name'] = 'volume-%s' % self.VOLUME_UUID
|
|
||||||
|
|
||||||
info = drv._read_info_file(info_path)
|
info = drv._read_info_file(info_path)
|
||||||
|
|
||||||
self.assertEqual('volume-%s' % self.VOLUME_UUID,
|
self.assertEqual('volume-%s' % self.VOLUME_UUID,
|
||||||
@ -897,7 +899,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
mock_qemu_img_info,\
|
mock_qemu_img_info,\
|
||||||
mock.patch.object(image_utils, 'resize_image') as \
|
mock.patch.object(image_utils, 'resize_image') as \
|
||||||
mock_resize_image:
|
mock_resize_image:
|
||||||
mock_get_active_image_from_info.return_value = volume['name']
|
mock_get_active_image_from_info.return_value = volume.name
|
||||||
mock_local_volume_dir.return_value = self.TEST_MNT_POINT
|
mock_local_volume_dir.return_value = self.TEST_MNT_POINT
|
||||||
mock_qemu_img_info.return_value = img_info
|
mock_qemu_img_info.return_value = img_info
|
||||||
|
|
||||||
@ -940,9 +942,6 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
def test_create_snapshot_online(self):
|
def test_create_snapshot_online(self):
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
|
|
||||||
volume = self._simple_volume()
|
|
||||||
volume['status'] = 'in-use'
|
|
||||||
|
|
||||||
hashed = drv._get_hash_str(self.TEST_EXPORT1)
|
hashed = drv._get_hash_str(self.TEST_EXPORT1)
|
||||||
volume_file = 'volume-%s' % self.VOLUME_UUID
|
volume_file = 'volume-%s' % self.VOLUME_UUID
|
||||||
volume_path = '%s/%s/%s' % (self.TEST_MNT_POINT_BASE,
|
volume_path = '%s/%s/%s' % (self.TEST_MNT_POINT_BASE,
|
||||||
@ -951,13 +950,14 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
ctxt = context.RequestContext('fake_user', 'fake_project')
|
ctxt = context.RequestContext('fake_user', 'fake_project')
|
||||||
|
|
||||||
snap_ref = {'name': 'test snap (online)',
|
snap_ref = fake_snapshot.fake_snapshot_obj(
|
||||||
'volume_id': self.VOLUME_UUID,
|
ctxt,
|
||||||
'volume': volume,
|
display_name='test snap (online)',
|
||||||
'id': self.SNAP_UUID,
|
volume_id=self.VOLUME_UUID,
|
||||||
'context': ctxt,
|
id=self.SNAP_UUID,
|
||||||
'status': fields.SnapshotStatus.CREATING,
|
status='creating',
|
||||||
'progress': 'asdf'}
|
progress='asdf')
|
||||||
|
snap_ref.context = ctxt
|
||||||
|
|
||||||
snap_path = '%s.%s' % (volume_path, self.SNAP_UUID)
|
snap_path = '%s.%s' % (volume_path, self.SNAP_UUID)
|
||||||
snap_file = '%s.%s' % (volume_file, self.SNAP_UUID)
|
snap_file = '%s.%s' % (volume_file, self.SNAP_UUID)
|
||||||
@ -967,26 +967,13 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
mock.patch.object(db, 'snapshot_get') as mock_snapshot_get,\
|
mock.patch.object(db, 'snapshot_get') as mock_snapshot_get,\
|
||||||
mock.patch.object(drv, '_nova') as mock_nova,\
|
mock.patch.object(drv, '_nova') as mock_nova,\
|
||||||
mock.patch.object(time, 'sleep') as mock_sleep:
|
mock.patch.object(time, 'sleep') as mock_sleep:
|
||||||
create_info = {'snapshot_id': snap_ref['id'],
|
create_info = {'snapshot_id': snap_ref.id,
|
||||||
'type': 'qcow2',
|
'type': 'qcow2',
|
||||||
'new_file': snap_file}
|
'new_file': snap_file}
|
||||||
|
|
||||||
snap_ref_progress = snap_ref.copy()
|
mock_snapshot_get.side_effect = SideEffectList(
|
||||||
snap_ref_progress['status'] = fields.SnapshotStatus.CREATING
|
snap_ref,
|
||||||
|
progress = ['0%', '50%', '90%'])
|
||||||
snap_ref_progress_0p = snap_ref_progress.copy()
|
|
||||||
snap_ref_progress_0p['progress'] = '0%'
|
|
||||||
|
|
||||||
snap_ref_progress_50p = snap_ref_progress.copy()
|
|
||||||
snap_ref_progress_50p['progress'] = '50%'
|
|
||||||
|
|
||||||
snap_ref_progress_90p = snap_ref_progress.copy()
|
|
||||||
snap_ref_progress_90p['progress'] = '90%'
|
|
||||||
|
|
||||||
mock_snapshot_get.side_effect = [
|
|
||||||
snap_ref_progress_0p, snap_ref_progress_50p,
|
|
||||||
snap_ref_progress_90p
|
|
||||||
]
|
|
||||||
|
|
||||||
drv._create_snapshot_online(snap_ref, snap_file, snap_path)
|
drv._create_snapshot_online(snap_ref, snap_file, snap_path)
|
||||||
mock_do_create_snapshot.\
|
mock_do_create_snapshot.\
|
||||||
@ -999,7 +986,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
drv = self._driver
|
drv = self._driver
|
||||||
|
|
||||||
volume = self._simple_volume()
|
volume = self._simple_volume()
|
||||||
volume['status'] = 'in-use'
|
volume.status = 'in-use'
|
||||||
|
|
||||||
hashed = drv._get_hash_str(self.TEST_EXPORT1)
|
hashed = drv._get_hash_str(self.TEST_EXPORT1)
|
||||||
volume_file = 'volume-%s' % self.VOLUME_UUID
|
volume_file = 'volume-%s' % self.VOLUME_UUID
|
||||||
@ -1009,11 +996,12 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
ctxt = context.RequestContext('fake_user', 'fake_project')
|
ctxt = context.RequestContext('fake_user', 'fake_project')
|
||||||
|
|
||||||
snap_ref = {'name': 'test snap (online)',
|
snap_ref = fake_snapshot.fake_snapshot_obj(
|
||||||
'volume_id': self.VOLUME_UUID,
|
ctxt,
|
||||||
'volume': volume,
|
display_name='test snap (online)',
|
||||||
'id': self.SNAP_UUID,
|
volume_id=self.VOLUME_UUID,
|
||||||
'context': ctxt}
|
id=self.SNAP_UUID)
|
||||||
|
snap_ref.context = ctxt
|
||||||
|
|
||||||
snap_path = '%s.%s' % (volume_path, self.SNAP_UUID)
|
snap_path = '%s.%s' % (volume_path, self.SNAP_UUID)
|
||||||
snap_file = '%s.%s' % (volume_file, self.SNAP_UUID)
|
snap_file = '%s.%s' % (volume_file, self.SNAP_UUID)
|
||||||
@ -1022,23 +1010,11 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
mock.patch.object(db, 'snapshot_get') as mock_snapshot_get,\
|
mock.patch.object(db, 'snapshot_get') as mock_snapshot_get,\
|
||||||
mock.patch.object(drv, '_nova') as mock_nova,\
|
mock.patch.object(drv, '_nova') as mock_nova,\
|
||||||
mock.patch.object(time, 'sleep') as mock_sleep:
|
mock.patch.object(time, 'sleep') as mock_sleep:
|
||||||
snap_ref_progress = snap_ref.copy()
|
|
||||||
snap_ref_progress['status'] = fields.SnapshotStatus.CREATING
|
|
||||||
|
|
||||||
snap_ref_progress_0p = snap_ref_progress.copy()
|
mock_snapshot_get.side_effect = SideEffectList(
|
||||||
snap_ref_progress_0p['progress'] = '0%'
|
snap_ref,
|
||||||
|
progress = ['0%', '50%', '99%'],
|
||||||
snap_ref_progress_50p = snap_ref_progress.copy()
|
status = ["creating", "creating", "error"])
|
||||||
snap_ref_progress_50p['progress'] = '50%'
|
|
||||||
|
|
||||||
snap_ref_progress_99p = snap_ref_progress.copy()
|
|
||||||
snap_ref_progress_99p['progress'] = '99%'
|
|
||||||
snap_ref_progress_99p['status'] = fields.SnapshotStatus.ERROR
|
|
||||||
|
|
||||||
mock_snapshot_get.side_effect = [
|
|
||||||
snap_ref_progress_0p, snap_ref_progress_50p,
|
|
||||||
snap_ref_progress_99p
|
|
||||||
]
|
|
||||||
|
|
||||||
self.assertRaisesAndMessageMatches(
|
self.assertRaisesAndMessageMatches(
|
||||||
exception.RemoteFSException,
|
exception.RemoteFSException,
|
||||||
@ -1054,15 +1030,19 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
drv = self._driver
|
drv = self._driver
|
||||||
|
|
||||||
volume = self._simple_volume()
|
volume = self._simple_volume()
|
||||||
volume['status'] = 'in-use'
|
volume.status = 'in-use'
|
||||||
|
|
||||||
ctxt = context.RequestContext('fake_user', 'fake_project')
|
ctxt = context.RequestContext('fake_user', 'fake_project')
|
||||||
|
|
||||||
snap_ref = {'name': 'test snap to delete (online)',
|
snap_ref = fake_snapshot.fake_snapshot_obj(
|
||||||
'volume_id': self.VOLUME_UUID,
|
ctxt,
|
||||||
'volume': volume,
|
display_name='test snap to delete (online)',
|
||||||
'id': self.SNAP_UUID,
|
volume_id=self.VOLUME_UUID,
|
||||||
'context': ctxt}
|
status="deleting",
|
||||||
|
id=self.SNAP_UUID)
|
||||||
|
snap_ref.context = ctxt
|
||||||
|
|
||||||
|
snap_ref.volume = volume
|
||||||
|
|
||||||
hashed = drv._get_hash_str(self.TEST_EXPORT1)
|
hashed = drv._get_hash_str(self.TEST_EXPORT1)
|
||||||
volume_file = 'volume-%s' % self.VOLUME_UUID
|
volume_file = 'volume-%s' % self.VOLUME_UUID
|
||||||
@ -1120,22 +1100,8 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
'volume_id': self.VOLUME_UUID
|
'volume_id': self.VOLUME_UUID
|
||||||
}
|
}
|
||||||
|
|
||||||
snap_ref_progress = snap_ref.copy()
|
mock_snapshot_get.side_effect = SideEffectList(
|
||||||
snap_ref_progress['status'] = 'deleting'
|
snap_ref, progress = ['0%', '50%', '90%'])
|
||||||
|
|
||||||
snap_ref_progress_0p = snap_ref_progress.copy()
|
|
||||||
snap_ref_progress_0p['progress'] = '0%'
|
|
||||||
|
|
||||||
snap_ref_progress_50p = snap_ref_progress.copy()
|
|
||||||
snap_ref_progress_50p['progress'] = '50%'
|
|
||||||
|
|
||||||
snap_ref_progress_90p = snap_ref_progress.copy()
|
|
||||||
snap_ref_progress_90p['progress'] = '90%'
|
|
||||||
|
|
||||||
mock_snapshot_get.side_effect = [
|
|
||||||
snap_ref_progress_0p, snap_ref_progress_50p,
|
|
||||||
snap_ref_progress_90p
|
|
||||||
]
|
|
||||||
|
|
||||||
drv.delete_snapshot(snap_ref)
|
drv.delete_snapshot(snap_ref)
|
||||||
|
|
||||||
@ -1156,15 +1122,18 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
drv = self._driver
|
drv = self._driver
|
||||||
|
|
||||||
volume = self._simple_volume()
|
volume = self._simple_volume()
|
||||||
volume['status'] = 'in-use'
|
volume.status = 'in-use'
|
||||||
|
|
||||||
ctxt = context.RequestContext('fake_user', 'fake_project')
|
ctxt = context.RequestContext('fake_user', 'fake_project')
|
||||||
|
|
||||||
snap_ref = {'name': 'test snap to delete (online)',
|
snap_ref = fake_snapshot.fake_snapshot_obj(
|
||||||
'volume_id': self.VOLUME_UUID,
|
ctxt,
|
||||||
'volume': volume,
|
display_name='test snap to delete (online)',
|
||||||
'id': self.SNAP_UUID,
|
volume_id=self.VOLUME_UUID,
|
||||||
'context': ctxt}
|
status='deleting',
|
||||||
|
id=self.SNAP_UUID)
|
||||||
|
snap_ref.volume = volume
|
||||||
|
snap_ref.context = ctxt
|
||||||
|
|
||||||
hashed = drv._get_hash_str(self.TEST_EXPORT1)
|
hashed = drv._get_hash_str(self.TEST_EXPORT1)
|
||||||
volume_file = 'volume-%s' % self.VOLUME_UUID
|
volume_file = 'volume-%s' % self.VOLUME_UUID
|
||||||
@ -1225,21 +1194,8 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
'file_to_merge': snap_file,
|
'file_to_merge': snap_file,
|
||||||
'volume_id': self.VOLUME_UUID}
|
'volume_id': self.VOLUME_UUID}
|
||||||
|
|
||||||
snap_ref_progress = snap_ref.copy()
|
mock_snapshot_get.side_effect = SideEffectList(
|
||||||
snap_ref_progress['status'] = 'deleting'
|
snap_ref, progress = ['0%', '50%', '90%'])
|
||||||
|
|
||||||
snap_ref_progress_0p = snap_ref_progress.copy()
|
|
||||||
snap_ref_progress_0p['progress'] = '0%'
|
|
||||||
|
|
||||||
snap_ref_progress_50p = snap_ref_progress.copy()
|
|
||||||
snap_ref_progress_50p['progress'] = '50%'
|
|
||||||
|
|
||||||
snap_ref_progress_90p = snap_ref_progress.copy()
|
|
||||||
snap_ref_progress_90p['progress'] = '90%'
|
|
||||||
|
|
||||||
mock_snapshot_get.side_effect = [
|
|
||||||
snap_ref_progress_0p, snap_ref_progress_50p,
|
|
||||||
snap_ref_progress_90p]
|
|
||||||
|
|
||||||
drv.delete_snapshot(snap_ref)
|
drv.delete_snapshot(snap_ref)
|
||||||
|
|
||||||
@ -1260,15 +1216,17 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
drv = self._driver
|
drv = self._driver
|
||||||
|
|
||||||
volume = self._simple_volume()
|
volume = self._simple_volume()
|
||||||
volume['status'] = 'in-use'
|
volume.status = 'in-use'
|
||||||
|
|
||||||
ctxt = context.RequestContext('fake_user', 'fake_project')
|
ctxt = context.RequestContext('fake_user', 'fake_project')
|
||||||
|
|
||||||
snap_ref = {'name': 'test snap to delete (online)',
|
snap_ref = fake_snapshot.fake_snapshot_obj(
|
||||||
'volume_id': self.VOLUME_UUID,
|
ctxt,
|
||||||
'volume': volume,
|
display_name='test snap to delete (online)',
|
||||||
'id': self.SNAP_UUID,
|
volume_id=self.VOLUME_UUID,
|
||||||
'context': ctxt}
|
id=self.SNAP_UUID)
|
||||||
|
snap_ref.volume = volume
|
||||||
|
snap_ref.context = ctxt
|
||||||
|
|
||||||
hashed = drv._get_hash_str(self.TEST_EXPORT1)
|
hashed = drv._get_hash_str(self.TEST_EXPORT1)
|
||||||
volume_file = 'volume-%s' % self.VOLUME_UUID
|
volume_file = 'volume-%s' % self.VOLUME_UUID
|
||||||
@ -1320,23 +1278,10 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
return paths[args[0]]
|
return paths[args[0]]
|
||||||
|
|
||||||
mock_qemu_img_info.side_effect = img_info_side_effect
|
mock_qemu_img_info.side_effect = img_info_side_effect
|
||||||
|
mock_snapshot_get.side_effect = SideEffectList(
|
||||||
snap_ref_progress = snap_ref.copy()
|
snap_ref,
|
||||||
snap_ref_progress['status'] = 'deleting'
|
progress = ['0%', '50%', '99%'],
|
||||||
|
status = ['deleting', 'deleting', 'error'])
|
||||||
snap_ref_progress_0p = snap_ref_progress.copy()
|
|
||||||
snap_ref_progress_0p['progress'] = '0%'
|
|
||||||
|
|
||||||
snap_ref_progress_50p = snap_ref_progress.copy()
|
|
||||||
snap_ref_progress_50p['progress'] = '50%'
|
|
||||||
|
|
||||||
snap_ref_progress_90p = snap_ref_progress.copy()
|
|
||||||
snap_ref_progress_90p['status'] = 'error_deleting'
|
|
||||||
snap_ref_progress_90p['progress'] = '90%'
|
|
||||||
|
|
||||||
mock_snapshot_get.side_effect = [
|
|
||||||
snap_ref_progress_0p, snap_ref_progress_50p,
|
|
||||||
snap_ref_progress_90p]
|
|
||||||
self.assertRaisesAndMessageMatches(exception.RemoteFSException,
|
self.assertRaisesAndMessageMatches(exception.RemoteFSException,
|
||||||
'Unable to delete snapshot',
|
'Unable to delete snapshot',
|
||||||
drv.delete_snapshot,
|
drv.delete_snapshot,
|
||||||
@ -1355,9 +1300,9 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
self.TEST_MNT_POINT_BASE)
|
self.TEST_MNT_POINT_BASE)
|
||||||
|
|
||||||
volume = self._simple_volume()
|
volume = self._simple_volume()
|
||||||
vol_filename = volume['name']
|
vol_filename = volume.name
|
||||||
vol_filename_2 = volume['name'] + '.abcd'
|
vol_filename_2 = volume.name + '.abcd'
|
||||||
vol_filename_3 = volume['name'] + '.efef'
|
vol_filename_3 = volume.name + '.efef'
|
||||||
hashed = drv._get_hash_str(self.TEST_EXPORT1)
|
hashed = drv._get_hash_str(self.TEST_EXPORT1)
|
||||||
vol_dir = '%s/%s' % (self.TEST_MNT_POINT_BASE, hashed)
|
vol_dir = '%s/%s' % (self.TEST_MNT_POINT_BASE, hashed)
|
||||||
vol_path = '%s/%s' % (vol_dir, vol_filename)
|
vol_path = '%s/%s' % (vol_dir, vol_filename)
|
||||||
@ -1432,25 +1377,29 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
vol_dir = os.path.join(self.TEST_MNT_POINT_BASE,
|
vol_dir = os.path.join(self.TEST_MNT_POINT_BASE,
|
||||||
drv._get_hash_str(self.TEST_EXPORT1))
|
drv._get_hash_str(self.TEST_EXPORT1))
|
||||||
src_vol_path = os.path.join(vol_dir, src_volume['name'])
|
src_vol_path = os.path.join(vol_dir, src_volume.name)
|
||||||
dest_vol_path = os.path.join(vol_dir, dest_volume['name'])
|
dest_vol_path = os.path.join(vol_dir, dest_volume.name)
|
||||||
snapshot = {'volume_name': src_volume['name'],
|
|
||||||
'name': 'clone-snap-%s' % src_volume['id'],
|
snapshot = fake_snapshot.fake_snapshot_obj(
|
||||||
'size': src_volume['size'],
|
self.context,
|
||||||
'volume_size': src_volume['size'],
|
volume_name=src_volume.name,
|
||||||
'volume_id': src_volume['id'],
|
display_name='clone-snap-%s' % src_volume.id,
|
||||||
'id': 'tmp-snap-%s' % src_volume['id'],
|
size=src_volume.size,
|
||||||
'volume': src_volume}
|
volume_size=src_volume.size,
|
||||||
snap_file = dest_volume['name'] + '.' + snapshot['id']
|
volume_id=src_volume.id,
|
||||||
size = dest_volume['size']
|
id=self.SNAP_UUID)
|
||||||
|
snapshot.volume = src_volume
|
||||||
|
|
||||||
|
snap_file = dest_volume.name + '.' + snapshot.id
|
||||||
|
size = dest_volume.size
|
||||||
mock_read_info_file.return_value = {'active': snap_file,
|
mock_read_info_file.return_value = {'active': snap_file,
|
||||||
snapshot['id']: snap_file}
|
snapshot.id: snap_file}
|
||||||
qemu_img_output = """image: %s
|
qemu_img_output = """image: %s
|
||||||
file format: raw
|
file format: raw
|
||||||
virtual size: 1.0G (1073741824 bytes)
|
virtual size: 1.0G (1073741824 bytes)
|
||||||
disk size: 173K
|
disk size: 173K
|
||||||
backing file: %s
|
backing file: %s
|
||||||
""" % (snap_file, src_volume['name'])
|
""" % (snap_file, src_volume.name)
|
||||||
img_info = imageutils.QemuImgInfo(qemu_img_output)
|
img_info = imageutils.QemuImgInfo(qemu_img_output)
|
||||||
mock_qemu_img_info.return_value = img_info
|
mock_qemu_img_info.return_value = img_info
|
||||||
|
|
||||||
@ -1464,18 +1413,20 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
drv = self._driver
|
drv = self._driver
|
||||||
|
|
||||||
src_volume = self._simple_volume()
|
src_volume = self._simple_volume()
|
||||||
snap_ref = {'volume_name': src_volume['name'],
|
snap_ref = fake_snapshot.fake_snapshot_obj(
|
||||||
'name': 'clone-snap-%s' % src_volume['id'],
|
self.context,
|
||||||
'size': src_volume['size'],
|
volume_name=src_volume.name,
|
||||||
'volume_size': src_volume['size'],
|
display_name='clone-snap-%s' % src_volume.id,
|
||||||
'volume_id': src_volume['id'],
|
size=src_volume.size,
|
||||||
'id': 'tmp-snap-%s' % src_volume['id'],
|
volume_size=src_volume.size,
|
||||||
'volume': src_volume,
|
volume_id=src_volume.id,
|
||||||
'status': 'available'}
|
id=self.SNAP_UUID,
|
||||||
|
status='available')
|
||||||
|
snap_ref.volume = src_volume
|
||||||
|
|
||||||
new_volume = DumbVolume()
|
new_volume = fake_volume.fake_volume_obj(self.context,
|
||||||
new_volume['id'] = self.VOLUME_UUID
|
id=self.VOLUME_UUID,
|
||||||
new_volume['size'] = snap_ref['size']
|
size=snap_ref.volume.size)
|
||||||
|
|
||||||
with mock.patch.object(drv, '_ensure_shares_mounted') as \
|
with mock.patch.object(drv, '_ensure_shares_mounted') as \
|
||||||
mock_ensure_shares_mounted,\
|
mock_ensure_shares_mounted,\
|
||||||
@ -1492,7 +1443,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
mock_do_create_volume.assert_called_once_with(new_volume)
|
mock_do_create_volume.assert_called_once_with(new_volume)
|
||||||
mock_copy_volume.assert_called_once_with(snap_ref,
|
mock_copy_volume.assert_called_once_with(snap_ref,
|
||||||
new_volume,
|
new_volume,
|
||||||
new_volume['size'])
|
new_volume.size)
|
||||||
|
|
||||||
def test_initialize_connection(self):
|
def test_initialize_connection(self):
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
@ -1502,14 +1453,14 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
file format: raw
|
file format: raw
|
||||||
virtual size: 1.0G (1073741824 bytes)
|
virtual size: 1.0G (1073741824 bytes)
|
||||||
disk size: 173K
|
disk size: 173K
|
||||||
""" % volume['name']
|
""" % volume.name
|
||||||
img_info = imageutils.QemuImgInfo(qemu_img_output)
|
img_info = imageutils.QemuImgInfo(qemu_img_output)
|
||||||
|
|
||||||
with mock.patch.object(drv, 'get_active_image_from_info') as \
|
with mock.patch.object(drv, 'get_active_image_from_info') as \
|
||||||
mock_get_active_image_from_info,\
|
mock_get_active_image_from_info,\
|
||||||
mock.patch.object(image_utils, 'qemu_img_info') as \
|
mock.patch.object(image_utils, 'qemu_img_info') as \
|
||||||
mock_qemu_img_info:
|
mock_qemu_img_info:
|
||||||
mock_get_active_image_from_info.return_value = volume['name']
|
mock_get_active_image_from_info.return_value = volume.name
|
||||||
mock_qemu_img_info.return_value = img_info
|
mock_qemu_img_info.return_value = img_info
|
||||||
|
|
||||||
conn_info = drv.initialize_connection(volume, None)
|
conn_info = drv.initialize_connection(volume, None)
|
||||||
@ -1539,7 +1490,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
mock_backup_volume:
|
mock_backup_volume:
|
||||||
ctxt = context.RequestContext('fake_user', 'fake_project')
|
ctxt = context.RequestContext('fake_user', 'fake_project')
|
||||||
volume = self._simple_volume()
|
volume = self._simple_volume()
|
||||||
backup = {'volume_id': volume['id']}
|
backup = {'volume_id': volume.id}
|
||||||
mock_volume_get.return_value = volume
|
mock_volume_get.return_value = volume
|
||||||
mock_get_active_image_from_info.return_value = '/some/path'
|
mock_get_active_image_from_info.return_value = '/some/path'
|
||||||
|
|
||||||
@ -1566,7 +1517,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
mock_backup_volume:
|
mock_backup_volume:
|
||||||
ctxt = context.RequestContext('fake_user', 'fake_project')
|
ctxt = context.RequestContext('fake_user', 'fake_project')
|
||||||
volume = self._simple_volume()
|
volume = self._simple_volume()
|
||||||
backup = {'volume_id': volume['id']}
|
backup = {'volume_id': volume.id}
|
||||||
mock_volume_get.return_value = volume
|
mock_volume_get.return_value = volume
|
||||||
mock_get_active_image_from_info.return_value = '/some/file2'
|
mock_get_active_image_from_info.return_value = '/some/file2'
|
||||||
|
|
||||||
@ -1586,7 +1537,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
mock_snapshot_get_all_for_volume:
|
mock_snapshot_get_all_for_volume:
|
||||||
ctxt = context.RequestContext('fake_user', 'fake_project')
|
ctxt = context.RequestContext('fake_user', 'fake_project')
|
||||||
volume = self._simple_volume()
|
volume = self._simple_volume()
|
||||||
backup = {'volume_id': volume['id']}
|
backup = {'volume_id': volume.id}
|
||||||
mock_snapshot_get_all_for_volume.return_value = [
|
mock_snapshot_get_all_for_volume.return_value = [
|
||||||
{'snap1': 'a'},
|
{'snap1': 'a'},
|
||||||
{'snap2': 'b'}
|
{'snap2': 'b'}
|
||||||
@ -1606,7 +1557,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
mock_qemu_img_info:
|
mock_qemu_img_info:
|
||||||
ctxt = context.RequestContext('fake_user', 'fake_project')
|
ctxt = context.RequestContext('fake_user', 'fake_project')
|
||||||
volume = self._simple_volume()
|
volume = self._simple_volume()
|
||||||
backup = {'volume_id': volume['id']}
|
backup = {'volume_id': volume.id}
|
||||||
mock_volume_get.return_value = volume
|
mock_volume_get.return_value = volume
|
||||||
mock_get_active_image_from_info.return_value = '/some/path/file2'
|
mock_get_active_image_from_info.return_value = '/some/path/file2'
|
||||||
|
|
||||||
@ -1629,7 +1580,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
mock.patch.object(drv, '_qemu_img_info') as mock_qemu_img_info:
|
mock.patch.object(drv, '_qemu_img_info') as mock_qemu_img_info:
|
||||||
ctxt = context.RequestContext('fake_user', 'fake_project')
|
ctxt = context.RequestContext('fake_user', 'fake_project')
|
||||||
volume = self._simple_volume()
|
volume = self._simple_volume()
|
||||||
backup = {'volume_id': volume['id']}
|
backup = {'volume_id': volume.id}
|
||||||
mock_volume_get.return_value = volume
|
mock_volume_get.return_value = volume
|
||||||
mock_get_active_image_from_info.return_value = '/some/path'
|
mock_get_active_image_from_info.return_value = '/some/path'
|
||||||
|
|
||||||
@ -1651,7 +1602,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
drv = self._driver
|
drv = self._driver
|
||||||
|
|
||||||
volume = self._simple_volume()
|
volume = self._simple_volume()
|
||||||
volume_path = '%s/%s' % (self.TEST_MNT_POINT, volume['name'])
|
volume_path = '%s/%s' % (self.TEST_MNT_POINT, volume.name)
|
||||||
image_meta = {'id': '10958016-e196-42e3-9e7f-5d8927ae3099'}
|
image_meta = {'id': '10958016-e196-42e3-9e7f-5d8927ae3099'}
|
||||||
|
|
||||||
with mock.patch.object(drv, 'get_active_image_from_info') as \
|
with mock.patch.object(drv, 'get_active_image_from_info') as \
|
||||||
@ -1664,7 +1615,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
mock_upload_volume, \
|
mock_upload_volume, \
|
||||||
mock.patch.object(image_utils, 'create_temporary_file') as \
|
mock.patch.object(image_utils, 'create_temporary_file') as \
|
||||||
mock_create_temporary_file:
|
mock_create_temporary_file:
|
||||||
mock_get_active_image_from_info.return_value = volume['name']
|
mock_get_active_image_from_info.return_value = volume.name
|
||||||
|
|
||||||
mock_local_volume_dir.return_value = self.TEST_MNT_POINT
|
mock_local_volume_dir.return_value = self.TEST_MNT_POINT
|
||||||
|
|
||||||
@ -1674,7 +1625,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
file format: raw
|
file format: raw
|
||||||
virtual size: 1.0G (1073741824 bytes)
|
virtual size: 1.0G (1073741824 bytes)
|
||||||
disk size: 173K
|
disk size: 173K
|
||||||
""" % volume['name']
|
""" % volume.name
|
||||||
img_info = imageutils.QemuImgInfo(qemu_img_output)
|
img_info = imageutils.QemuImgInfo(qemu_img_output)
|
||||||
mock_qemu_img_info.return_value = img_info
|
mock_qemu_img_info.return_value = img_info
|
||||||
|
|
||||||
@ -1694,7 +1645,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
drv = self._driver
|
drv = self._driver
|
||||||
|
|
||||||
volume = self._simple_volume()
|
volume = self._simple_volume()
|
||||||
volume_path = '%s/%s' % (self.TEST_MNT_POINT, volume['name'])
|
volume_path = '%s/%s' % (self.TEST_MNT_POINT, volume.name)
|
||||||
image_meta = {'id': '10958016-e196-42e3-9e7f-5d8927ae3099'}
|
image_meta = {'id': '10958016-e196-42e3-9e7f-5d8927ae3099'}
|
||||||
|
|
||||||
with mock.patch.object(drv, 'get_active_image_from_info') as \
|
with mock.patch.object(drv, 'get_active_image_from_info') as \
|
||||||
@ -1709,7 +1660,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
mock_upload_volume, \
|
mock_upload_volume, \
|
||||||
mock.patch.object(image_utils, 'create_temporary_file') as \
|
mock.patch.object(image_utils, 'create_temporary_file') as \
|
||||||
mock_create_temporary_file:
|
mock_create_temporary_file:
|
||||||
mock_get_active_image_from_info.return_value = volume['name']
|
mock_get_active_image_from_info.return_value = volume.name
|
||||||
|
|
||||||
mock_local_volume_dir.return_value = self.TEST_MNT_POINT
|
mock_local_volume_dir.return_value = self.TEST_MNT_POINT
|
||||||
|
|
||||||
@ -1719,7 +1670,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
file format: qcow2
|
file format: qcow2
|
||||||
virtual size: 1.0G (1073741824 bytes)
|
virtual size: 1.0G (1073741824 bytes)
|
||||||
disk size: 173K
|
disk size: 173K
|
||||||
""" % volume['name']
|
""" % volume.name
|
||||||
img_info = imageutils.QemuImgInfo(qemu_img_output)
|
img_info = imageutils.QemuImgInfo(qemu_img_output)
|
||||||
mock_qemu_img_info.return_value = img_info
|
mock_qemu_img_info.return_value = img_info
|
||||||
|
|
||||||
@ -1757,7 +1708,7 @@ class GlusterFsDriverTestCase(test.TestCase):
|
|||||||
mock_upload_volume, \
|
mock_upload_volume, \
|
||||||
mock.patch.object(image_utils, 'create_temporary_file') as \
|
mock.patch.object(image_utils, 'create_temporary_file') as \
|
||||||
mock_create_temporary_file:
|
mock_create_temporary_file:
|
||||||
mock_get_active_image_from_info.return_value = volume['name']
|
mock_get_active_image_from_info.return_value = volume.name
|
||||||
|
|
||||||
mock_local_volume_dir.return_value = self.TEST_MNT_POINT
|
mock_local_volume_dir.return_value = self.TEST_MNT_POINT
|
||||||
|
|
||||||
|
@ -23,9 +23,11 @@ import mock
|
|||||||
from mox3 import mox as mox_lib
|
from mox3 import mox as mox_lib
|
||||||
import six
|
import six
|
||||||
|
|
||||||
|
from cinder import context
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.image import image_utils
|
from cinder.image import image_utils
|
||||||
from cinder import test
|
from cinder import test
|
||||||
|
from cinder.tests.unit import fake_volume
|
||||||
from cinder import utils as cinder_utils
|
from cinder import utils as cinder_utils
|
||||||
from cinder.volume import configuration as conf
|
from cinder.volume import configuration as conf
|
||||||
from cinder.volume.drivers.netapp import common
|
from cinder.volume.drivers.netapp import common
|
||||||
@ -158,6 +160,7 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
|||||||
self._driver.ssc_library = mock.Mock()
|
self._driver.ssc_library = mock.Mock()
|
||||||
config = self._driver.configuration
|
config = self._driver.configuration
|
||||||
config.netapp_vserver = FAKE_VSERVER
|
config.netapp_vserver = FAKE_VSERVER
|
||||||
|
self.context = context.get_admin_context()
|
||||||
|
|
||||||
def test_create_snapshot(self):
|
def test_create_snapshot(self):
|
||||||
"""Test snapshot can be created and deleted."""
|
"""Test snapshot can be created and deleted."""
|
||||||
@ -519,7 +522,8 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
|||||||
def test_clone_image_cloneableshare_raw(self):
|
def test_clone_image_cloneableshare_raw(self):
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
mox = self.mox
|
mox = self.mox
|
||||||
volume = {'name': 'vol', 'size': '20'}
|
volume = fake_volume.fake_volume_obj(self.context, size=20)
|
||||||
|
volume_name = 'volume-%s' % volume.id
|
||||||
mox.StubOutWithMock(utils, 'get_volume_extra_specs')
|
mox.StubOutWithMock(utils, 'get_volume_extra_specs')
|
||||||
mox.StubOutWithMock(drv, '_find_image_in_cache')
|
mox.StubOutWithMock(drv, '_find_image_in_cache')
|
||||||
mox.StubOutWithMock(drv, '_is_cloneable_share')
|
mox.StubOutWithMock(drv, '_is_cloneable_share')
|
||||||
@ -541,11 +545,11 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
|||||||
image_utils.qemu_img_info('/mnt/img-id', run_as_root=True).\
|
image_utils.qemu_img_info('/mnt/img-id', run_as_root=True).\
|
||||||
AndReturn(self.get_img_info('raw'))
|
AndReturn(self.get_img_info('raw'))
|
||||||
drv._clone_backing_file_for_volume(
|
drv._clone_backing_file_for_volume(
|
||||||
'img-id', 'vol', share='127.0.0.1:/share', volume_id=None)
|
'img-id', volume_name, share='127.0.0.1:/share', volume_id=None)
|
||||||
drv._get_mount_point_for_share(mox_lib.IgnoreArg()).AndReturn('/mnt')
|
drv._get_mount_point_for_share(mox_lib.IgnoreArg()).AndReturn('/mnt')
|
||||||
drv._discover_file_till_timeout(mox_lib.IgnoreArg()).AndReturn(True)
|
drv._discover_file_till_timeout(mox_lib.IgnoreArg()).AndReturn(True)
|
||||||
drv._set_rw_permissions('/mnt/vol')
|
drv._set_rw_permissions('/mnt/%s' % volume_name)
|
||||||
drv._resize_image_file({'name': 'vol'}, mox_lib.IgnoreArg())
|
drv._resize_image_file({'name': volume_name}, mox_lib.IgnoreArg())
|
||||||
|
|
||||||
mox.ReplayAll()
|
mox.ReplayAll()
|
||||||
drv.clone_image(
|
drv.clone_image(
|
||||||
@ -559,7 +563,8 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
|||||||
def test_clone_image_cloneableshare_notraw(self):
|
def test_clone_image_cloneableshare_notraw(self):
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
mox = self.mox
|
mox = self.mox
|
||||||
volume = {'name': 'vol', 'size': '20'}
|
volume = fake_volume.fake_volume_obj(self.context, size=20)
|
||||||
|
volume_name = 'volume-%s' % volume.id
|
||||||
mox.StubOutWithMock(utils, 'get_volume_extra_specs')
|
mox.StubOutWithMock(utils, 'get_volume_extra_specs')
|
||||||
mox.StubOutWithMock(drv, '_find_image_in_cache')
|
mox.StubOutWithMock(drv, '_find_image_in_cache')
|
||||||
mox.StubOutWithMock(drv, '_is_cloneable_share')
|
mox.StubOutWithMock(drv, '_is_cloneable_share')
|
||||||
@ -572,6 +577,7 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
|||||||
mox.StubOutWithMock(image_utils, 'convert_image')
|
mox.StubOutWithMock(image_utils, 'convert_image')
|
||||||
mox.StubOutWithMock(drv, '_register_image_in_cache')
|
mox.StubOutWithMock(drv, '_register_image_in_cache')
|
||||||
mox.StubOutWithMock(drv, '_is_share_clone_compatible')
|
mox.StubOutWithMock(drv, '_is_share_clone_compatible')
|
||||||
|
mox.StubOutWithMock(drv, '_do_qos_for_volume')
|
||||||
|
|
||||||
utils.get_volume_extra_specs(mox_lib.IgnoreArg())
|
utils.get_volume_extra_specs(mox_lib.IgnoreArg())
|
||||||
drv._find_image_in_cache(mox_lib.IgnoreArg()).AndReturn([])
|
drv._find_image_in_cache(mox_lib.IgnoreArg()).AndReturn([])
|
||||||
@ -585,13 +591,15 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
|||||||
image_utils.convert_image(mox_lib.IgnoreArg(),
|
image_utils.convert_image(mox_lib.IgnoreArg(),
|
||||||
mox_lib.IgnoreArg(),
|
mox_lib.IgnoreArg(),
|
||||||
'raw', run_as_root=True)
|
'raw', run_as_root=True)
|
||||||
image_utils.qemu_img_info('/mnt/vol', run_as_root=True).\
|
image_utils.qemu_img_info('/mnt/%s' % volume_name, run_as_root=True).\
|
||||||
AndReturn(self.get_img_info('raw'))
|
AndReturn(self.get_img_info('raw'))
|
||||||
drv._register_image_in_cache(mox_lib.IgnoreArg(), mox_lib.IgnoreArg())
|
drv._register_image_in_cache(mox_lib.IgnoreArg(), mox_lib.IgnoreArg())
|
||||||
|
drv._do_qos_for_volume(mox_lib.IgnoreArg(), mox_lib.IgnoreArg())
|
||||||
|
|
||||||
drv._get_mount_point_for_share('127.0.0.1:/share').AndReturn('/mnt')
|
drv._get_mount_point_for_share('127.0.0.1:/share').AndReturn('/mnt')
|
||||||
drv._discover_file_till_timeout(mox_lib.IgnoreArg()).AndReturn(True)
|
drv._discover_file_till_timeout(mox_lib.IgnoreArg()).AndReturn(True)
|
||||||
drv._set_rw_permissions('/mnt/vol')
|
drv._set_rw_permissions('/mnt/%s' % volume_name)
|
||||||
drv._resize_image_file({'name': 'vol'}, mox_lib.IgnoreArg())
|
drv._resize_image_file({'name': volume_name}, mox_lib.IgnoreArg())
|
||||||
|
|
||||||
mox.ReplayAll()
|
mox.ReplayAll()
|
||||||
drv.clone_image(
|
drv.clone_image(
|
||||||
@ -605,7 +613,8 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
|||||||
def test_clone_image_file_not_discovered(self):
|
def test_clone_image_file_not_discovered(self):
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
mox = self.mox
|
mox = self.mox
|
||||||
volume = {'name': 'vol', 'size': '20'}
|
volume = fake_volume.fake_volume_obj(self.context, size=20)
|
||||||
|
volume_name = 'volume-%s' % volume.id
|
||||||
mox.StubOutWithMock(utils, 'get_volume_extra_specs')
|
mox.StubOutWithMock(utils, 'get_volume_extra_specs')
|
||||||
mox.StubOutWithMock(drv, '_find_image_in_cache')
|
mox.StubOutWithMock(drv, '_find_image_in_cache')
|
||||||
mox.StubOutWithMock(drv, '_is_cloneable_share')
|
mox.StubOutWithMock(drv, '_is_cloneable_share')
|
||||||
@ -631,12 +640,12 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
|||||||
image_utils.convert_image(mox_lib.IgnoreArg(),
|
image_utils.convert_image(mox_lib.IgnoreArg(),
|
||||||
mox_lib.IgnoreArg(),
|
mox_lib.IgnoreArg(),
|
||||||
'raw', run_as_root=True)
|
'raw', run_as_root=True)
|
||||||
image_utils.qemu_img_info('/mnt/vol', run_as_root=True).\
|
image_utils.qemu_img_info('/mnt/%s' % volume_name, run_as_root=True).\
|
||||||
AndReturn(self.get_img_info('raw'))
|
AndReturn(self.get_img_info('raw'))
|
||||||
drv._register_image_in_cache(mox_lib.IgnoreArg(),
|
drv._register_image_in_cache(mox_lib.IgnoreArg(),
|
||||||
mox_lib.IgnoreArg())
|
mox_lib.IgnoreArg())
|
||||||
drv._do_qos_for_volume(mox_lib.IgnoreArg(), mox_lib.IgnoreArg())
|
drv._do_qos_for_volume(mox_lib.IgnoreArg(), mox_lib.IgnoreArg())
|
||||||
drv.local_path(mox_lib.IgnoreArg()).AndReturn('/mnt/vol')
|
drv.local_path(mox_lib.IgnoreArg()).AndReturn('/mnt/%s' % volume_name)
|
||||||
drv._discover_file_till_timeout(mox_lib.IgnoreArg()).AndReturn(False)
|
drv._discover_file_till_timeout(mox_lib.IgnoreArg()).AndReturn(False)
|
||||||
|
|
||||||
mox.ReplayAll()
|
mox.ReplayAll()
|
||||||
@ -1180,6 +1189,8 @@ class NetAppCmodeNfsDriverOnlyTestCase(test.TestCase):
|
|||||||
'spec': None,
|
'spec': None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.context = context.get_admin_context()
|
||||||
|
|
||||||
@mock.patch.object(utils, 'LOG', mock.Mock())
|
@mock.patch.object(utils, 'LOG', mock.Mock())
|
||||||
def test_create_volume(self):
|
def test_create_volume(self):
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
@ -1234,47 +1245,48 @@ class NetAppCmodeNfsDriverOnlyTestCase(test.TestCase):
|
|||||||
|
|
||||||
def test_copy_img_to_vol_copyoffload_success(self):
|
def test_copy_img_to_vol_copyoffload_success(self):
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
context = object()
|
volume = fake_volume.fake_volume_obj(self.context)
|
||||||
volume = {'id': 'vol_id', 'name': 'name'}
|
|
||||||
image_service = object()
|
image_service = object()
|
||||||
image_id = 'image_id'
|
image_id = 'image_id'
|
||||||
drv.zapi_client.get_ontapi_version = mock.Mock(return_value=(1, 20))
|
drv.zapi_client.get_ontapi_version = mock.Mock(return_value=(1, 20))
|
||||||
drv._copy_from_img_service = mock.Mock()
|
drv._copy_from_img_service = mock.Mock()
|
||||||
drv._get_provider_location = mock.Mock(return_value='share')
|
drv._get_provider_location = mock.Mock(return_value='share')
|
||||||
drv._get_vol_for_share = mock.Mock(return_value='vol')
|
drv._get_vol_for_share = mock.Mock(return_value=volume.id)
|
||||||
drv._update_stale_vols = mock.Mock()
|
drv._update_stale_vols = mock.Mock()
|
||||||
|
|
||||||
drv.copy_image_to_volume(context, volume, image_service, image_id)
|
drv.copy_image_to_volume(self.context, volume, image_service, image_id)
|
||||||
drv._copy_from_img_service.assert_called_once_with(context, volume,
|
drv._copy_from_img_service.assert_called_once_with(self.context,
|
||||||
|
volume,
|
||||||
image_service,
|
image_service,
|
||||||
image_id)
|
image_id)
|
||||||
drv._update_stale_vols.assert_called_once_with('vol')
|
drv._update_stale_vols.assert_called_once_with(volume.id)
|
||||||
|
|
||||||
def test_copy_img_to_vol_copyoffload_failure(self):
|
def test_copy_img_to_vol_copyoffload_failure(self):
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
context = object()
|
volume = fake_volume.fake_volume_obj(self.context)
|
||||||
volume = {'id': 'vol_id', 'name': 'name'}
|
|
||||||
image_service = object()
|
image_service = object()
|
||||||
image_id = 'image_id'
|
image_id = 'image_id'
|
||||||
drv.zapi_client.get_ontapi_version = mock.Mock(return_value=(1, 20))
|
drv.zapi_client.get_ontapi_version = mock.Mock(return_value=(1, 20))
|
||||||
drv._copy_from_img_service = mock.Mock(side_effect=Exception())
|
drv._copy_from_img_service = mock.Mock(side_effect=Exception())
|
||||||
nfs_base.NetAppNfsDriver.copy_image_to_volume = mock.Mock()
|
nfs_base.NetAppNfsDriver.copy_image_to_volume = mock.Mock()
|
||||||
drv._get_provider_location = mock.Mock(return_value='share')
|
drv._get_provider_location = mock.Mock(return_value='share')
|
||||||
drv._get_vol_for_share = mock.Mock(return_value='vol')
|
drv._get_vol_for_share = mock.Mock(return_value=volume.id)
|
||||||
drv._update_stale_vols = mock.Mock()
|
drv._update_stale_vols = mock.Mock()
|
||||||
|
|
||||||
drv.copy_image_to_volume(context, volume, image_service, image_id)
|
drv.copy_image_to_volume(self.context, volume, image_service, image_id)
|
||||||
drv._copy_from_img_service.assert_called_once_with(context, volume,
|
drv._copy_from_img_service.assert_called_once_with(self.context,
|
||||||
|
volume,
|
||||||
image_service,
|
image_service,
|
||||||
image_id)
|
image_id)
|
||||||
nfs_base.NetAppNfsDriver.copy_image_to_volume. \
|
nfs_base.NetAppNfsDriver.copy_image_to_volume. \
|
||||||
assert_called_once_with(context, volume, image_service, image_id)
|
assert_called_once_with(self.context, volume,
|
||||||
drv._update_stale_vols.assert_called_once_with('vol')
|
image_service, image_id)
|
||||||
|
drv._update_stale_vols.assert_called_once_with(volume.id)
|
||||||
|
|
||||||
def test_copy_img_to_vol_copyoffload_nonexistent_binary_path(self):
|
def test_copy_img_to_vol_copyoffload_nonexistent_binary_path(self):
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
context = object()
|
volume = fake_volume.fake_volume_obj(self.context)
|
||||||
volume = {'id': 'vol_id', 'name': 'name'}
|
|
||||||
image_service = mock.Mock()
|
image_service = mock.Mock()
|
||||||
image_service.get_location.return_value = (mock.Mock(), mock.Mock())
|
image_service.get_location.return_value = (mock.Mock(), mock.Mock())
|
||||||
image_service.show.return_value = {'size': 0}
|
image_service.show.return_value = {'size': 0}
|
||||||
@ -1296,15 +1308,14 @@ class NetAppCmodeNfsDriverOnlyTestCase(test.TestCase):
|
|||||||
|
|
||||||
# Verify the original error is propagated
|
# Verify the original error is propagated
|
||||||
self.assertRaises(OSError, drv._copy_from_img_service,
|
self.assertRaises(OSError, drv._copy_from_img_service,
|
||||||
context, volume, image_service, image_id)
|
self.context, volume, image_service, image_id)
|
||||||
|
|
||||||
@mock.patch.object(image_utils, 'qemu_img_info')
|
@mock.patch.object(image_utils, 'qemu_img_info')
|
||||||
def test_img_service_raw_copyoffload_workflow_success(self,
|
def test_img_service_raw_copyoffload_workflow_success(self,
|
||||||
mock_qemu_img_info):
|
mock_qemu_img_info):
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
volume = {'id': 'vol_id', 'name': 'name', 'size': 1}
|
volume = fake_volume.fake_volume_obj(self.context, size=1)
|
||||||
image_id = 'image_id'
|
image_id = 'image_id'
|
||||||
context = object()
|
|
||||||
image_service = mock.Mock()
|
image_service = mock.Mock()
|
||||||
image_service.get_location.return_value = ('nfs://ip1/openstack/img',
|
image_service.get_location.return_value = ('nfs://ip1/openstack/img',
|
||||||
None)
|
None)
|
||||||
@ -1329,9 +1340,10 @@ class NetAppCmodeNfsDriverOnlyTestCase(test.TestCase):
|
|||||||
drv._clone_file_dst_exists = mock.Mock()
|
drv._clone_file_dst_exists = mock.Mock()
|
||||||
drv._post_clone_image = mock.Mock()
|
drv._post_clone_image = mock.Mock()
|
||||||
|
|
||||||
drv._copy_from_img_service(context, volume, image_service, image_id)
|
drv._copy_from_img_service(self.context, volume,
|
||||||
|
image_service, image_id)
|
||||||
drv._get_ip_verify_on_cluster.assert_any_call('ip1')
|
drv._get_ip_verify_on_cluster.assert_any_call('ip1')
|
||||||
drv._get_export_path.assert_called_with('vol_id')
|
drv._get_export_path.assert_called_with(volume.id)
|
||||||
drv._check_share_can_hold_size.assert_called_with('share', 1)
|
drv._check_share_can_hold_size.assert_called_with('share', 1)
|
||||||
|
|
||||||
assert drv._execute.call_count == 1
|
assert drv._execute.call_count == 1
|
||||||
@ -1344,9 +1356,8 @@ class NetAppCmodeNfsDriverOnlyTestCase(test.TestCase):
|
|||||||
mock_qemu_img_info,
|
mock_qemu_img_info,
|
||||||
mock_cvrt_image):
|
mock_cvrt_image):
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
volume = {'id': 'vol_id', 'name': 'name', 'size': 1}
|
volume = fake_volume.fake_volume_obj(self.context, size=1)
|
||||||
image_id = 'image_id'
|
image_id = 'image_id'
|
||||||
context = object()
|
|
||||||
image_service = mock.Mock()
|
image_service = mock.Mock()
|
||||||
image_service.get_location.return_value = ('nfs://ip1/openstack/img',
|
image_service.get_location.return_value = ('nfs://ip1/openstack/img',
|
||||||
None)
|
None)
|
||||||
@ -1371,9 +1382,10 @@ class NetAppCmodeNfsDriverOnlyTestCase(test.TestCase):
|
|||||||
drv._clone_file_dst_exists = mock.Mock()
|
drv._clone_file_dst_exists = mock.Mock()
|
||||||
drv._post_clone_image = mock.Mock()
|
drv._post_clone_image = mock.Mock()
|
||||||
|
|
||||||
drv._copy_from_img_service(context, volume, image_service, image_id)
|
drv._copy_from_img_service(self.context, volume,
|
||||||
|
image_service, image_id)
|
||||||
drv._get_ip_verify_on_cluster.assert_any_call('ip1')
|
drv._get_ip_verify_on_cluster.assert_any_call('ip1')
|
||||||
drv._get_export_path.assert_called_with('vol_id')
|
drv._get_export_path.assert_called_with(volume.id)
|
||||||
drv._check_share_can_hold_size.assert_called_with('share', 1)
|
drv._check_share_can_hold_size.assert_called_with('share', 1)
|
||||||
assert mock_cvrt_image.call_count == 1
|
assert mock_cvrt_image.call_count == 1
|
||||||
assert drv._execute.call_count == 1
|
assert drv._execute.call_count == 1
|
||||||
@ -1393,6 +1405,7 @@ class NetApp7modeNfsDriverTestCase(NetAppCmodeNfsDriverTestCase):
|
|||||||
self._driver = netapp_nfs_7mode.NetApp7modeNfsDriver(
|
self._driver = netapp_nfs_7mode.NetApp7modeNfsDriver(
|
||||||
configuration=create_configuration())
|
configuration=create_configuration())
|
||||||
self._driver.zapi_client = mock.Mock()
|
self._driver.zapi_client = mock.Mock()
|
||||||
|
self.context = context.get_admin_context()
|
||||||
|
|
||||||
def _prepare_delete_snapshot_mock(self, snapshot_exists):
|
def _prepare_delete_snapshot_mock(self, snapshot_exists):
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
|
@ -21,25 +21,16 @@ import os
|
|||||||
import mock
|
import mock
|
||||||
from oslo_utils import units
|
from oslo_utils import units
|
||||||
|
|
||||||
|
from cinder import context
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.image import image_utils
|
from cinder.image import image_utils
|
||||||
from cinder import test
|
from cinder import test
|
||||||
|
from cinder.tests.unit import fake_volume
|
||||||
from cinder.volume import configuration as conf
|
from cinder.volume import configuration as conf
|
||||||
from cinder.volume.drivers import nfs
|
from cinder.volume.drivers import nfs
|
||||||
from cinder.volume.drivers import remotefs
|
from cinder.volume.drivers import remotefs
|
||||||
|
|
||||||
|
|
||||||
class DumbVolume(object):
|
|
||||||
# TODO(eharney): replace this with an autospecced mock class
|
|
||||||
fields = {}
|
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
|
||||||
self.fields[key] = value
|
|
||||||
|
|
||||||
def __getitem__(self, item):
|
|
||||||
return self.fields[item]
|
|
||||||
|
|
||||||
|
|
||||||
class RemoteFsDriverTestCase(test.TestCase):
|
class RemoteFsDriverTestCase(test.TestCase):
|
||||||
TEST_FILE_NAME = 'test.txt'
|
TEST_FILE_NAME = 'test.txt'
|
||||||
TEST_EXPORT = 'nas-host1:/export'
|
TEST_EXPORT = 'nas-host1:/export'
|
||||||
@ -346,18 +337,19 @@ class NfsDriverTestCase(test.TestCase):
|
|||||||
mock_exc = mock.patch.object(self._driver, '_execute')
|
mock_exc = mock.patch.object(self._driver, '_execute')
|
||||||
self._execute = mock_exc.start()
|
self._execute = mock_exc.start()
|
||||||
self.addCleanup(mock_exc.stop)
|
self.addCleanup(mock_exc.stop)
|
||||||
|
self.context = context.get_admin_context()
|
||||||
|
|
||||||
def test_local_path(self):
|
def test_local_path(self):
|
||||||
"""local_path common use case."""
|
"""local_path common use case."""
|
||||||
self.configuration.nfs_mount_point_base = self.TEST_MNT_POINT_BASE
|
self.configuration.nfs_mount_point_base = self.TEST_MNT_POINT_BASE
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
|
|
||||||
volume = DumbVolume()
|
volume = fake_volume.fake_volume_obj(
|
||||||
volume['provider_location'] = self.TEST_NFS_EXPORT1
|
self.context,
|
||||||
volume['name'] = 'volume-123'
|
provider_location=self.TEST_NFS_EXPORT1)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'/mnt/test/2f4f60214cf43c595666dd815f0360a4/volume-123',
|
'/mnt/test/2f4f60214cf43c595666dd815f0360a4/%s' % volume.name,
|
||||||
drv.local_path(volume))
|
drv.local_path(volume))
|
||||||
|
|
||||||
@mock.patch.object(image_utils, 'qemu_img_info')
|
@mock.patch.object(image_utils, 'qemu_img_info')
|
||||||
@ -366,8 +358,9 @@ class NfsDriverTestCase(test.TestCase):
|
|||||||
def test_copy_image_to_volume(self, mock_fetch, mock_resize, mock_qemu):
|
def test_copy_image_to_volume(self, mock_fetch, mock_resize, mock_qemu):
|
||||||
"""resize_image common case usage."""
|
"""resize_image common case usage."""
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
TEST_IMG_SOURCE = 'foo.img'
|
volume = fake_volume.fake_volume_obj(self.context,
|
||||||
volume = {'size': self.TEST_SIZE_IN_GB, 'name': TEST_IMG_SOURCE}
|
size=self.TEST_SIZE_IN_GB)
|
||||||
|
TEST_IMG_SOURCE = 'volume-%s' % volume.id
|
||||||
|
|
||||||
with mock.patch.object(drv, 'local_path',
|
with mock.patch.object(drv, 'local_path',
|
||||||
return_value=TEST_IMG_SOURCE):
|
return_value=TEST_IMG_SOURCE):
|
||||||
@ -581,12 +574,10 @@ class NfsDriverTestCase(test.TestCase):
|
|||||||
self.assertEqual(2, mock_get_capacity_info.call_count)
|
self.assertEqual(2, mock_get_capacity_info.call_count)
|
||||||
|
|
||||||
def _simple_volume(self):
|
def _simple_volume(self):
|
||||||
volume = DumbVolume()
|
return fake_volume.fake_volume_obj(self.context,
|
||||||
volume['provider_location'] = '127.0.0.1:/mnt'
|
display_name='volume_name',
|
||||||
volume['name'] = 'volume_name'
|
provider_location='127.0.0.1:/mnt',
|
||||||
volume['size'] = 10
|
size=10)
|
||||||
|
|
||||||
return volume
|
|
||||||
|
|
||||||
def test_create_sparsed_volume(self):
|
def test_create_sparsed_volume(self):
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
@ -626,13 +617,14 @@ class NfsDriverTestCase(test.TestCase):
|
|||||||
"""create_volume ensures shares provided in config are mounted."""
|
"""create_volume ensures shares provided in config are mounted."""
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
drv._find_share = mock.Mock()
|
drv._find_share = mock.Mock()
|
||||||
|
drv._find_share.return_value = self.TEST_NFS_EXPORT1
|
||||||
drv._do_create_volume = mock.Mock()
|
drv._do_create_volume = mock.Mock()
|
||||||
|
|
||||||
with mock.patch.object(
|
with mock.patch.object(
|
||||||
drv, '_ensure_share_mounted') as mock_ensure_share:
|
drv, '_ensure_share_mounted') as mock_ensure_share:
|
||||||
drv._ensure_share_mounted()
|
drv._ensure_share_mounted()
|
||||||
volume = DumbVolume()
|
volume = fake_volume.fake_volume_obj(self.context,
|
||||||
volume['size'] = self.TEST_SIZE_IN_GB
|
size=self.TEST_SIZE_IN_GB)
|
||||||
drv.create_volume(volume)
|
drv.create_volume(volume)
|
||||||
|
|
||||||
mock_ensure_share.assert_called_once_with()
|
mock_ensure_share.assert_called_once_with()
|
||||||
@ -646,8 +638,8 @@ class NfsDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
with mock.patch.object(drv, '_find_share') as mock_find_share:
|
with mock.patch.object(drv, '_find_share') as mock_find_share:
|
||||||
mock_find_share.return_value = self.TEST_NFS_EXPORT1
|
mock_find_share.return_value = self.TEST_NFS_EXPORT1
|
||||||
volume = DumbVolume()
|
volume = fake_volume.fake_volume_obj(self.context,
|
||||||
volume['size'] = self.TEST_SIZE_IN_GB
|
size=self.TEST_SIZE_IN_GB)
|
||||||
result = drv.create_volume(volume)
|
result = drv.create_volume(volume)
|
||||||
self.assertEqual(self.TEST_NFS_EXPORT1,
|
self.assertEqual(self.TEST_NFS_EXPORT1,
|
||||||
result['provider_location'])
|
result['provider_location'])
|
||||||
@ -658,9 +650,10 @@ class NfsDriverTestCase(test.TestCase):
|
|||||||
drv = self._driver
|
drv = self._driver
|
||||||
drv._ensure_share_mounted = mock.Mock()
|
drv._ensure_share_mounted = mock.Mock()
|
||||||
|
|
||||||
volume = DumbVolume()
|
volume = fake_volume.fake_volume_obj(
|
||||||
volume['name'] = 'volume-123'
|
self.context,
|
||||||
volume['provider_location'] = self.TEST_NFS_EXPORT1
|
display_name='volume-123',
|
||||||
|
provider_location=self.TEST_NFS_EXPORT1)
|
||||||
|
|
||||||
with mock.patch.object(drv, 'local_path') as mock_local_path:
|
with mock.patch.object(drv, 'local_path') as mock_local_path:
|
||||||
mock_local_path.return_value = self.TEST_LOCAL_PATH
|
mock_local_path.return_value = self.TEST_LOCAL_PATH
|
||||||
@ -673,9 +666,10 @@ class NfsDriverTestCase(test.TestCase):
|
|||||||
def test_delete_should_ensure_share_mounted(self):
|
def test_delete_should_ensure_share_mounted(self):
|
||||||
"""delete_volume should ensure that corresponding share is mounted."""
|
"""delete_volume should ensure that corresponding share is mounted."""
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
volume = DumbVolume()
|
volume = fake_volume.fake_volume_obj(
|
||||||
volume['name'] = 'volume-123'
|
self.context,
|
||||||
volume['provider_location'] = self.TEST_NFS_EXPORT1
|
display_name='volume-123',
|
||||||
|
provider_location=self.TEST_NFS_EXPORT1)
|
||||||
|
|
||||||
with mock.patch.object(
|
with mock.patch.object(
|
||||||
drv, '_ensure_share_mounted') as mock_ensure_share:
|
drv, '_ensure_share_mounted') as mock_ensure_share:
|
||||||
@ -685,9 +679,9 @@ class NfsDriverTestCase(test.TestCase):
|
|||||||
def test_delete_should_not_delete_if_provider_location_not_provided(self):
|
def test_delete_should_not_delete_if_provider_location_not_provided(self):
|
||||||
"""delete_volume shouldn't delete if provider_location missed."""
|
"""delete_volume shouldn't delete if provider_location missed."""
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
volume = DumbVolume()
|
volume = fake_volume.fake_volume_obj(self.context,
|
||||||
volume['name'] = 'volume-123'
|
name='volume-123',
|
||||||
volume['provider_location'] = None
|
provider_location=None)
|
||||||
|
|
||||||
with mock.patch.object(drv, '_ensure_share_mounted'):
|
with mock.patch.object(drv, '_ensure_share_mounted'):
|
||||||
drv.delete_volume(volume)
|
drv.delete_volume(volume)
|
||||||
@ -846,8 +840,11 @@ class NfsDriverTestCase(test.TestCase):
|
|||||||
def test_extend_volume(self):
|
def test_extend_volume(self):
|
||||||
"""Extend a volume by 1."""
|
"""Extend a volume by 1."""
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
volume = {'id': '80ee16b6-75d2-4d54-9539-ffc1b4b0fb10', 'size': 1,
|
volume = fake_volume.fake_volume_obj(
|
||||||
'provider_location': 'nfs_share'}
|
self.context,
|
||||||
|
id='80ee16b6-75d2-4d54-9539-ffc1b4b0fb10',
|
||||||
|
size=1,
|
||||||
|
provider_location='nfs_share')
|
||||||
path = 'path'
|
path = 'path'
|
||||||
newSize = volume['size'] + 1
|
newSize = volume['size'] + 1
|
||||||
|
|
||||||
@ -865,8 +862,11 @@ class NfsDriverTestCase(test.TestCase):
|
|||||||
def test_extend_volume_failure(self):
|
def test_extend_volume_failure(self):
|
||||||
"""Error during extend operation."""
|
"""Error during extend operation."""
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
volume = {'id': '80ee16b6-75d2-4d54-9539-ffc1b4b0fb10', 'size': 1,
|
volume = fake_volume.fake_volume_obj(
|
||||||
'provider_location': 'nfs_share'}
|
self.context,
|
||||||
|
id='80ee16b6-75d2-4d54-9539-ffc1b4b0fb10',
|
||||||
|
size=1,
|
||||||
|
provider_location='nfs_share')
|
||||||
|
|
||||||
with mock.patch.object(image_utils, 'resize_image'):
|
with mock.patch.object(image_utils, 'resize_image'):
|
||||||
with mock.patch.object(drv, 'local_path', return_value='path'):
|
with mock.patch.object(drv, 'local_path', return_value='path'):
|
||||||
@ -880,8 +880,11 @@ class NfsDriverTestCase(test.TestCase):
|
|||||||
def test_extend_volume_insufficient_space(self):
|
def test_extend_volume_insufficient_space(self):
|
||||||
"""Insufficient space on nfs_share during extend operation."""
|
"""Insufficient space on nfs_share during extend operation."""
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
volume = {'id': '80ee16b6-75d2-4d54-9539-ffc1b4b0fb10', 'size': 1,
|
volume = fake_volume.fake_volume_obj(
|
||||||
'provider_location': 'nfs_share'}
|
self.context,
|
||||||
|
id='80ee16b6-75d2-4d54-9539-ffc1b4b0fb10',
|
||||||
|
size=1,
|
||||||
|
provider_location='nfs_share')
|
||||||
|
|
||||||
with mock.patch.object(image_utils, 'resize_image'):
|
with mock.patch.object(image_utils, 'resize_image'):
|
||||||
with mock.patch.object(drv, 'local_path', return_value='path'):
|
with mock.patch.object(drv, 'local_path', return_value='path'):
|
||||||
@ -1125,8 +1128,8 @@ class NfsDriverDoSetupTestCase(test.TestCase):
|
|||||||
def _test_update_migrated_volume(self, volume_status, rename_volume,
|
def _test_update_migrated_volume(self, volume_status, rename_volume,
|
||||||
rename_exception=False):
|
rename_exception=False):
|
||||||
drv = nfs.NfsDriver(configuration=self.configuration)
|
drv = nfs.NfsDriver(configuration=self.configuration)
|
||||||
fake_volume_id = 'vol1'
|
fake_volume_id = 'f51b5730-13b7-11e6-a238-fa163e67a298'
|
||||||
fake_new_volume_id = 'vol2'
|
fake_new_volume_id = '12341234-13b7-11e6-a238-fa163e67a298'
|
||||||
fake_provider_source = 'fake_provider_source'
|
fake_provider_source = 'fake_provider_source'
|
||||||
fake_provider = 'fake_provider'
|
fake_provider = 'fake_provider'
|
||||||
base_dir = '/dir_base/'
|
base_dir = '/dir_base/'
|
||||||
@ -1135,27 +1138,34 @@ class NfsDriverDoSetupTestCase(test.TestCase):
|
|||||||
current_name = volume_name_template % fake_new_volume_id
|
current_name = volume_name_template % fake_new_volume_id
|
||||||
original_volume_path = base_dir + original_volume_name
|
original_volume_path = base_dir + original_volume_name
|
||||||
current_path = base_dir + current_name
|
current_path = base_dir + current_name
|
||||||
fake_volume = {'size': 1, 'id': fake_volume_id,
|
volume = fake_volume.fake_volume_obj(
|
||||||
'provider_location': fake_provider_source,
|
self.context,
|
||||||
'_name_id': None}
|
id=fake_volume_id,
|
||||||
fake_new_volume = {'size': 1, 'id': fake_new_volume_id,
|
size=1,
|
||||||
'provider_location': fake_provider,
|
provider_location=fake_provider_source,
|
||||||
'_name_id': None}
|
_name_id=None)
|
||||||
|
|
||||||
|
new_volume = fake_volume.fake_volume_obj(
|
||||||
|
self.context,
|
||||||
|
id=fake_new_volume_id,
|
||||||
|
size=1,
|
||||||
|
provider_location=fake_provider,
|
||||||
|
_name_id=None)
|
||||||
|
|
||||||
with mock.patch.object(drv, 'local_path') as local_path:
|
with mock.patch.object(drv, 'local_path') as local_path:
|
||||||
local_path.return_value = base_dir + current_name
|
local_path.return_value = base_dir + current_name
|
||||||
if volume_status == 'in-use':
|
if volume_status == 'in-use':
|
||||||
update = drv.update_migrated_volume(self.context,
|
update = drv.update_migrated_volume(self.context,
|
||||||
fake_volume,
|
volume,
|
||||||
fake_new_volume,
|
new_volume,
|
||||||
volume_status)
|
volume_status)
|
||||||
self.assertEqual({'_name_id': fake_new_volume_id,
|
self.assertEqual({'_name_id': fake_new_volume_id,
|
||||||
'provider_location': fake_provider}, update)
|
'provider_location': fake_provider}, update)
|
||||||
elif rename_exception:
|
elif rename_exception:
|
||||||
rename_volume.side_effect = OSError
|
rename_volume.side_effect = OSError
|
||||||
update = drv.update_migrated_volume(self.context,
|
update = drv.update_migrated_volume(self.context,
|
||||||
fake_volume,
|
volume,
|
||||||
fake_new_volume,
|
new_volume,
|
||||||
volume_status)
|
volume_status)
|
||||||
rename_volume.assert_called_once_with(current_path,
|
rename_volume.assert_called_once_with(current_path,
|
||||||
original_volume_path)
|
original_volume_path)
|
||||||
@ -1163,8 +1173,8 @@ class NfsDriverDoSetupTestCase(test.TestCase):
|
|||||||
'provider_location': fake_provider}, update)
|
'provider_location': fake_provider}, update)
|
||||||
else:
|
else:
|
||||||
update = drv.update_migrated_volume(self.context,
|
update = drv.update_migrated_volume(self.context,
|
||||||
fake_volume,
|
volume,
|
||||||
fake_new_volume,
|
new_volume,
|
||||||
volume_status)
|
volume_status)
|
||||||
rename_volume.assert_called_once_with(current_path,
|
rename_volume.assert_called_once_with(current_path,
|
||||||
original_volume_path)
|
original_volume_path)
|
||||||
@ -1175,7 +1185,7 @@ class NfsDriverDoSetupTestCase(test.TestCase):
|
|||||||
"Ensure that driver.retype() is there."""
|
"Ensure that driver.retype() is there."""
|
||||||
|
|
||||||
drv = nfs.NfsDriver(configuration=self.configuration)
|
drv = nfs.NfsDriver(configuration=self.configuration)
|
||||||
v1 = DumbVolume()
|
v1 = fake_volume.fake_volume_obj(self.context)
|
||||||
|
|
||||||
ret = drv.retype(self.context,
|
ret = drv.retype(self.context,
|
||||||
v1,
|
v1,
|
||||||
|
@ -30,6 +30,8 @@ from cinder import context
|
|||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.image import image_utils
|
from cinder.image import image_utils
|
||||||
from cinder import test
|
from cinder import test
|
||||||
|
from cinder.tests.unit import fake_snapshot
|
||||||
|
from cinder.tests.unit import fake_volume
|
||||||
from cinder.volume import configuration as conf
|
from cinder.volume import configuration as conf
|
||||||
from cinder.volume.drivers import quobyte
|
from cinder.volume.drivers import quobyte
|
||||||
|
|
||||||
@ -37,16 +39,6 @@ from cinder.volume.drivers import quobyte
|
|||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
class DumbVolume(object):
|
|
||||||
fields = {}
|
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
|
||||||
self.fields[key] = value
|
|
||||||
|
|
||||||
def __getitem__(self, item):
|
|
||||||
return self.fields[item]
|
|
||||||
|
|
||||||
|
|
||||||
class FakeDb(object):
|
class FakeDb(object):
|
||||||
msg = "Tests are broken: mock this out."
|
msg = "Tests are broken: mock this out."
|
||||||
|
|
||||||
@ -66,7 +58,6 @@ class QuobyteDriverTestCase(test.TestCase):
|
|||||||
TEST_SIZE_IN_GB = 1
|
TEST_SIZE_IN_GB = 1
|
||||||
TEST_MNT_POINT = '/mnt/quobyte'
|
TEST_MNT_POINT = '/mnt/quobyte'
|
||||||
TEST_MNT_POINT_BASE = '/mnt'
|
TEST_MNT_POINT_BASE = '/mnt'
|
||||||
TEST_LOCAL_PATH = '/mnt/quobyte/volume-123'
|
|
||||||
TEST_FILE_NAME = 'test.txt'
|
TEST_FILE_NAME = 'test.txt'
|
||||||
TEST_SHARES_CONFIG_FILE = '/etc/cinder/test-shares.conf'
|
TEST_SHARES_CONFIG_FILE = '/etc/cinder/test-shares.conf'
|
||||||
TEST_TMP_FILE = '/tmp/tempfile'
|
TEST_TMP_FILE = '/tmp/tempfile'
|
||||||
@ -94,6 +85,7 @@ class QuobyteDriverTestCase(test.TestCase):
|
|||||||
db=FakeDb())
|
db=FakeDb())
|
||||||
self._driver.shares = {}
|
self._driver.shares = {}
|
||||||
self._driver.set_nas_security_options(is_new_cinder_install=False)
|
self._driver.set_nas_security_options(is_new_cinder_install=False)
|
||||||
|
self.context = context.get_admin_context()
|
||||||
|
|
||||||
def assertRaisesAndMessageMatches(
|
def assertRaisesAndMessageMatches(
|
||||||
self, excClass, msg, callableObj, *args, **kwargs):
|
self, excClass, msg, callableObj, *args, **kwargs):
|
||||||
@ -115,13 +107,11 @@ class QuobyteDriverTestCase(test.TestCase):
|
|||||||
def test_local_path(self):
|
def test_local_path(self):
|
||||||
"""local_path common use case."""
|
"""local_path common use case."""
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
|
vol_id = self.VOLUME_UUID
|
||||||
volume = DumbVolume()
|
volume = self._simple_volume(_name_id=vol_id)
|
||||||
volume['provider_location'] = self.TEST_QUOBYTE_VOLUME
|
|
||||||
volume['name'] = 'volume-123'
|
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'/mnt/1331538734b757ed52d0e18c0a7210cd/volume-123',
|
'/mnt/1331538734b757ed52d0e18c0a7210cd/volume-%s' % vol_id,
|
||||||
drv.local_path(volume))
|
drv.local_path(volume))
|
||||||
|
|
||||||
def test_mount_quobyte_should_mount_correctly(self):
|
def test_mount_quobyte_should_mount_correctly(self):
|
||||||
@ -428,19 +418,18 @@ class QuobyteDriverTestCase(test.TestCase):
|
|||||||
# Future ones might do and therefore we mocked it.
|
# Future ones might do and therefore we mocked it.
|
||||||
self.assertGreaterEqual(mock_get_available_capacity.call_count, 0)
|
self.assertGreaterEqual(mock_get_available_capacity.call_count, 0)
|
||||||
|
|
||||||
def _simple_volume(self, uuid=None):
|
def _simple_volume(self, **kwargs):
|
||||||
volume = DumbVolume()
|
updates = {'id': self.VOLUME_UUID,
|
||||||
volume['provider_location'] = self.TEST_QUOBYTE_VOLUME
|
'provider_location': self.TEST_QUOBYTE_VOLUME,
|
||||||
if uuid is None:
|
'display_name': 'volume-%s' % self.VOLUME_UUID,
|
||||||
volume['id'] = self.VOLUME_UUID
|
'size': 10,
|
||||||
else:
|
'status': 'available'}
|
||||||
volume['id'] = uuid
|
|
||||||
# volume['name'] mirrors format from db/sqlalchemy/models.py
|
|
||||||
volume['name'] = 'volume-%s' % volume['id']
|
|
||||||
volume['size'] = 10
|
|
||||||
volume['status'] = 'available'
|
|
||||||
|
|
||||||
return volume
|
updates.update(kwargs)
|
||||||
|
if 'display_name' not in updates:
|
||||||
|
updates['display_name'] = 'volume-%s' % updates['id']
|
||||||
|
|
||||||
|
return fake_volume.fake_volume_obj(self.context, **updates)
|
||||||
|
|
||||||
def test_create_sparsed_volume(self):
|
def test_create_sparsed_volume(self):
|
||||||
drv = self._driver
|
drv = self._driver
|
||||||
@ -501,11 +490,11 @@ class QuobyteDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
drv.LOG = mock.Mock()
|
drv.LOG = mock.Mock()
|
||||||
drv._find_share = mock.Mock()
|
drv._find_share = mock.Mock()
|
||||||
|
drv._find_share.return_value = self.TEST_QUOBYTE_VOLUME
|
||||||
drv._do_create_volume = mock.Mock()
|
drv._do_create_volume = mock.Mock()
|
||||||
drv._ensure_shares_mounted = mock.Mock()
|
drv._ensure_shares_mounted = mock.Mock()
|
||||||
|
|
||||||
volume = DumbVolume()
|
volume = self._simple_volume(size=self.TEST_SIZE_IN_GB)
|
||||||
volume['size'] = self.TEST_SIZE_IN_GB
|
|
||||||
drv.create_volume(volume)
|
drv.create_volume(volume)
|
||||||
|
|
||||||
drv._find_share.assert_called_once_with(mock.ANY)
|
drv._find_share.assert_called_once_with(mock.ANY)
|
||||||
@ -521,8 +510,7 @@ class QuobyteDriverTestCase(test.TestCase):
|
|||||||
drv._do_create_volume = mock.Mock()
|
drv._do_create_volume = mock.Mock()
|
||||||
drv._find_share = mock.Mock(return_value=self.TEST_QUOBYTE_VOLUME)
|
drv._find_share = mock.Mock(return_value=self.TEST_QUOBYTE_VOLUME)
|
||||||
|
|
||||||
volume = DumbVolume()
|
volume = self._simple_volume(size=self.TEST_SIZE_IN_GB)
|
||||||
volume['size'] = self.TEST_SIZE_IN_GB
|
|
||||||
result = drv.create_volume(volume)
|
result = drv.create_volume(volume)
|
||||||
self.assertEqual(self.TEST_QUOBYTE_VOLUME, result['provider_location'])
|
self.assertEqual(self.TEST_QUOBYTE_VOLUME, result['provider_location'])
|
||||||
|
|
||||||
@ -575,9 +563,7 @@ class QuobyteDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
drv._execute = mock.Mock()
|
drv._execute = mock.Mock()
|
||||||
|
|
||||||
volume = DumbVolume()
|
volume = self._simple_volume(display_name='volume-123')
|
||||||
volume['name'] = 'volume-123'
|
|
||||||
volume['provider_location'] = self.TEST_QUOBYTE_VOLUME
|
|
||||||
|
|
||||||
drv._ensure_share_mounted = mock.Mock()
|
drv._ensure_share_mounted = mock.Mock()
|
||||||
|
|
||||||
@ -596,9 +582,8 @@ class QuobyteDriverTestCase(test.TestCase):
|
|||||||
drv._ensure_share_mounted = mock.Mock()
|
drv._ensure_share_mounted = mock.Mock()
|
||||||
drv._execute = mock.Mock()
|
drv._execute = mock.Mock()
|
||||||
|
|
||||||
volume = DumbVolume()
|
volume = self._simple_volume(display_name='volume-123',
|
||||||
volume['name'] = 'volume-123'
|
provider_location=None)
|
||||||
volume['provider_location'] = None
|
|
||||||
|
|
||||||
drv.delete_volume(volume)
|
drv.delete_volume(volume)
|
||||||
|
|
||||||
@ -638,7 +623,7 @@ class QuobyteDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
# lots of test vars to be prepared at first
|
# lots of test vars to be prepared at first
|
||||||
dest_volume = self._simple_volume(
|
dest_volume = self._simple_volume(
|
||||||
'c1073000-0000-0000-0000-0000000c1073')
|
id='c1073000-0000-0000-0000-0000000c1073')
|
||||||
src_volume = self._simple_volume()
|
src_volume = self._simple_volume()
|
||||||
|
|
||||||
vol_dir = os.path.join(self.TEST_MNT_POINT_BASE,
|
vol_dir = os.path.join(self.TEST_MNT_POINT_BASE,
|
||||||
@ -647,13 +632,15 @@ class QuobyteDriverTestCase(test.TestCase):
|
|||||||
dest_vol_path = os.path.join(vol_dir, dest_volume['name'])
|
dest_vol_path = os.path.join(vol_dir, dest_volume['name'])
|
||||||
info_path = os.path.join(vol_dir, src_volume['name']) + '.info'
|
info_path = os.path.join(vol_dir, src_volume['name']) + '.info'
|
||||||
|
|
||||||
snapshot = {'volume_name': src_volume['name'],
|
snapshot = fake_snapshot.fake_snapshot_obj(
|
||||||
'name': 'clone-snap-%s' % src_volume['id'],
|
self.context,
|
||||||
'size': src_volume['size'],
|
volume_name=src_volume.name,
|
||||||
'volume_size': src_volume['size'],
|
display_name='clone-snap-%s' % src_volume.id,
|
||||||
'volume_id': src_volume['id'],
|
size=src_volume.size,
|
||||||
'id': 'tmp-snap-%s' % src_volume['id'],
|
volume_size=src_volume.size,
|
||||||
'volume': src_volume}
|
volume_id=src_volume.id,
|
||||||
|
id=self.SNAP_UUID)
|
||||||
|
snapshot.volume = src_volume
|
||||||
|
|
||||||
snap_file = dest_volume['name'] + '.' + snapshot['id']
|
snap_file = dest_volume['name'] + '.' + snapshot['id']
|
||||||
snap_path = os.path.join(vol_dir, snap_file)
|
snap_path = os.path.join(vol_dir, snap_file)
|
||||||
@ -692,17 +679,18 @@ class QuobyteDriverTestCase(test.TestCase):
|
|||||||
drv = self._driver
|
drv = self._driver
|
||||||
|
|
||||||
src_volume = self._simple_volume()
|
src_volume = self._simple_volume()
|
||||||
snap_ref = {'volume_name': src_volume['name'],
|
|
||||||
'name': 'clone-snap-%s' % src_volume['id'],
|
|
||||||
'size': src_volume['size'],
|
|
||||||
'volume_size': src_volume['size'],
|
|
||||||
'volume_id': src_volume['id'],
|
|
||||||
'id': 'tmp-snap-%s' % src_volume['id'],
|
|
||||||
'volume': src_volume,
|
|
||||||
'status': 'error'}
|
|
||||||
|
|
||||||
new_volume = DumbVolume()
|
snap_ref = fake_snapshot.fake_snapshot_obj(
|
||||||
new_volume['size'] = snap_ref['size']
|
self.context,
|
||||||
|
volume_name=src_volume.name,
|
||||||
|
display_name='clone-snap-%s' % src_volume.id,
|
||||||
|
volume_size=src_volume.size,
|
||||||
|
volume_id=src_volume.id,
|
||||||
|
id=self.SNAP_UUID,
|
||||||
|
status='error')
|
||||||
|
snap_ref.volume = src_volume
|
||||||
|
|
||||||
|
new_volume = self._simple_volume(size=snap_ref.volume_size)
|
||||||
|
|
||||||
self.assertRaises(exception.InvalidSnapshot,
|
self.assertRaises(exception.InvalidSnapshot,
|
||||||
drv.create_volume_from_snapshot,
|
drv.create_volume_from_snapshot,
|
||||||
@ -713,17 +701,18 @@ class QuobyteDriverTestCase(test.TestCase):
|
|||||||
drv = self._driver
|
drv = self._driver
|
||||||
|
|
||||||
src_volume = self._simple_volume()
|
src_volume = self._simple_volume()
|
||||||
snap_ref = {'volume_name': src_volume['name'],
|
|
||||||
'name': 'clone-snap-%s' % src_volume['id'],
|
|
||||||
'size': src_volume['size'],
|
|
||||||
'volume_size': src_volume['size'],
|
|
||||||
'volume_id': src_volume['id'],
|
|
||||||
'id': 'tmp-snap-%s' % src_volume['id'],
|
|
||||||
'volume': src_volume,
|
|
||||||
'status': 'available'}
|
|
||||||
|
|
||||||
new_volume = DumbVolume()
|
snap_ref = fake_snapshot.fake_snapshot_obj(
|
||||||
new_volume['size'] = snap_ref['size']
|
self.context,
|
||||||
|
volume_name=src_volume.name,
|
||||||
|
display_name='clone-snap-%s' % src_volume.id,
|
||||||
|
volume_size=src_volume.size,
|
||||||
|
volume_id=src_volume.id,
|
||||||
|
id=self.SNAP_UUID,
|
||||||
|
status='available')
|
||||||
|
snap_ref.volume = src_volume
|
||||||
|
|
||||||
|
new_volume = self._simple_volume(size=snap_ref.volume_size)
|
||||||
|
|
||||||
drv._ensure_shares_mounted = mock.Mock()
|
drv._ensure_shares_mounted = mock.Mock()
|
||||||
drv._find_share = mock.Mock(return_value=self.TEST_QUOBYTE_VOLUME)
|
drv._find_share = mock.Mock(return_value=self.TEST_QUOBYTE_VOLUME)
|
||||||
|
@ -12,15 +12,19 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import collections
|
||||||
import copy
|
import copy
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import ddt
|
import ddt
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
|
from cinder import context
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.image import image_utils
|
from cinder.image import image_utils
|
||||||
from cinder import test
|
from cinder import test
|
||||||
|
from cinder.tests.unit import fake_snapshot
|
||||||
|
from cinder.tests.unit import fake_volume
|
||||||
from cinder import utils
|
from cinder import utils
|
||||||
from cinder.volume.drivers import remotefs
|
from cinder.volume.drivers import remotefs
|
||||||
|
|
||||||
@ -28,25 +32,7 @@ from cinder.volume.drivers import remotefs
|
|||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
class RemoteFsSnapDriverTestCase(test.TestCase):
|
class RemoteFsSnapDriverTestCase(test.TestCase):
|
||||||
|
|
||||||
_FAKE_CONTEXT = 'fake_context'
|
|
||||||
_FAKE_VOLUME_ID = '4f711859-4928-4cb7-801a-a50c37ceaccc'
|
|
||||||
_FAKE_VOLUME_NAME = 'volume-%s' % _FAKE_VOLUME_ID
|
|
||||||
_FAKE_VOLUME = {'id': _FAKE_VOLUME_ID,
|
|
||||||
'size': 1,
|
|
||||||
'provider_location': 'fake_share',
|
|
||||||
'name': _FAKE_VOLUME_NAME,
|
|
||||||
'status': 'available'}
|
|
||||||
_FAKE_MNT_POINT = '/mnt/fake_hash'
|
_FAKE_MNT_POINT = '/mnt/fake_hash'
|
||||||
_FAKE_VOLUME_PATH = os.path.join(_FAKE_MNT_POINT,
|
|
||||||
_FAKE_VOLUME_NAME)
|
|
||||||
_FAKE_SNAPSHOT_ID = '5g811859-4928-4cb7-801a-a50c37ceacba'
|
|
||||||
_FAKE_SNAPSHOT = {'context': _FAKE_CONTEXT,
|
|
||||||
'id': _FAKE_SNAPSHOT_ID,
|
|
||||||
'volume': _FAKE_VOLUME,
|
|
||||||
'volume_id': _FAKE_VOLUME_ID,
|
|
||||||
'status': 'available',
|
|
||||||
'volume_size': 1}
|
|
||||||
_FAKE_SNAPSHOT_PATH = (_FAKE_VOLUME_PATH + '.' + _FAKE_SNAPSHOT_ID)
|
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(RemoteFsSnapDriverTestCase, self).setUp()
|
super(RemoteFsSnapDriverTestCase, self).setUp()
|
||||||
@ -55,21 +41,32 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
|
|||||||
self._driver._execute = mock.Mock()
|
self._driver._execute = mock.Mock()
|
||||||
self._driver._delete = mock.Mock()
|
self._driver._delete = mock.Mock()
|
||||||
|
|
||||||
|
self.context = context.get_admin_context()
|
||||||
|
|
||||||
|
self._fake_volume = fake_volume.fake_volume_obj(
|
||||||
|
self.context, provider_location='fake_share')
|
||||||
|
self._fake_volume_path = os.path.join(self._FAKE_MNT_POINT,
|
||||||
|
self._fake_volume.name)
|
||||||
|
self._fake_snapshot = fake_snapshot.fake_snapshot_obj(self.context)
|
||||||
|
self._fake_snapshot_path = (self._fake_volume_path + '.' +
|
||||||
|
self._fake_snapshot.id)
|
||||||
|
self._fake_snapshot.volume = self._fake_volume
|
||||||
|
|
||||||
def _test_delete_snapshot(self, volume_in_use=False,
|
def _test_delete_snapshot(self, volume_in_use=False,
|
||||||
stale_snapshot=False,
|
stale_snapshot=False,
|
||||||
is_active_image=True):
|
is_active_image=True):
|
||||||
# If the snapshot is not the active image, it is guaranteed that
|
# If the snapshot is not the active image, it is guaranteed that
|
||||||
# another snapshot exists having it as backing file.
|
# another snapshot exists having it as backing file.
|
||||||
|
|
||||||
fake_snapshot_name = os.path.basename(self._FAKE_SNAPSHOT_PATH)
|
fake_snapshot_name = os.path.basename(self._fake_snapshot_path)
|
||||||
fake_info = {'active': fake_snapshot_name,
|
fake_info = {'active': fake_snapshot_name,
|
||||||
self._FAKE_SNAPSHOT['id']: fake_snapshot_name}
|
self._fake_snapshot.id: fake_snapshot_name}
|
||||||
fake_snap_img_info = mock.Mock()
|
fake_snap_img_info = mock.Mock()
|
||||||
fake_base_img_info = mock.Mock()
|
fake_base_img_info = mock.Mock()
|
||||||
if stale_snapshot:
|
if stale_snapshot:
|
||||||
fake_snap_img_info.backing_file = None
|
fake_snap_img_info.backing_file = None
|
||||||
else:
|
else:
|
||||||
fake_snap_img_info.backing_file = self._FAKE_VOLUME_NAME
|
fake_snap_img_info.backing_file = self._fake_volume.name
|
||||||
fake_snap_img_info.file_format = 'qcow2'
|
fake_snap_img_info.file_format = 'qcow2'
|
||||||
fake_base_img_info.backing_file = None
|
fake_base_img_info.backing_file = None
|
||||||
fake_base_img_info.file_format = 'raw'
|
fake_base_img_info.file_format = 'raw'
|
||||||
@ -91,72 +88,71 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
expected_info = {
|
expected_info = {
|
||||||
'active': fake_snapshot_name,
|
'active': fake_snapshot_name,
|
||||||
self._FAKE_SNAPSHOT_ID: fake_snapshot_name
|
self._fake_snapshot.id: fake_snapshot_name
|
||||||
}
|
}
|
||||||
|
|
||||||
if volume_in_use:
|
if volume_in_use:
|
||||||
fake_snapshot = copy.deepcopy(self._FAKE_SNAPSHOT)
|
self._fake_snapshot.volume.status = 'in-use'
|
||||||
fake_snapshot['volume']['status'] = 'in-use'
|
|
||||||
|
|
||||||
self._driver._read_info_file.return_value = fake_info
|
self._driver._read_info_file.return_value = fake_info
|
||||||
|
|
||||||
self._driver._delete_snapshot(fake_snapshot)
|
self._driver._delete_snapshot(self._fake_snapshot)
|
||||||
if stale_snapshot:
|
if stale_snapshot:
|
||||||
self._driver._delete_stale_snapshot.assert_called_once_with(
|
self._driver._delete_stale_snapshot.assert_called_once_with(
|
||||||
fake_snapshot)
|
self._fake_snapshot)
|
||||||
else:
|
else:
|
||||||
expected_online_delete_info = {
|
expected_online_delete_info = {
|
||||||
'active_file': fake_snapshot_name,
|
'active_file': fake_snapshot_name,
|
||||||
'snapshot_file': fake_snapshot_name,
|
'snapshot_file': fake_snapshot_name,
|
||||||
'base_file': self._FAKE_VOLUME_NAME,
|
'base_file': self._fake_volume.name,
|
||||||
'base_id': None,
|
'base_id': None,
|
||||||
'new_base_file': None
|
'new_base_file': None
|
||||||
}
|
}
|
||||||
self._driver._delete_snapshot_online.assert_called_once_with(
|
self._driver._delete_snapshot_online.assert_called_once_with(
|
||||||
self._FAKE_CONTEXT, fake_snapshot,
|
self.context, self._fake_snapshot,
|
||||||
expected_online_delete_info)
|
expected_online_delete_info)
|
||||||
|
|
||||||
elif is_active_image:
|
elif is_active_image:
|
||||||
self._driver._read_info_file.return_value = fake_info
|
self._driver._read_info_file.return_value = fake_info
|
||||||
|
|
||||||
self._driver._delete_snapshot(self._FAKE_SNAPSHOT)
|
self._driver._delete_snapshot(self._fake_snapshot)
|
||||||
|
|
||||||
self._driver._img_commit.assert_called_once_with(
|
self._driver._img_commit.assert_called_once_with(
|
||||||
self._FAKE_SNAPSHOT_PATH)
|
self._fake_snapshot_path)
|
||||||
self.assertNotIn(self._FAKE_SNAPSHOT_ID, fake_info)
|
self.assertNotIn(self._fake_snapshot.id, fake_info)
|
||||||
self._driver._write_info_file.assert_called_once_with(
|
self._driver._write_info_file.assert_called_once_with(
|
||||||
mock.sentinel.fake_info_path, fake_info)
|
mock.sentinel.fake_info_path, fake_info)
|
||||||
else:
|
else:
|
||||||
fake_upper_snap_id = 'fake_upper_snap_id'
|
fake_upper_snap_id = 'fake_upper_snap_id'
|
||||||
fake_upper_snap_path = (
|
fake_upper_snap_path = (
|
||||||
self._FAKE_VOLUME_PATH + '-snapshot' + fake_upper_snap_id)
|
self._fake_volume_path + '-snapshot' + fake_upper_snap_id)
|
||||||
fake_upper_snap_name = os.path.basename(fake_upper_snap_path)
|
fake_upper_snap_name = os.path.basename(fake_upper_snap_path)
|
||||||
|
|
||||||
fake_backing_chain = [
|
fake_backing_chain = [
|
||||||
{'filename': fake_upper_snap_name,
|
{'filename': fake_upper_snap_name,
|
||||||
'backing-filename': fake_snapshot_name},
|
'backing-filename': fake_snapshot_name},
|
||||||
{'filename': fake_snapshot_name,
|
{'filename': fake_snapshot_name,
|
||||||
'backing-filename': self._FAKE_VOLUME_NAME},
|
'backing-filename': self._fake_volume.name},
|
||||||
{'filename': self._FAKE_VOLUME_NAME,
|
{'filename': self._fake_volume.name,
|
||||||
'backing-filename': None}]
|
'backing-filename': None}]
|
||||||
|
|
||||||
fake_info[fake_upper_snap_id] = fake_upper_snap_name
|
fake_info[fake_upper_snap_id] = fake_upper_snap_name
|
||||||
fake_info[self._FAKE_SNAPSHOT_ID] = fake_snapshot_name
|
fake_info[self._fake_snapshot.id] = fake_snapshot_name
|
||||||
fake_info['active'] = fake_upper_snap_name
|
fake_info['active'] = fake_upper_snap_name
|
||||||
|
|
||||||
expected_info = copy.deepcopy(fake_info)
|
expected_info = copy.deepcopy(fake_info)
|
||||||
del expected_info[self._FAKE_SNAPSHOT_ID]
|
del expected_info[self._fake_snapshot.id]
|
||||||
|
|
||||||
self._driver._read_info_file.return_value = fake_info
|
self._driver._read_info_file.return_value = fake_info
|
||||||
self._driver._get_backing_chain_for_path = mock.Mock(
|
self._driver._get_backing_chain_for_path = mock.Mock(
|
||||||
return_value=fake_backing_chain)
|
return_value=fake_backing_chain)
|
||||||
|
|
||||||
self._driver._delete_snapshot(self._FAKE_SNAPSHOT)
|
self._driver._delete_snapshot(self._fake_snapshot)
|
||||||
|
|
||||||
self._driver._img_commit.assert_called_once_with(
|
self._driver._img_commit.assert_called_once_with(
|
||||||
self._FAKE_SNAPSHOT_PATH)
|
self._fake_snapshot_path)
|
||||||
self._driver._rebase_img.assert_called_once_with(
|
self._driver._rebase_img.assert_called_once_with(
|
||||||
fake_upper_snap_path, self._FAKE_VOLUME_NAME,
|
fake_upper_snap_path, self._fake_volume.name,
|
||||||
fake_base_img_info.file_format)
|
fake_base_img_info.file_format)
|
||||||
self._driver._write_info_file.assert_called_once_with(
|
self._driver._write_info_file.assert_called_once_with(
|
||||||
mock.sentinel.fake_info_path, expected_info)
|
mock.sentinel.fake_info_path, expected_info)
|
||||||
@ -175,12 +171,12 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
|
|||||||
self._test_delete_snapshot(is_active_image=False)
|
self._test_delete_snapshot(is_active_image=False)
|
||||||
|
|
||||||
def test_delete_stale_snapshot(self):
|
def test_delete_stale_snapshot(self):
|
||||||
fake_snapshot_name = os.path.basename(self._FAKE_SNAPSHOT_PATH)
|
fake_snapshot_name = os.path.basename(self._fake_snapshot_path)
|
||||||
fake_snap_info = {
|
fake_snap_info = {
|
||||||
'active': self._FAKE_VOLUME_NAME,
|
'active': self._fake_volume.name,
|
||||||
self._FAKE_SNAPSHOT_ID: fake_snapshot_name
|
self._fake_snapshot.id: fake_snapshot_name
|
||||||
}
|
}
|
||||||
expected_info = {'active': self._FAKE_VOLUME_NAME}
|
expected_info = {'active': self._fake_volume.name}
|
||||||
|
|
||||||
self._driver._local_path_volume_info = mock.Mock(
|
self._driver._local_path_volume_info = mock.Mock(
|
||||||
return_value=mock.sentinel.fake_info_path)
|
return_value=mock.sentinel.fake_info_path)
|
||||||
@ -190,42 +186,41 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
|
|||||||
return_value=self._FAKE_MNT_POINT)
|
return_value=self._FAKE_MNT_POINT)
|
||||||
self._driver._write_info_file = mock.Mock()
|
self._driver._write_info_file = mock.Mock()
|
||||||
|
|
||||||
self._driver._delete_stale_snapshot(self._FAKE_SNAPSHOT)
|
self._driver._delete_stale_snapshot(self._fake_snapshot)
|
||||||
|
|
||||||
self._driver._delete.assert_called_once_with(self._FAKE_SNAPSHOT_PATH)
|
self._driver._delete.assert_called_once_with(self._fake_snapshot_path)
|
||||||
self._driver._write_info_file.assert_called_once_with(
|
self._driver._write_info_file.assert_called_once_with(
|
||||||
mock.sentinel.fake_info_path, expected_info)
|
mock.sentinel.fake_info_path, expected_info)
|
||||||
|
|
||||||
def test_do_create_snapshot(self):
|
def test_do_create_snapshot(self):
|
||||||
self._driver._local_volume_dir = mock.Mock(
|
self._driver._local_volume_dir = mock.Mock(
|
||||||
return_value=self._FAKE_VOLUME_PATH)
|
return_value=self._fake_volume_path)
|
||||||
fake_backing_path = os.path.join(
|
fake_backing_path = os.path.join(
|
||||||
self._driver._local_volume_dir(),
|
self._driver._local_volume_dir(),
|
||||||
self._FAKE_VOLUME_NAME)
|
self._fake_volume.name)
|
||||||
|
|
||||||
self._driver._execute = mock.Mock()
|
self._driver._execute = mock.Mock()
|
||||||
self._driver._set_rw_permissions = mock.Mock()
|
self._driver._set_rw_permissions = mock.Mock()
|
||||||
self._driver._qemu_img_info = mock.Mock(
|
self._driver._qemu_img_info = mock.Mock(
|
||||||
return_value=mock.Mock(file_format=mock.sentinel.backing_fmt))
|
return_value=mock.Mock(file_format=mock.sentinel.backing_fmt))
|
||||||
|
|
||||||
self._driver._do_create_snapshot(self._FAKE_SNAPSHOT,
|
self._driver._do_create_snapshot(self._fake_snapshot,
|
||||||
self._FAKE_VOLUME_NAME,
|
self._fake_volume.name,
|
||||||
self._FAKE_SNAPSHOT_PATH)
|
self._fake_snapshot_path)
|
||||||
command1 = ['qemu-img', 'create', '-f', 'qcow2', '-o',
|
command1 = ['qemu-img', 'create', '-f', 'qcow2', '-o',
|
||||||
'backing_file=%s' % fake_backing_path,
|
'backing_file=%s' % fake_backing_path,
|
||||||
self._FAKE_SNAPSHOT_PATH]
|
self._fake_snapshot_path]
|
||||||
command2 = ['qemu-img', 'rebase', '-u',
|
command2 = ['qemu-img', 'rebase', '-u',
|
||||||
'-b', self._FAKE_VOLUME_NAME,
|
'-b', self._fake_volume.name,
|
||||||
'-F', mock.sentinel.backing_fmt,
|
'-F', mock.sentinel.backing_fmt,
|
||||||
self._FAKE_SNAPSHOT_PATH]
|
self._fake_snapshot_path]
|
||||||
|
|
||||||
self._driver._execute.assert_any_call(*command1, run_as_root=True)
|
self._driver._execute.assert_any_call(*command1, run_as_root=True)
|
||||||
self._driver._execute.assert_any_call(*command2, run_as_root=True)
|
self._driver._execute.assert_any_call(*command2, run_as_root=True)
|
||||||
|
|
||||||
def _test_create_snapshot(self, volume_in_use=False):
|
def _test_create_snapshot(self, volume_in_use=False):
|
||||||
fake_snapshot = copy.deepcopy(self._FAKE_SNAPSHOT)
|
|
||||||
fake_snapshot_info = {}
|
fake_snapshot_info = {}
|
||||||
fake_snapshot_file_name = os.path.basename(self._FAKE_SNAPSHOT_PATH)
|
fake_snapshot_file_name = os.path.basename(self._fake_snapshot_path)
|
||||||
|
|
||||||
self._driver._local_path_volume_info = mock.Mock(
|
self._driver._local_path_volume_info = mock.Mock(
|
||||||
return_value=mock.sentinel.fake_info_path)
|
return_value=mock.sentinel.fake_info_path)
|
||||||
@ -235,28 +230,28 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
|
|||||||
self._driver._create_snapshot_online = mock.Mock()
|
self._driver._create_snapshot_online = mock.Mock()
|
||||||
self._driver._write_info_file = mock.Mock()
|
self._driver._write_info_file = mock.Mock()
|
||||||
self._driver.get_active_image_from_info = mock.Mock(
|
self._driver.get_active_image_from_info = mock.Mock(
|
||||||
return_value=self._FAKE_VOLUME_NAME)
|
return_value=self._fake_volume.name)
|
||||||
self._driver._get_new_snap_path = mock.Mock(
|
self._driver._get_new_snap_path = mock.Mock(
|
||||||
return_value=self._FAKE_SNAPSHOT_PATH)
|
return_value=self._fake_snapshot_path)
|
||||||
|
|
||||||
expected_snapshot_info = {
|
expected_snapshot_info = {
|
||||||
'active': fake_snapshot_file_name,
|
'active': fake_snapshot_file_name,
|
||||||
self._FAKE_SNAPSHOT_ID: fake_snapshot_file_name
|
self._fake_snapshot.id: fake_snapshot_file_name
|
||||||
}
|
}
|
||||||
|
|
||||||
if volume_in_use:
|
if volume_in_use:
|
||||||
fake_snapshot['volume']['status'] = 'in-use'
|
self._fake_snapshot.volume.status = 'in-use'
|
||||||
expected_method_called = '_create_snapshot_online'
|
expected_method_called = '_create_snapshot_online'
|
||||||
else:
|
else:
|
||||||
fake_snapshot['volume']['status'] = 'available'
|
self._fake_snapshot.volume.status = 'available'
|
||||||
expected_method_called = '_do_create_snapshot'
|
expected_method_called = '_do_create_snapshot'
|
||||||
|
|
||||||
self._driver._create_snapshot(fake_snapshot)
|
self._driver._create_snapshot(self._fake_snapshot)
|
||||||
|
|
||||||
fake_method = getattr(self._driver, expected_method_called)
|
fake_method = getattr(self._driver, expected_method_called)
|
||||||
fake_method.assert_called_with(
|
fake_method.assert_called_with(
|
||||||
fake_snapshot, self._FAKE_VOLUME_NAME,
|
self._fake_snapshot, self._fake_volume.name,
|
||||||
self._FAKE_SNAPSHOT_PATH)
|
self._fake_snapshot_path)
|
||||||
self._driver._write_info_file.assert_called_with(
|
self._driver._write_info_file.assert_called_with(
|
||||||
mock.sentinel.fake_info_path,
|
mock.sentinel.fake_info_path,
|
||||||
expected_snapshot_info)
|
expected_snapshot_info)
|
||||||
@ -268,12 +263,10 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
|
|||||||
self._test_create_snapshot(volume_in_use=True)
|
self._test_create_snapshot(volume_in_use=True)
|
||||||
|
|
||||||
def test_create_snapshot_invalid_volume(self):
|
def test_create_snapshot_invalid_volume(self):
|
||||||
fake_snapshot = copy.deepcopy(self._FAKE_SNAPSHOT)
|
self._fake_snapshot.volume.status = 'error'
|
||||||
fake_snapshot['volume']['status'] = 'error'
|
|
||||||
|
|
||||||
self.assertRaises(exception.InvalidVolume,
|
self.assertRaises(exception.InvalidVolume,
|
||||||
self._driver._create_snapshot,
|
self._driver._create_snapshot,
|
||||||
fake_snapshot)
|
self._fake_snapshot)
|
||||||
|
|
||||||
@mock.patch('cinder.db.snapshot_get')
|
@mock.patch('cinder.db.snapshot_get')
|
||||||
@mock.patch('time.sleep')
|
@mock.patch('time.sleep')
|
||||||
@ -294,18 +287,18 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
|
|||||||
mock_do_create_snapshot:
|
mock_do_create_snapshot:
|
||||||
self.assertRaises(exception.RemoteFSConcurrentRequest,
|
self.assertRaises(exception.RemoteFSConcurrentRequest,
|
||||||
self._driver._create_snapshot_online,
|
self._driver._create_snapshot_online,
|
||||||
self._FAKE_SNAPSHOT,
|
self._fake_snapshot,
|
||||||
self._FAKE_VOLUME_NAME,
|
self._fake_volume.name,
|
||||||
self._FAKE_SNAPSHOT_PATH)
|
self._fake_snapshot_path)
|
||||||
|
|
||||||
mock_do_create_snapshot.assert_called_once_with(
|
mock_do_create_snapshot.assert_called_once_with(
|
||||||
self._FAKE_SNAPSHOT, self._FAKE_VOLUME_NAME,
|
self._fake_snapshot, self._fake_volume.name,
|
||||||
self._FAKE_SNAPSHOT_PATH)
|
self._fake_snapshot_path)
|
||||||
self.assertEqual([mock.call(1), mock.call(1)],
|
self.assertEqual([mock.call(1), mock.call(1)],
|
||||||
mock_sleep.call_args_list)
|
mock_sleep.call_args_list)
|
||||||
self.assertEqual(3, mock_snapshot_get.call_count)
|
self.assertEqual(3, mock_snapshot_get.call_count)
|
||||||
mock_snapshot_get.assert_called_with(self._FAKE_SNAPSHOT['context'],
|
mock_snapshot_get.assert_called_with(self._fake_snapshot._context,
|
||||||
self._FAKE_SNAPSHOT['id'])
|
self._fake_snapshot.id)
|
||||||
|
|
||||||
@mock.patch.object(utils, 'synchronized')
|
@mock.patch.object(utils, 'synchronized')
|
||||||
def _locked_volume_operation_test_helper(self, mock_synchronized, func,
|
def _locked_volume_operation_test_helper(self, mock_synchronized, func,
|
||||||
@ -318,7 +311,7 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
mock_synchronized.side_effect = mock_decorator
|
mock_synchronized.side_effect = mock_decorator
|
||||||
expected_lock = '%s-%s' % (self._driver.driver_prefix,
|
expected_lock = '%s-%s' % (self._driver.driver_prefix,
|
||||||
self._FAKE_VOLUME_ID)
|
self._fake_volume.id)
|
||||||
|
|
||||||
if expected_exception:
|
if expected_exception:
|
||||||
self.assertRaises(expected_exception, func,
|
self.assertRaises(expected_exception, func,
|
||||||
@ -332,7 +325,8 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
|
|||||||
self.assertEqual(mock.sentinel.ret_val, ret_val)
|
self.assertEqual(mock.sentinel.ret_val, ret_val)
|
||||||
|
|
||||||
def test_locked_volume_id_operation(self):
|
def test_locked_volume_id_operation(self):
|
||||||
mock_volume = {'id': self._FAKE_VOLUME_ID}
|
mock_volume = mock.Mock()
|
||||||
|
mock_volume.id = self._fake_volume.id
|
||||||
|
|
||||||
@remotefs.locked_volume_id_operation
|
@remotefs.locked_volume_id_operation
|
||||||
def synchronized_func(inst, volume):
|
def synchronized_func(inst, volume):
|
||||||
@ -342,7 +336,8 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
|
|||||||
volume=mock_volume)
|
volume=mock_volume)
|
||||||
|
|
||||||
def test_locked_volume_id_snapshot_operation(self):
|
def test_locked_volume_id_snapshot_operation(self):
|
||||||
mock_snapshot = {'volume': {'id': self._FAKE_VOLUME_ID}}
|
mock_snapshot = mock.Mock()
|
||||||
|
mock_snapshot.volume.id = self._fake_volume.id
|
||||||
|
|
||||||
@remotefs.locked_volume_id_operation
|
@remotefs.locked_volume_id_operation
|
||||||
def synchronized_func(inst, snapshot):
|
def synchronized_func(inst, snapshot):
|
||||||
@ -432,22 +427,36 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
|
|||||||
mock.patch.object(drv, '_copy_volume_from_snapshot') as \
|
mock.patch.object(drv, '_copy_volume_from_snapshot') as \
|
||||||
mock_copy_volume_from_snapshot:
|
mock_copy_volume_from_snapshot:
|
||||||
|
|
||||||
volume = self._FAKE_VOLUME.copy()
|
volume = fake_volume.fake_volume_obj(self.context)
|
||||||
src_vref = self._FAKE_VOLUME.copy()
|
src_vref_id = '375e32b2-804a-49f2-b282-85d1d5a5b9e1'
|
||||||
src_vref['id'] = '375e32b2-804a-49f2-b282-85d1d5a5b9e1'
|
src_vref = fake_volume.fake_volume_obj(
|
||||||
src_vref['name'] = 'volume-%s' % src_vref['id']
|
self.context,
|
||||||
volume_ref = {'id': volume['id'],
|
id=src_vref_id,
|
||||||
'name': volume['name'],
|
name='volume-%s' % src_vref_id)
|
||||||
'status': volume['status'],
|
|
||||||
'provider_location': volume['provider_location'],
|
vol_attrs = ['provider_location', 'size', 'id', 'name', 'status',
|
||||||
'size': volume['size']}
|
'volume_type', 'metadata']
|
||||||
snap_ref = {'volume_name': volume['name'],
|
Volume = collections.namedtuple('Volume', vol_attrs)
|
||||||
'name': 'clone-snap-%s' % src_vref['id'],
|
|
||||||
'size': src_vref['size'],
|
snap_attrs = ['volume_name', 'volume_size', 'name',
|
||||||
'volume_size': src_vref['size'],
|
'volume_id', 'id', 'volume']
|
||||||
'volume_id': src_vref['id'],
|
Snapshot = collections.namedtuple('Snapshot', snap_attrs)
|
||||||
'id': 'tmp-snap-%s' % src_vref['id'],
|
|
||||||
'volume': src_vref}
|
volume_ref = Volume(id=volume.id,
|
||||||
|
name=volume.name,
|
||||||
|
status=volume.status,
|
||||||
|
provider_location=volume.provider_location,
|
||||||
|
size=volume.size,
|
||||||
|
volume_type=volume.volume_type,
|
||||||
|
metadata=volume.metadata)
|
||||||
|
|
||||||
|
snap_ref = Snapshot(volume_name=volume.name,
|
||||||
|
name='clone-snap-%s' % src_vref.id,
|
||||||
|
volume_size=src_vref.size,
|
||||||
|
volume_id=src_vref.id,
|
||||||
|
id='tmp-snap-%s' % src_vref.id,
|
||||||
|
volume=src_vref)
|
||||||
|
|
||||||
drv.create_cloned_volume(volume, src_vref)
|
drv.create_cloned_volume(volume, src_vref)
|
||||||
|
|
||||||
mock_create_snapshot.assert_called_once_with(snap_ref)
|
mock_create_snapshot.assert_called_once_with(snap_ref)
|
||||||
|
@ -26,27 +26,26 @@ from six.moves import urllib
|
|||||||
from cinder import context
|
from cinder import context
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder import test
|
from cinder import test
|
||||||
|
from cinder.tests.unit import fake_snapshot
|
||||||
|
from cinder.tests.unit import fake_volume
|
||||||
from cinder.volume import configuration as conf
|
from cinder.volume import configuration as conf
|
||||||
import cinder.volume.drivers.scality as driver
|
import cinder.volume.drivers.scality as driver
|
||||||
|
|
||||||
_FAKE_VOLUME = {'name': 'volume-a79d463e-1fd5-11e5-a6ff-5b81bfee8544',
|
_FAKE_VOLUME_ID = 'a79d463e-1fd5-11e5-a6ff-5b81bfee8544'
|
||||||
'id': 'a79d463e-1fd5-11e5-a6ff-5b81bfee8544',
|
_FAKE_VOLUME_NAME = 'volume-a79d463e-1fd5-11e5-a6ff-5b81bfee8544'
|
||||||
'provider_location': 'fake_share'}
|
|
||||||
_FAKE_SNAPSHOT = {'id': 'ae3d6da2-1fd5-11e5-967f-1b8cf3b401ab',
|
_FAKE_SNAPSHOT_ID = 'ae3d6da2-1fd5-11e5-967f-1b8cf3b401ab'
|
||||||
'volume': _FAKE_VOLUME,
|
_FAKE_SNAPSHOT_NAME = 'snapshot-ae3d6da2-1fd5-11e5-967f-1b8cf3b401ab'
|
||||||
'status': 'available',
|
|
||||||
'provider_location': None,
|
|
||||||
'volume_size': 1,
|
|
||||||
'name': 'snapshot-ae3d6da2-1fd5-11e5-967f-1b8cf3b401ab'}
|
|
||||||
_FAKE_BACKUP = {'id': '914849d2-2585-11e5-be54-d70ca0c343d6',
|
_FAKE_BACKUP = {'id': '914849d2-2585-11e5-be54-d70ca0c343d6',
|
||||||
'volume_id': _FAKE_VOLUME['id']}
|
'volume_id': _FAKE_VOLUME_ID}
|
||||||
|
|
||||||
_FAKE_MNT_POINT = '/tmp'
|
_FAKE_MNT_POINT = '/tmp'
|
||||||
_FAKE_SOFS_CONFIG = '/etc/sfused.conf'
|
_FAKE_SOFS_CONFIG = '/etc/sfused.conf'
|
||||||
_FAKE_VOLUME_DIR = 'cinder/volumes'
|
_FAKE_VOLUME_DIR = 'cinder/volumes'
|
||||||
_FAKE_VOL_BASEDIR = os.path.join(_FAKE_MNT_POINT, _FAKE_VOLUME_DIR, '00')
|
_FAKE_VOL_BASEDIR = os.path.join(_FAKE_MNT_POINT, _FAKE_VOLUME_DIR, '00')
|
||||||
_FAKE_VOL_PATH = os.path.join(_FAKE_VOL_BASEDIR, _FAKE_VOLUME['name'])
|
_FAKE_VOL_PATH = os.path.join(_FAKE_VOL_BASEDIR, _FAKE_VOLUME_NAME)
|
||||||
_FAKE_SNAP_PATH = os.path.join(_FAKE_VOL_BASEDIR, _FAKE_SNAPSHOT['name'])
|
_FAKE_SNAP_PATH = os.path.join(_FAKE_VOL_BASEDIR, _FAKE_SNAPSHOT_NAME)
|
||||||
|
|
||||||
_FAKE_MOUNTS_TABLE = [['tmpfs /dev/shm\n'],
|
_FAKE_MOUNTS_TABLE = [['tmpfs /dev/shm\n'],
|
||||||
['fuse ' + _FAKE_MNT_POINT + '\n']]
|
['fuse ' + _FAKE_MNT_POINT + '\n']]
|
||||||
@ -66,6 +65,30 @@ class ScalityDriverTestCase(test.TestCase):
|
|||||||
self.drv = driver.ScalityDriver(configuration=self.cfg)
|
self.drv = driver.ScalityDriver(configuration=self.cfg)
|
||||||
self.drv.db = mock.Mock()
|
self.drv.db = mock.Mock()
|
||||||
|
|
||||||
|
self.context = context.get_admin_context()
|
||||||
|
|
||||||
|
def _simple_volume(self, **kwargs):
|
||||||
|
updates = {'display_name': _FAKE_VOLUME_NAME,
|
||||||
|
'id': _FAKE_VOLUME_ID,
|
||||||
|
'provider_location': 'fake_share'}
|
||||||
|
updates.update(kwargs)
|
||||||
|
|
||||||
|
return fake_volume.fake_volume_obj(self.context, **updates)
|
||||||
|
|
||||||
|
def _simple_snapshot(self, **kwargs):
|
||||||
|
updates = {'id': _FAKE_SNAPSHOT_ID,
|
||||||
|
'display_name': _FAKE_SNAPSHOT_NAME,
|
||||||
|
'status': 'available',
|
||||||
|
'provider_location': None,
|
||||||
|
'volume_size': 1}
|
||||||
|
|
||||||
|
updates.update(kwargs)
|
||||||
|
snapshot = fake_snapshot.fake_snapshot_obj(self.context, **updates)
|
||||||
|
volume = self._simple_volume()
|
||||||
|
snapshot.volume = volume
|
||||||
|
|
||||||
|
return snapshot
|
||||||
|
|
||||||
@mock.patch.object(driver.urllib.request, 'urlopen')
|
@mock.patch.object(driver.urllib.request, 'urlopen')
|
||||||
@mock.patch('os.access')
|
@mock.patch('os.access')
|
||||||
def test_check_for_setup_error(self, mock_os_access, mock_urlopen):
|
def test_check_for_setup_error(self, mock_os_access, mock_urlopen):
|
||||||
@ -206,27 +229,28 @@ class ScalityDriverTestCase(test.TestCase):
|
|||||||
def test_initialize_connection(self, mock_qemu_img_info):
|
def test_initialize_connection(self, mock_qemu_img_info):
|
||||||
info = imageutils.QemuImgInfo()
|
info = imageutils.QemuImgInfo()
|
||||||
info.file_format = 'raw'
|
info.file_format = 'raw'
|
||||||
info.image = _FAKE_VOLUME['name']
|
info.image = _FAKE_VOLUME_NAME
|
||||||
mock_qemu_img_info.return_value = info
|
mock_qemu_img_info.return_value = info
|
||||||
|
|
||||||
|
volume = self._simple_volume()
|
||||||
with mock.patch.object(self.drv, 'get_active_image_from_info') as \
|
with mock.patch.object(self.drv, 'get_active_image_from_info') as \
|
||||||
mock_get_active_image_from_info:
|
mock_get_active_image_from_info:
|
||||||
|
|
||||||
mock_get_active_image_from_info.return_value = _FAKE_VOLUME['name']
|
mock_get_active_image_from_info.return_value = _FAKE_VOLUME_NAME
|
||||||
conn_info = self.drv.initialize_connection(_FAKE_VOLUME, None)
|
conn_info = self.drv.initialize_connection(volume, None)
|
||||||
|
|
||||||
expected_conn_info = {
|
expected_conn_info = {
|
||||||
'driver_volume_type': driver.ScalityDriver.driver_volume_type,
|
'driver_volume_type': driver.ScalityDriver.driver_volume_type,
|
||||||
'mount_point_base': _FAKE_MNT_POINT,
|
'mount_point_base': _FAKE_MNT_POINT,
|
||||||
'data': {
|
'data': {
|
||||||
'export': _FAKE_VOLUME['provider_location'],
|
'export': volume.provider_location,
|
||||||
'name': _FAKE_VOLUME['name'],
|
'name': volume.name,
|
||||||
'sofs_path': 'cinder/volumes/00/' + _FAKE_VOLUME['name'],
|
'sofs_path': 'cinder/volumes/00/' + volume.name,
|
||||||
'format': 'raw'
|
'format': 'raw'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.assertEqual(expected_conn_info, conn_info)
|
self.assertEqual(expected_conn_info, conn_info)
|
||||||
mock_get_active_image_from_info.assert_called_once_with(_FAKE_VOLUME)
|
mock_get_active_image_from_info.assert_called_once_with(volume)
|
||||||
mock_qemu_img_info.assert_called_once_with(_FAKE_VOL_PATH)
|
mock_qemu_img_info.assert_called_once_with(_FAKE_VOL_PATH)
|
||||||
|
|
||||||
@mock.patch("cinder.image.image_utils.resize_image")
|
@mock.patch("cinder.image.image_utils.resize_image")
|
||||||
@ -236,7 +260,7 @@ class ScalityDriverTestCase(test.TestCase):
|
|||||||
info.file_format = 'raw'
|
info.file_format = 'raw'
|
||||||
mock_qemu_img_info.return_value = info
|
mock_qemu_img_info.return_value = info
|
||||||
|
|
||||||
self.drv.extend_volume(_FAKE_VOLUME, 2)
|
self.drv.extend_volume(self._simple_volume(), 2)
|
||||||
|
|
||||||
mock_qemu_img_info.assert_called_once_with(_FAKE_VOL_PATH)
|
mock_qemu_img_info.assert_called_once_with(_FAKE_VOL_PATH)
|
||||||
|
|
||||||
@ -249,7 +273,7 @@ class ScalityDriverTestCase(test.TestCase):
|
|||||||
mock_qemu_img_info.return_value = info
|
mock_qemu_img_info.return_value = info
|
||||||
|
|
||||||
self.assertRaises(exception.InvalidVolume,
|
self.assertRaises(exception.InvalidVolume,
|
||||||
self.drv.extend_volume, _FAKE_VOLUME, 2)
|
self.drv.extend_volume, self._simple_volume(), 2)
|
||||||
|
|
||||||
@mock.patch("cinder.image.image_utils.resize_image")
|
@mock.patch("cinder.image.image_utils.resize_image")
|
||||||
@mock.patch("cinder.image.image_utils.convert_image")
|
@mock.patch("cinder.image.image_utils.convert_image")
|
||||||
@ -260,8 +284,8 @@ class ScalityDriverTestCase(test.TestCase):
|
|||||||
mock.patch.object(self.drv, '_set_rw_permissions_for_all') as \
|
mock.patch.object(self.drv, '_set_rw_permissions_for_all') as \
|
||||||
mock_set_rw_permissions:
|
mock_set_rw_permissions:
|
||||||
mock_read_info_file.side_effect = IOError(errno.ENOENT, '')
|
mock_read_info_file.side_effect = IOError(errno.ENOENT, '')
|
||||||
self.drv._copy_volume_from_snapshot(_FAKE_SNAPSHOT,
|
self.drv._copy_volume_from_snapshot(self._simple_snapshot(),
|
||||||
_FAKE_VOLUME, 1)
|
self._simple_volume(), 1)
|
||||||
|
|
||||||
mock_read_info_file.assert_called_once_with("%s.info" % _FAKE_VOL_PATH)
|
mock_read_info_file.assert_called_once_with("%s.info" % _FAKE_VOL_PATH)
|
||||||
mock_convert_image.assert_called_once_with(_FAKE_SNAP_PATH,
|
mock_convert_image.assert_called_once_with(_FAKE_SNAP_PATH,
|
||||||
@ -276,10 +300,11 @@ class ScalityDriverTestCase(test.TestCase):
|
|||||||
def test_copy_volume_from_snapshot(self, mock_qemu_img_info,
|
def test_copy_volume_from_snapshot(self, mock_qemu_img_info,
|
||||||
mock_convert_image, mock_resize_image):
|
mock_convert_image, mock_resize_image):
|
||||||
|
|
||||||
new_volume = {'name': 'volume-3fa63b02-1fe5-11e5-b492-abf97a8fb23b',
|
new_volume = self._simple_volume(
|
||||||
'id': '3fa63b02-1fe5-11e5-b492-abf97a8fb23b',
|
display_name='volume-3fa63b02-1fe5-11e5-b492-abf97a8fb23b',
|
||||||
'provider_location': 'fake_share'}
|
id='3fa63b02-1fe5-11e5-b492-abf97a8fb23b',
|
||||||
new_vol_path = os.path.join(_FAKE_VOL_BASEDIR, new_volume['name'])
|
provider_location='fake_share')
|
||||||
|
new_vol_path = os.path.join(_FAKE_VOL_BASEDIR, new_volume.name)
|
||||||
|
|
||||||
info = imageutils.QemuImgInfo()
|
info = imageutils.QemuImgInfo()
|
||||||
info.file_format = 'raw'
|
info.file_format = 'raw'
|
||||||
@ -290,7 +315,7 @@ class ScalityDriverTestCase(test.TestCase):
|
|||||||
mock_read_info_file, \
|
mock_read_info_file, \
|
||||||
mock.patch.object(self.drv, '_set_rw_permissions_for_all') as \
|
mock.patch.object(self.drv, '_set_rw_permissions_for_all') as \
|
||||||
mock_set_rw_permissions:
|
mock_set_rw_permissions:
|
||||||
self.drv._copy_volume_from_snapshot(_FAKE_SNAPSHOT,
|
self.drv._copy_volume_from_snapshot(self._simple_snapshot(),
|
||||||
new_volume, 1)
|
new_volume, 1)
|
||||||
|
|
||||||
mock_read_info_file.assert_called_once_with("%s.info" % _FAKE_VOL_PATH)
|
mock_read_info_file.assert_called_once_with("%s.info" % _FAKE_VOL_PATH)
|
||||||
@ -311,9 +336,9 @@ class ScalityDriverTestCase(test.TestCase):
|
|||||||
info.file_format = 'raw'
|
info.file_format = 'raw'
|
||||||
mock_qemu_img_info.return_value = info
|
mock_qemu_img_info.return_value = info
|
||||||
|
|
||||||
backup = {'volume_id': _FAKE_VOLUME['id']}
|
backup = {'volume_id': _FAKE_VOLUME_ID}
|
||||||
mock_backup_service = mock.MagicMock()
|
mock_backup_service = mock.MagicMock()
|
||||||
self.drv.db.volume_get.return_value = _FAKE_VOLUME
|
self.drv.db.volume_get.return_value = self._simple_volume()
|
||||||
|
|
||||||
self.drv.backup_volume(context, backup, mock_backup_service)
|
self.drv.backup_volume(context, backup, mock_backup_service)
|
||||||
|
|
||||||
@ -330,7 +355,7 @@ class ScalityDriverTestCase(test.TestCase):
|
|||||||
info.file_format = 'qcow2'
|
info.file_format = 'qcow2'
|
||||||
mock_qemu_img_info.return_value = info
|
mock_qemu_img_info.return_value = info
|
||||||
|
|
||||||
self.drv.db.volume_get.return_value = _FAKE_VOLUME
|
self.drv.db.volume_get.return_value = self._simple_volume()
|
||||||
|
|
||||||
self.assertRaises(exception.InvalidVolume, self.drv.backup_volume,
|
self.assertRaises(exception.InvalidVolume, self.drv.backup_volume,
|
||||||
context, _FAKE_BACKUP, mock.MagicMock())
|
context, _FAKE_BACKUP, mock.MagicMock())
|
||||||
@ -345,8 +370,8 @@ class ScalityDriverTestCase(test.TestCase):
|
|||||||
info.backing_file = 'fake.img'
|
info.backing_file = 'fake.img'
|
||||||
mock_qemu_img_info.return_value = info
|
mock_qemu_img_info.return_value = info
|
||||||
|
|
||||||
backup = {'volume_id': _FAKE_VOLUME['id']}
|
backup = {'volume_id': _FAKE_VOLUME_ID}
|
||||||
self.drv.db.volume_get.return_value = _FAKE_VOLUME
|
self.drv.db.volume_get.return_value = self._simple_volume()
|
||||||
|
|
||||||
self.assertRaises(exception.InvalidVolume, self.drv.backup_volume,
|
self.assertRaises(exception.InvalidVolume, self.drv.backup_volume,
|
||||||
context, backup, mock.MagicMock())
|
context, backup, mock.MagicMock())
|
||||||
@ -358,10 +383,10 @@ class ScalityDriverTestCase(test.TestCase):
|
|||||||
def test_restore_bakup(self, mock_open, mock_temporary_chown):
|
def test_restore_bakup(self, mock_open, mock_temporary_chown):
|
||||||
mock_backup_service = mock.MagicMock()
|
mock_backup_service = mock.MagicMock()
|
||||||
|
|
||||||
self.drv.restore_backup(context, _FAKE_BACKUP, _FAKE_VOLUME,
|
self.drv.restore_backup(context, _FAKE_BACKUP, self._simple_volume(),
|
||||||
mock_backup_service)
|
mock_backup_service)
|
||||||
|
|
||||||
mock_temporary_chown.assert_called_once_with(_FAKE_VOL_PATH)
|
mock_temporary_chown.assert_called_once_with(_FAKE_VOL_PATH)
|
||||||
mock_open.assert_called_once_with(_FAKE_VOL_PATH, 'wb')
|
mock_open.assert_called_once_with(_FAKE_VOL_PATH, 'wb')
|
||||||
mock_backup_service.restore.assert_called_once_with(
|
mock_backup_service.restore.assert_called_once_with(
|
||||||
_FAKE_BACKUP, _FAKE_VOLUME['id'], mock_open().__enter__())
|
_FAKE_BACKUP, _FAKE_VOLUME_ID, mock_open().__enter__())
|
||||||
|
@ -21,11 +21,10 @@ import mock
|
|||||||
from oslo_utils import fileutils
|
from oslo_utils import fileutils
|
||||||
|
|
||||||
from cinder import context
|
from cinder import context
|
||||||
from cinder import db
|
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.image import image_utils
|
from cinder.image import image_utils
|
||||||
from cinder import objects
|
|
||||||
from cinder import test
|
from cinder import test
|
||||||
|
from cinder.tests.unit import fake_snapshot
|
||||||
from cinder.tests.unit import fake_volume
|
from cinder.tests.unit import fake_volume
|
||||||
from cinder.volume.drivers import remotefs
|
from cinder.volume.drivers import remotefs
|
||||||
from cinder.volume.drivers import smbfs
|
from cinder.volume.drivers import smbfs
|
||||||
@ -39,7 +38,7 @@ def requires_allocation_data_update(expected_size):
|
|||||||
inst._smbfs_driver,
|
inst._smbfs_driver,
|
||||||
'update_disk_allocation_data') as fake_update:
|
'update_disk_allocation_data') as fake_update:
|
||||||
func(inst, *args, **kwargs)
|
func(inst, *args, **kwargs)
|
||||||
fake_update.assert_called_once_with(inst._FAKE_VOLUME,
|
fake_update.assert_called_once_with(inst.volume,
|
||||||
expected_size)
|
expected_size)
|
||||||
return inner
|
return inner
|
||||||
return wrapper
|
return wrapper
|
||||||
@ -55,18 +54,10 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
_FAKE_TOTAL_SIZE = '2048'
|
_FAKE_TOTAL_SIZE = '2048'
|
||||||
_FAKE_TOTAL_AVAILABLE = '1024'
|
_FAKE_TOTAL_AVAILABLE = '1024'
|
||||||
_FAKE_TOTAL_ALLOCATED = 1024
|
_FAKE_TOTAL_ALLOCATED = 1024
|
||||||
_FAKE_VOLUME = {'id': '4f711859-4928-4cb7-801a-a50c37ceaccc',
|
|
||||||
'size': 1,
|
|
||||||
'provider_location': _FAKE_SHARE,
|
|
||||||
'name': _FAKE_VOLUME_NAME,
|
|
||||||
'status': 'available'}
|
|
||||||
_FAKE_MNT_POINT = os.path.join(_FAKE_MNT_BASE, _FAKE_SHARE_HASH)
|
_FAKE_MNT_POINT = os.path.join(_FAKE_MNT_BASE, _FAKE_SHARE_HASH)
|
||||||
_FAKE_VOLUME_PATH = os.path.join(_FAKE_MNT_POINT, _FAKE_VOLUME_NAME)
|
_FAKE_VOLUME_PATH = os.path.join(_FAKE_MNT_POINT, _FAKE_VOLUME_NAME)
|
||||||
_FAKE_SNAPSHOT_ID = '5g811859-4928-4cb7-801a-a50c37ceacba'
|
_FAKE_VOLUME_SIZE = 1
|
||||||
_FAKE_SNAPSHOT = {'id': _FAKE_SNAPSHOT_ID,
|
_FAKE_SNAPSHOT_ID = '50811859-4928-4cb7-801a-a50c37ceacba'
|
||||||
'volume': _FAKE_VOLUME,
|
|
||||||
'status': 'available',
|
|
||||||
'volume_size': 1}
|
|
||||||
_FAKE_SNAPSHOT_PATH = (
|
_FAKE_SNAPSHOT_PATH = (
|
||||||
_FAKE_VOLUME_PATH + '-snapshot' + _FAKE_SNAPSHOT_ID)
|
_FAKE_VOLUME_PATH + '-snapshot' + _FAKE_SNAPSHOT_ID)
|
||||||
_FAKE_SHARE_OPTS = '-o username=Administrator,password=12345'
|
_FAKE_SHARE_OPTS = '-o username=Administrator,password=12345'
|
||||||
@ -93,6 +84,22 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
self._smbfs_driver.base = self._FAKE_MNT_BASE
|
self._smbfs_driver.base = self._FAKE_MNT_BASE
|
||||||
self._smbfs_driver._alloc_info_file_path = (
|
self._smbfs_driver._alloc_info_file_path = (
|
||||||
self._FAKE_ALLOCATION_DATA_PATH)
|
self._FAKE_ALLOCATION_DATA_PATH)
|
||||||
|
self.context = context.get_admin_context()
|
||||||
|
|
||||||
|
self.volume = fake_volume.fake_volume_obj(
|
||||||
|
self.context,
|
||||||
|
id='4f711859-4928-4cb7-801a-a50c37ceaccc',
|
||||||
|
size=self._FAKE_VOLUME_SIZE,
|
||||||
|
provider_location=self._FAKE_SHARE,
|
||||||
|
display_name=self._FAKE_VOLUME_NAME,
|
||||||
|
status='available')
|
||||||
|
|
||||||
|
self.snapshot = fake_snapshot.fake_snapshot_obj(
|
||||||
|
self.context,
|
||||||
|
id=self._FAKE_SNAPSHOT_ID,
|
||||||
|
status='available',
|
||||||
|
volume_size=1)
|
||||||
|
self.snapshot.volume = self.volume
|
||||||
|
|
||||||
self.addCleanup(mock.patch.stopall)
|
self.addCleanup(mock.patch.stopall)
|
||||||
|
|
||||||
@ -137,24 +144,24 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
fake_alloc_data = self._get_fake_allocation_data()
|
fake_alloc_data = self._get_fake_allocation_data()
|
||||||
if volume_exists:
|
if volume_exists:
|
||||||
fake_alloc_data[self._FAKE_SHARE_HASH][
|
fake_alloc_data[self._FAKE_SHARE_HASH][
|
||||||
self._FAKE_VOLUME_NAME] = self._FAKE_VOLUME['size']
|
self._FAKE_VOLUME_NAME] = self.volume.size
|
||||||
|
|
||||||
self._smbfs_driver._allocation_data = fake_alloc_data
|
self._smbfs_driver._allocation_data = fake_alloc_data
|
||||||
|
|
||||||
self._smbfs_driver.update_disk_allocation_data(self._FAKE_VOLUME,
|
self._smbfs_driver.update_disk_allocation_data(self.volume,
|
||||||
virtual_size_gb)
|
virtual_size_gb)
|
||||||
|
|
||||||
vol_allocated_size = fake_alloc_data[self._FAKE_SHARE_HASH].get(
|
vol_allocated_size = fake_alloc_data[self._FAKE_SHARE_HASH].get(
|
||||||
self._FAKE_VOLUME_NAME, None)
|
self._FAKE_VOLUME_NAME, None)
|
||||||
if not virtual_size_gb:
|
if not virtual_size_gb:
|
||||||
expected_total_allocated = (self._FAKE_TOTAL_ALLOCATED -
|
expected_total_allocated = (self._FAKE_TOTAL_ALLOCATED -
|
||||||
self._FAKE_VOLUME['size'])
|
self.volume.size)
|
||||||
|
|
||||||
self.assertIsNone(vol_allocated_size)
|
self.assertIsNone(vol_allocated_size)
|
||||||
else:
|
else:
|
||||||
expected_total_allocated = (self._FAKE_TOTAL_ALLOCATED +
|
expected_total_allocated = (self._FAKE_TOTAL_ALLOCATED +
|
||||||
virtual_size_gb -
|
virtual_size_gb -
|
||||||
self._FAKE_VOLUME['size'])
|
self.volume.size)
|
||||||
self.assertEqual(virtual_size_gb, vol_allocated_size)
|
self.assertEqual(virtual_size_gb, vol_allocated_size)
|
||||||
|
|
||||||
update_func.assert_called_once_with()
|
update_func.assert_called_once_with()
|
||||||
@ -168,11 +175,11 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
|
|
||||||
def test_update_allocation_data_volume_extended(self):
|
def test_update_allocation_data_volume_extended(self):
|
||||||
self._test_update_allocation_data(
|
self._test_update_allocation_data(
|
||||||
virtual_size_gb=self._FAKE_VOLUME['size'] + 1)
|
virtual_size_gb=self.volume.size + 1)
|
||||||
|
|
||||||
def test_update_allocation_data_volume_created(self):
|
def test_update_allocation_data_volume_created(self):
|
||||||
self._test_update_allocation_data(
|
self._test_update_allocation_data(
|
||||||
virtual_size_gb=self._FAKE_VOLUME['size'])
|
virtual_size_gb=self.volume.size)
|
||||||
|
|
||||||
@requires_allocation_data_update(expected_size=None)
|
@requires_allocation_data_update(expected_size=None)
|
||||||
def test_delete_volume(self):
|
def test_delete_volume(self):
|
||||||
@ -191,7 +198,7 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
return_value=fake_vol_info)
|
return_value=fake_vol_info)
|
||||||
|
|
||||||
with mock.patch('os.path.exists', lambda x: True):
|
with mock.patch('os.path.exists', lambda x: True):
|
||||||
drv.delete_volume(self._FAKE_VOLUME)
|
drv.delete_volume(self.volume)
|
||||||
|
|
||||||
fake_ensure_mounted.assert_called_once_with(self._FAKE_SHARE)
|
fake_ensure_mounted.assert_called_once_with(self._FAKE_SHARE)
|
||||||
drv._delete.assert_any_call(
|
drv._delete.assert_any_call(
|
||||||
@ -266,12 +273,12 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
if volume_exists:
|
if volume_exists:
|
||||||
self.assertRaises(exception.InvalidVolume,
|
self.assertRaises(exception.InvalidVolume,
|
||||||
self._smbfs_driver._do_create_volume,
|
self._smbfs_driver._do_create_volume,
|
||||||
self._FAKE_VOLUME)
|
self.volume)
|
||||||
return
|
return
|
||||||
|
|
||||||
self._smbfs_driver._do_create_volume(self._FAKE_VOLUME)
|
self._smbfs_driver._do_create_volume(self.volume)
|
||||||
expected_create_args = [mock.sentinel.vol_path,
|
expected_create_args = [mock.sentinel.vol_path,
|
||||||
self._FAKE_VOLUME['size']]
|
self.volume.size]
|
||||||
if volume_format in [self._smbfs_driver._DISK_FORMAT_VHDX,
|
if volume_format in [self._smbfs_driver._DISK_FORMAT_VHDX,
|
||||||
self._smbfs_driver._DISK_FORMAT_VHD]:
|
self._smbfs_driver._DISK_FORMAT_VHD]:
|
||||||
expected_create_args.append(volume_format)
|
expected_create_args.append(volume_format)
|
||||||
@ -320,14 +327,14 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
if not mounted_shares:
|
if not mounted_shares:
|
||||||
self.assertRaises(exception.SmbfsNoSharesMounted,
|
self.assertRaises(exception.SmbfsNoSharesMounted,
|
||||||
self._smbfs_driver._find_share,
|
self._smbfs_driver._find_share,
|
||||||
self._FAKE_VOLUME['size'])
|
self.volume.size)
|
||||||
elif not eligible_shares:
|
elif not eligible_shares:
|
||||||
self.assertRaises(exception.SmbfsNoSuitableShareFound,
|
self.assertRaises(exception.SmbfsNoSuitableShareFound,
|
||||||
self._smbfs_driver._find_share,
|
self._smbfs_driver._find_share,
|
||||||
self._FAKE_VOLUME['size'])
|
self.volume.size)
|
||||||
else:
|
else:
|
||||||
ret_value = self._smbfs_driver._find_share(
|
ret_value = self._smbfs_driver._find_share(
|
||||||
self._FAKE_VOLUME['size'])
|
self.volume.size)
|
||||||
# The eligible share with the minimum allocated space
|
# The eligible share with the minimum allocated space
|
||||||
# will be selected
|
# will be selected
|
||||||
self.assertEqual('fake_share3', ret_value)
|
self.assertEqual('fake_share3', ret_value)
|
||||||
@ -404,12 +411,12 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
expected_vol_path if volume_exists else None)
|
expected_vol_path if volume_exists else None)
|
||||||
mock_get_volume_format.return_value = volume_format
|
mock_get_volume_format.return_value = volume_format
|
||||||
|
|
||||||
ret_val = drv.local_path(self._FAKE_VOLUME)
|
ret_val = drv.local_path(self.volume)
|
||||||
|
|
||||||
if volume_exists:
|
if volume_exists:
|
||||||
self.assertFalse(mock_get_volume_format.called)
|
self.assertFalse(mock_get_volume_format.called)
|
||||||
else:
|
else:
|
||||||
mock_get_volume_format.assert_called_once_with(self._FAKE_VOLUME)
|
mock_get_volume_format.assert_called_once_with(self.volume)
|
||||||
self.assertEqual(expected_vol_path, ret_val)
|
self.assertEqual(expected_vol_path, ret_val)
|
||||||
|
|
||||||
def test_get_existing_volume_path(self):
|
def test_get_existing_volume_path(self):
|
||||||
@ -422,7 +429,7 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
def test_get_local_volume_path_template(self, mock_get_local_dir):
|
def test_get_local_volume_path_template(self, mock_get_local_dir):
|
||||||
mock_get_local_dir.return_value = self._FAKE_MNT_POINT
|
mock_get_local_dir.return_value = self._FAKE_MNT_POINT
|
||||||
ret_val = self._smbfs_driver._get_local_volume_path_template(
|
ret_val = self._smbfs_driver._get_local_volume_path_template(
|
||||||
self._FAKE_VOLUME)
|
self.volume)
|
||||||
self.assertEqual(self._FAKE_VOLUME_PATH, ret_val)
|
self.assertEqual(self._FAKE_VOLUME_PATH, ret_val)
|
||||||
|
|
||||||
@mock.patch('os.path.exists')
|
@mock.patch('os.path.exists')
|
||||||
@ -457,7 +464,7 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
mock_qemu_img_info.return_value.file_format = volume_format
|
mock_qemu_img_info.return_value.file_format = volume_format
|
||||||
mock_get_format_spec.return_value = volume_format
|
mock_get_format_spec.return_value = volume_format
|
||||||
|
|
||||||
ret_val = self._smbfs_driver.get_volume_format(self._FAKE_VOLUME,
|
ret_val = self._smbfs_driver.get_volume_format(self.volume,
|
||||||
qemu_format)
|
qemu_format)
|
||||||
|
|
||||||
if volume_exists:
|
if volume_exists:
|
||||||
@ -465,7 +472,7 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
self._FAKE_VOLUME_NAME)
|
self._FAKE_VOLUME_NAME)
|
||||||
self.assertFalse(mock_get_format_spec.called)
|
self.assertFalse(mock_get_format_spec.called)
|
||||||
else:
|
else:
|
||||||
mock_get_format_spec.assert_called_once_with(self._FAKE_VOLUME)
|
mock_get_format_spec.assert_called_once_with(self.volume)
|
||||||
self.assertFalse(mock_qemu_img_info.called)
|
self.assertFalse(mock_qemu_img_info.called)
|
||||||
|
|
||||||
return ret_val
|
return ret_val
|
||||||
@ -506,7 +513,7 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
'data': fake_data,
|
'data': fake_data,
|
||||||
'mount_point_base': self._FAKE_MNT_BASE}
|
'mount_point_base': self._FAKE_MNT_BASE}
|
||||||
ret_val = self._smbfs_driver.initialize_connection(
|
ret_val = self._smbfs_driver.initialize_connection(
|
||||||
self._FAKE_VOLUME, None)
|
self.volume, None)
|
||||||
|
|
||||||
self.assertEqual(expected, ret_val)
|
self.assertEqual(expected, ret_val)
|
||||||
|
|
||||||
@ -529,9 +536,9 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
if extend_failed:
|
if extend_failed:
|
||||||
self.assertRaises(exception.ExtendVolumeError,
|
self.assertRaises(exception.ExtendVolumeError,
|
||||||
drv.extend_volume,
|
drv.extend_volume,
|
||||||
self._FAKE_VOLUME, mock.sentinel.new_size)
|
self.volume, mock.sentinel.new_size)
|
||||||
else:
|
else:
|
||||||
drv.extend_volume(self._FAKE_VOLUME, mock.sentinel.new_size)
|
drv.extend_volume(self.volume, mock.sentinel.new_size)
|
||||||
|
|
||||||
if image_format in (drv._DISK_FORMAT_VHDX,
|
if image_format in (drv._DISK_FORMAT_VHDX,
|
||||||
drv._DISK_FORMAT_VHD_LEGACY):
|
drv._DISK_FORMAT_VHD_LEGACY):
|
||||||
@ -576,14 +583,14 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
if has_snapshots:
|
if has_snapshots:
|
||||||
self.assertRaises(exception.InvalidVolume,
|
self.assertRaises(exception.InvalidVolume,
|
||||||
self._smbfs_driver._check_extend_volume_support,
|
self._smbfs_driver._check_extend_volume_support,
|
||||||
self._FAKE_VOLUME, 2)
|
self.volume, 2)
|
||||||
elif not is_eligible:
|
elif not is_eligible:
|
||||||
self.assertRaises(exception.ExtendVolumeError,
|
self.assertRaises(exception.ExtendVolumeError,
|
||||||
self._smbfs_driver._check_extend_volume_support,
|
self._smbfs_driver._check_extend_volume_support,
|
||||||
self._FAKE_VOLUME, 2)
|
self.volume, 2)
|
||||||
else:
|
else:
|
||||||
self._smbfs_driver._check_extend_volume_support(
|
self._smbfs_driver._check_extend_volume_support(
|
||||||
self._FAKE_VOLUME, 2)
|
self.volume, 2)
|
||||||
self._smbfs_driver._is_share_eligible.assert_called_once_with(
|
self._smbfs_driver._is_share_eligible.assert_called_once_with(
|
||||||
self._FAKE_SHARE, 1)
|
self._FAKE_SHARE, 1)
|
||||||
|
|
||||||
@ -596,35 +603,35 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
def test_check_extend_volume_uneligible_share(self):
|
def test_check_extend_volume_uneligible_share(self):
|
||||||
self._test_check_extend_support(is_eligible=False)
|
self._test_check_extend_support(is_eligible=False)
|
||||||
|
|
||||||
@requires_allocation_data_update(expected_size=_FAKE_VOLUME['size'])
|
@requires_allocation_data_update(expected_size=_FAKE_VOLUME_SIZE)
|
||||||
@mock.patch.object(remotefs.RemoteFSSnapDriver, 'create_volume')
|
@mock.patch.object(remotefs.RemoteFSSnapDriver, 'create_volume')
|
||||||
def test_create_volume_base(self, mock_create_volume):
|
def test_create_volume_base(self, mock_create_volume):
|
||||||
self._smbfs_driver.create_volume(self._FAKE_VOLUME)
|
self._smbfs_driver.create_volume(self.volume)
|
||||||
mock_create_volume.assert_called_once_with(self._FAKE_VOLUME)
|
mock_create_volume.assert_called_once_with(self.volume)
|
||||||
|
|
||||||
@requires_allocation_data_update(expected_size=_FAKE_VOLUME['size'])
|
@requires_allocation_data_update(expected_size=_FAKE_VOLUME_SIZE)
|
||||||
@mock.patch.object(smbfs.SmbfsDriver,
|
@mock.patch.object(smbfs.SmbfsDriver,
|
||||||
'_create_volume_from_snapshot')
|
'_create_volume_from_snapshot')
|
||||||
def test_create_volume_from_snapshot(self, mock_create_volume):
|
def test_create_volume_from_snapshot(self, mock_create_volume):
|
||||||
self._smbfs_driver.create_volume_from_snapshot(self._FAKE_VOLUME,
|
self._smbfs_driver.create_volume_from_snapshot(self.volume,
|
||||||
self._FAKE_SNAPSHOT)
|
self.snapshot)
|
||||||
mock_create_volume.assert_called_once_with(self._FAKE_VOLUME,
|
mock_create_volume.assert_called_once_with(self.volume,
|
||||||
self._FAKE_SNAPSHOT)
|
self.snapshot)
|
||||||
|
|
||||||
@requires_allocation_data_update(expected_size=_FAKE_VOLUME['size'])
|
@requires_allocation_data_update(expected_size=_FAKE_VOLUME_SIZE)
|
||||||
@mock.patch.object(smbfs.SmbfsDriver, '_create_cloned_volume')
|
@mock.patch.object(smbfs.SmbfsDriver, '_create_cloned_volume')
|
||||||
def test_create_cloned_volume(self, mock_create_volume):
|
def test_create_cloned_volume(self, mock_create_volume):
|
||||||
self._smbfs_driver.create_cloned_volume(self._FAKE_VOLUME,
|
self._smbfs_driver.create_cloned_volume(self.volume,
|
||||||
mock.sentinel.src_vol)
|
mock.sentinel.src_vol)
|
||||||
mock_create_volume.assert_called_once_with(self._FAKE_VOLUME,
|
mock_create_volume.assert_called_once_with(self.volume,
|
||||||
mock.sentinel.src_vol)
|
mock.sentinel.src_vol)
|
||||||
|
|
||||||
def test_create_volume_from_in_use_snapshot(self):
|
def test_create_volume_from_unavailable_snapshot(self):
|
||||||
fake_snapshot = {'status': 'in-use'}
|
self.snapshot.status = 'error'
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.InvalidSnapshot,
|
exception.InvalidSnapshot,
|
||||||
self._smbfs_driver.create_volume_from_snapshot,
|
self._smbfs_driver.create_volume_from_snapshot,
|
||||||
self._FAKE_VOLUME, fake_snapshot)
|
self.volume, self.snapshot)
|
||||||
|
|
||||||
def test_copy_volume_from_snapshot(self):
|
def test_copy_volume_from_snapshot(self):
|
||||||
drv = self._smbfs_driver
|
drv = self._smbfs_driver
|
||||||
@ -651,10 +658,10 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
with mock.patch.object(image_utils, 'convert_image') as (
|
with mock.patch.object(image_utils, 'convert_image') as (
|
||||||
fake_convert_image):
|
fake_convert_image):
|
||||||
drv._copy_volume_from_snapshot(
|
drv._copy_volume_from_snapshot(
|
||||||
self._FAKE_SNAPSHOT, self._FAKE_VOLUME,
|
self.snapshot, self.volume,
|
||||||
self._FAKE_VOLUME['size'])
|
self.volume.size)
|
||||||
drv._extend_volume.assert_called_once_with(
|
drv._extend_volume.assert_called_once_with(
|
||||||
self._FAKE_VOLUME, self._FAKE_VOLUME['size'])
|
self.volume, self.volume.size)
|
||||||
fake_convert_image.assert_called_once_with(
|
fake_convert_image.assert_called_once_with(
|
||||||
self._FAKE_VOLUME_PATH, self._FAKE_VOLUME_PATH[:-1], 'raw')
|
self._FAKE_VOLUME_PATH, self._FAKE_VOLUME_PATH[:-1], 'raw')
|
||||||
|
|
||||||
@ -668,7 +675,7 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
def _test_copy_image_to_volume(self, wrong_size_after_fetch=False):
|
def _test_copy_image_to_volume(self, wrong_size_after_fetch=False):
|
||||||
drv = self._smbfs_driver
|
drv = self._smbfs_driver
|
||||||
|
|
||||||
vol_size_bytes = self._FAKE_VOLUME['size'] << 30
|
vol_size_bytes = self.volume.size << 30
|
||||||
|
|
||||||
fake_img_info = mock.MagicMock()
|
fake_img_info = mock.MagicMock()
|
||||||
|
|
||||||
@ -696,12 +703,12 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.ImageUnacceptable,
|
exception.ImageUnacceptable,
|
||||||
drv.copy_image_to_volume,
|
drv.copy_image_to_volume,
|
||||||
mock.sentinel.context, self._FAKE_VOLUME,
|
mock.sentinel.context, self.volume,
|
||||||
mock.sentinel.image_service,
|
mock.sentinel.image_service,
|
||||||
mock.sentinel.image_id)
|
mock.sentinel.image_id)
|
||||||
else:
|
else:
|
||||||
drv.copy_image_to_volume(
|
drv.copy_image_to_volume(
|
||||||
mock.sentinel.context, self._FAKE_VOLUME,
|
mock.sentinel.context, self.volume,
|
||||||
mock.sentinel.image_service,
|
mock.sentinel.image_service,
|
||||||
mock.sentinel.image_id)
|
mock.sentinel.image_id)
|
||||||
fake_fetch.assert_called_once_with(
|
fake_fetch.assert_called_once_with(
|
||||||
@ -711,8 +718,8 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
mock.sentinel.block_size)
|
mock.sentinel.block_size)
|
||||||
drv._do_extend_volume.assert_called_once_with(
|
drv._do_extend_volume.assert_called_once_with(
|
||||||
self._FAKE_VOLUME_PATH,
|
self._FAKE_VOLUME_PATH,
|
||||||
self._FAKE_VOLUME['size'],
|
self.volume.size,
|
||||||
self._FAKE_VOLUME['name'])
|
self.volume.name)
|
||||||
|
|
||||||
def test_copy_image_to_volume(self):
|
def test_copy_image_to_volume(self):
|
||||||
self._test_copy_image_to_volume()
|
self._test_copy_image_to_volume()
|
||||||
@ -740,43 +747,34 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
self._FAKE_TOTAL_ALLOCATED)
|
self._FAKE_TOTAL_ALLOCATED)
|
||||||
self.assertEqual(expected, ret_val)
|
self.assertEqual(expected, ret_val)
|
||||||
|
|
||||||
@ddt.data([True, False, False],
|
@ddt.data([False, False],
|
||||||
[False, False, False],
|
[True, True],
|
||||||
[True, True, True],
|
[False, True])
|
||||||
[False, True, True],
|
|
||||||
[False, False, True],
|
|
||||||
[True, False, True])
|
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
def test_get_volume_format_spec(self, volume_versioned_object,
|
def test_get_volume_format_spec(self,
|
||||||
volume_meta_contains_fmt,
|
volume_meta_contains_fmt,
|
||||||
volume_type_contains_fmt):
|
volume_type_contains_fmt):
|
||||||
|
self._smbfs_driver.configuration = copy.copy(self._FAKE_SMBFS_CONFIG)
|
||||||
|
|
||||||
fake_vol_meta_fmt = 'vhd'
|
fake_vol_meta_fmt = 'vhd'
|
||||||
fake_vol_type_fmt = 'vhdx'
|
fake_vol_type_fmt = 'vhdx'
|
||||||
|
|
||||||
volume_metadata = {}
|
volume_metadata = {}
|
||||||
volume_type_extra_specs = {}
|
volume_type_extra_specs = {}
|
||||||
|
|
||||||
fake_vol_dict = fake_volume.fake_db_volume()
|
|
||||||
del fake_vol_dict['name']
|
|
||||||
|
|
||||||
if volume_meta_contains_fmt:
|
if volume_meta_contains_fmt:
|
||||||
volume_metadata['volume_format'] = fake_vol_meta_fmt
|
volume_metadata['volume_format'] = fake_vol_meta_fmt
|
||||||
elif volume_type_contains_fmt:
|
elif volume_type_contains_fmt:
|
||||||
volume_type_extra_specs['smbfs:volume_format'] = fake_vol_type_fmt
|
volume_type_extra_specs['volume_format'] = fake_vol_type_fmt
|
||||||
|
|
||||||
ctxt = context.get_admin_context()
|
volume_type = fake_volume.fake_volume_type_obj(self.context)
|
||||||
volume_type = db.volume_type_create(
|
volume = fake_volume.fake_volume_obj(self.context)
|
||||||
ctxt, {'extra_specs': volume_type_extra_specs,
|
# Optional arguments are not set in _from_db_object,
|
||||||
'name': 'fake_vol_type'})
|
# so have to set explicitly here
|
||||||
fake_vol_dict.update(metadata=volume_metadata,
|
volume.volume_type = volume_type
|
||||||
volume_type_id=volume_type.id)
|
volume.metadata = volume_metadata
|
||||||
# We want to get a 'real' SqlA model object, not just a dict.
|
# Same for extra_specs and VolumeType
|
||||||
volume = db.volume_create(ctxt, fake_vol_dict)
|
volume_type.extra_specs = volume_type_extra_specs
|
||||||
volume = db.volume_get(ctxt, volume.id)
|
|
||||||
|
|
||||||
if volume_versioned_object:
|
|
||||||
volume = objects.Volume._from_db_object(ctxt, objects.Volume(),
|
|
||||||
volume)
|
|
||||||
|
|
||||||
resulted_fmt = self._smbfs_driver._get_volume_format_spec(volume)
|
resulted_fmt = self._smbfs_driver._get_volume_format_spec(volume)
|
||||||
|
|
||||||
@ -785,6 +783,6 @@ class SmbFsTestCase(test.TestCase):
|
|||||||
elif volume_type_contains_fmt:
|
elif volume_type_contains_fmt:
|
||||||
expected_fmt = fake_vol_type_fmt
|
expected_fmt = fake_vol_type_fmt
|
||||||
else:
|
else:
|
||||||
expected_fmt = None
|
expected_fmt = self._FAKE_SMBFS_CONFIG.smbfs_default_volume_format
|
||||||
|
|
||||||
self.assertEqual(expected_fmt, resulted_fmt)
|
self.assertEqual(expected_fmt, resulted_fmt)
|
||||||
|
@ -21,9 +21,12 @@ import mock
|
|||||||
from os_brick.remotefs import remotefs
|
from os_brick.remotefs import remotefs
|
||||||
from oslo_utils import units
|
from oslo_utils import units
|
||||||
|
|
||||||
|
from cinder import context
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.image import image_utils
|
from cinder.image import image_utils
|
||||||
from cinder import test
|
from cinder import test
|
||||||
|
from cinder.tests.unit import fake_snapshot
|
||||||
|
from cinder.tests.unit import fake_volume
|
||||||
from cinder.volume.drivers import vzstorage
|
from cinder.volume.drivers import vzstorage
|
||||||
|
|
||||||
|
|
||||||
@ -37,24 +40,16 @@ class VZStorageTestCase(test.TestCase):
|
|||||||
_FAKE_MNT_POINT = os.path.join(_FAKE_MNT_BASE, 'fake_hash')
|
_FAKE_MNT_POINT = os.path.join(_FAKE_MNT_BASE, 'fake_hash')
|
||||||
_FAKE_VOLUME_NAME = 'volume-4f711859-4928-4cb7-801a-a50c37ceaccc'
|
_FAKE_VOLUME_NAME = 'volume-4f711859-4928-4cb7-801a-a50c37ceaccc'
|
||||||
_FAKE_VOLUME_PATH = os.path.join(_FAKE_MNT_POINT, _FAKE_VOLUME_NAME)
|
_FAKE_VOLUME_PATH = os.path.join(_FAKE_MNT_POINT, _FAKE_VOLUME_NAME)
|
||||||
_FAKE_VOLUME = {'id': '4f711859-4928-4cb7-801a-a50c37ceaccc',
|
_FAKE_SNAPSHOT_ID = '50811859-4928-4cb7-801a-a50c37ceacba'
|
||||||
'size': 1,
|
|
||||||
'provider_location': _FAKE_SHARE,
|
|
||||||
'name': _FAKE_VOLUME_NAME,
|
|
||||||
'status': 'available'}
|
|
||||||
_FAKE_SNAPSHOT_ID = '5g811859-4928-4cb7-801a-a50c37ceacba'
|
|
||||||
_FAKE_SNAPSHOT_PATH = (
|
_FAKE_SNAPSHOT_PATH = (
|
||||||
_FAKE_VOLUME_PATH + '-snapshot' + _FAKE_SNAPSHOT_ID)
|
_FAKE_VOLUME_PATH + '-snapshot' + _FAKE_SNAPSHOT_ID)
|
||||||
_FAKE_SNAPSHOT = {'id': _FAKE_SNAPSHOT_ID,
|
|
||||||
'volume': _FAKE_VOLUME,
|
|
||||||
'status': 'available',
|
|
||||||
'volume_size': 1}
|
|
||||||
|
|
||||||
_FAKE_VZ_CONFIG = mock.MagicMock()
|
_FAKE_VZ_CONFIG = mock.MagicMock()
|
||||||
_FAKE_VZ_CONFIG.vzstorage_shares_config = '/fake/config/path'
|
_FAKE_VZ_CONFIG.vzstorage_shares_config = '/fake/config/path'
|
||||||
_FAKE_VZ_CONFIG.vzstorage_sparsed_volumes = False
|
_FAKE_VZ_CONFIG.vzstorage_sparsed_volumes = False
|
||||||
_FAKE_VZ_CONFIG.vzstorage_used_ratio = 0.7
|
_FAKE_VZ_CONFIG.vzstorage_used_ratio = 0.7
|
||||||
_FAKE_VZ_CONFIG.vzstorage_mount_point_base = _FAKE_MNT_BASE
|
_FAKE_VZ_CONFIG.vzstorage_mount_point_base = _FAKE_MNT_BASE
|
||||||
|
_FAKE_VZ_CONFIG.vzstorage_default_volume_format = 'raw'
|
||||||
_FAKE_VZ_CONFIG.nas_secure_file_operations = 'auto'
|
_FAKE_VZ_CONFIG.nas_secure_file_operations = 'auto'
|
||||||
_FAKE_VZ_CONFIG.nas_secure_file_permissions = 'auto'
|
_FAKE_VZ_CONFIG.nas_secure_file_permissions = 'auto'
|
||||||
|
|
||||||
@ -72,6 +67,26 @@ class VZStorageTestCase(test.TestCase):
|
|||||||
self._vz_driver._execute = mock.Mock()
|
self._vz_driver._execute = mock.Mock()
|
||||||
self._vz_driver.base = self._FAKE_MNT_BASE
|
self._vz_driver.base = self._FAKE_MNT_BASE
|
||||||
|
|
||||||
|
self.context = context.get_admin_context()
|
||||||
|
vol_type = fake_volume.fake_volume_type_obj(self.context)
|
||||||
|
vol_type.extra_specs = {}
|
||||||
|
_FAKE_VOLUME = {'id': '4f711859-4928-4cb7-801a-a50c37ceaccc',
|
||||||
|
'size': 1,
|
||||||
|
'provider_location': self._FAKE_SHARE,
|
||||||
|
'name': self._FAKE_VOLUME_NAME,
|
||||||
|
'status': 'available'}
|
||||||
|
self.vol = fake_volume.fake_volume_obj(self.context,
|
||||||
|
volume_type_id=vol_type.id,
|
||||||
|
**_FAKE_VOLUME)
|
||||||
|
self.vol.volume_type = vol_type
|
||||||
|
|
||||||
|
_FAKE_SNAPSHOT = {'id': self._FAKE_SNAPSHOT_ID,
|
||||||
|
'status': 'available',
|
||||||
|
'volume_size': 1}
|
||||||
|
self.snap = fake_snapshot.fake_snapshot_obj(self.context,
|
||||||
|
**_FAKE_SNAPSHOT)
|
||||||
|
self.snap.volume = self.vol
|
||||||
|
|
||||||
def _path_exists(self, path):
|
def _path_exists(self, path):
|
||||||
if path.startswith(self._FAKE_VZ_CONFIG.vzstorage_shares_config):
|
if path.startswith(self._FAKE_VZ_CONFIG.vzstorage_shares_config):
|
||||||
return True
|
return True
|
||||||
@ -135,9 +150,13 @@ class VZStorageTestCase(test.TestCase):
|
|||||||
file_format = 'raw'
|
file_format = 'raw'
|
||||||
info = mock.Mock()
|
info = mock.Mock()
|
||||||
info.file_format = file_format
|
info.file_format = file_format
|
||||||
|
snap_info = """{"volume_format": "raw",
|
||||||
|
"active": "%s"}""" % self.vol.id
|
||||||
with mock.patch.object(drv, '_qemu_img_info', return_value=info):
|
with mock.patch.object(drv, '_qemu_img_info', return_value=info):
|
||||||
ret = drv.initialize_connection(self._FAKE_VOLUME, None)
|
with mock.patch.object(drv, '_read_file',
|
||||||
name = drv.get_active_image_from_info(self._FAKE_VOLUME)
|
return_value=snap_info):
|
||||||
|
ret = drv.initialize_connection(self.vol, None)
|
||||||
|
name = drv.get_active_image_from_info(self.vol)
|
||||||
expected = {'driver_volume_type': 'vzstorage',
|
expected = {'driver_volume_type': 'vzstorage',
|
||||||
'data': {'export': self._FAKE_SHARE,
|
'data': {'export': self._FAKE_SHARE,
|
||||||
'format': file_format,
|
'format': file_format,
|
||||||
@ -197,9 +216,13 @@ class VZStorageTestCase(test.TestCase):
|
|||||||
drv._check_extend_volume_support = mock.Mock(return_value=True)
|
drv._check_extend_volume_support = mock.Mock(return_value=True)
|
||||||
drv._is_file_size_equal = mock.Mock(return_value=True)
|
drv._is_file_size_equal = mock.Mock(return_value=True)
|
||||||
|
|
||||||
|
snap_info = """{"volume_format": "raw",
|
||||||
|
"active": "%s"}""" % self.vol.id
|
||||||
with mock.patch.object(drv, 'local_path',
|
with mock.patch.object(drv, 'local_path',
|
||||||
return_value=self._FAKE_VOLUME_PATH):
|
return_value=self._FAKE_VOLUME_PATH):
|
||||||
drv.extend_volume(self._FAKE_VOLUME, 10)
|
with mock.patch.object(drv, '_read_file',
|
||||||
|
return_value=snap_info):
|
||||||
|
drv.extend_volume(self.vol, 10)
|
||||||
|
|
||||||
mock_resize_image.assert_called_once_with(self._FAKE_VOLUME_PATH, 10)
|
mock_resize_image.assert_called_once_with(self._FAKE_VOLUME_PATH, 10)
|
||||||
|
|
||||||
@ -218,13 +241,13 @@ class VZStorageTestCase(test.TestCase):
|
|||||||
if has_snapshots:
|
if has_snapshots:
|
||||||
self.assertRaises(exception.InvalidVolume,
|
self.assertRaises(exception.InvalidVolume,
|
||||||
drv._check_extend_volume_support,
|
drv._check_extend_volume_support,
|
||||||
self._FAKE_VOLUME, 2)
|
self.vol, 2)
|
||||||
elif not is_eligible:
|
elif not is_eligible:
|
||||||
self.assertRaises(exception.ExtendVolumeError,
|
self.assertRaises(exception.ExtendVolumeError,
|
||||||
drv._check_extend_volume_support,
|
drv._check_extend_volume_support,
|
||||||
self._FAKE_VOLUME, 2)
|
self.vol, 2)
|
||||||
else:
|
else:
|
||||||
drv._check_extend_volume_support(self._FAKE_VOLUME, 2)
|
drv._check_extend_volume_support(self.vol, 2)
|
||||||
drv._is_share_eligible.assert_called_once_with(self._FAKE_SHARE, 1)
|
drv._is_share_eligible.assert_called_once_with(self._FAKE_SHARE, 1)
|
||||||
|
|
||||||
def test_check_extend_support(self):
|
def test_check_extend_support(self):
|
||||||
@ -258,10 +281,10 @@ class VZStorageTestCase(test.TestCase):
|
|||||||
drv._extend_volume = mock.Mock()
|
drv._extend_volume = mock.Mock()
|
||||||
|
|
||||||
drv._copy_volume_from_snapshot(
|
drv._copy_volume_from_snapshot(
|
||||||
self._FAKE_SNAPSHOT, self._FAKE_VOLUME,
|
self.snap, self.vol,
|
||||||
self._FAKE_VOLUME['size'])
|
self.vol['size'])
|
||||||
drv._extend_volume.assert_called_once_with(
|
drv._extend_volume.assert_called_once_with(
|
||||||
self._FAKE_VOLUME, self._FAKE_VOLUME['size'])
|
self.vol, self.vol['size'])
|
||||||
mock_convert_image.assert_called_once_with(
|
mock_convert_image.assert_called_once_with(
|
||||||
self._FAKE_VOLUME_PATH, self._FAKE_VOLUME_PATH[:-1], 'raw')
|
self._FAKE_VOLUME_PATH, self._FAKE_VOLUME_PATH[:-1], 'raw')
|
||||||
|
|
||||||
@ -281,7 +304,7 @@ class VZStorageTestCase(test.TestCase):
|
|||||||
return_value=fake_vol_info)
|
return_value=fake_vol_info)
|
||||||
|
|
||||||
with mock.patch('os.path.exists', lambda x: True):
|
with mock.patch('os.path.exists', lambda x: True):
|
||||||
drv.delete_volume(self._FAKE_VOLUME)
|
drv.delete_volume(self.vol)
|
||||||
|
|
||||||
fake_ensure_mounted.assert_called_once_with(self._FAKE_SHARE)
|
fake_ensure_mounted.assert_called_once_with(self._FAKE_SHARE)
|
||||||
drv._delete.assert_any_call(
|
drv._delete.assert_any_call(
|
||||||
|
@ -17,9 +17,12 @@ import os
|
|||||||
import mock
|
import mock
|
||||||
from oslo_utils import units
|
from oslo_utils import units
|
||||||
|
|
||||||
|
from cinder import context
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.image import image_utils
|
from cinder.image import image_utils
|
||||||
from cinder import test
|
from cinder import test
|
||||||
|
from cinder.tests.unit import fake_snapshot
|
||||||
|
from cinder.tests.unit import fake_volume
|
||||||
from cinder.volume.drivers.windows import smbfs
|
from cinder.volume.drivers.windows import smbfs
|
||||||
|
|
||||||
|
|
||||||
@ -35,12 +38,6 @@ class WindowsSmbFsTestCase(test.TestCase):
|
|||||||
_FAKE_TOTAL_SIZE = '2048'
|
_FAKE_TOTAL_SIZE = '2048'
|
||||||
_FAKE_TOTAL_AVAILABLE = '1024'
|
_FAKE_TOTAL_AVAILABLE = '1024'
|
||||||
_FAKE_TOTAL_ALLOCATED = 1024
|
_FAKE_TOTAL_ALLOCATED = 1024
|
||||||
_FAKE_VOLUME = {'id': 'e8d76af4-cbb9-4b70-8e9e-5a133f1a1a66',
|
|
||||||
'size': 1,
|
|
||||||
'provider_location': _FAKE_SHARE}
|
|
||||||
_FAKE_SNAPSHOT = {'id': '35a23942-7625-4683-ad84-144b76e87a80',
|
|
||||||
'volume': _FAKE_VOLUME,
|
|
||||||
'volume_size': _FAKE_VOLUME['size']}
|
|
||||||
_FAKE_SHARE_OPTS = '-o username=Administrator,password=12345'
|
_FAKE_SHARE_OPTS = '-o username=Administrator,password=12345'
|
||||||
_FAKE_VOLUME_PATH = os.path.join(_FAKE_MNT_POINT,
|
_FAKE_VOLUME_PATH = os.path.join(_FAKE_MNT_POINT,
|
||||||
_FAKE_VOLUME_NAME + '.vhdx')
|
_FAKE_VOLUME_NAME + '.vhdx')
|
||||||
@ -56,6 +53,25 @@ class WindowsSmbFsTestCase(test.TestCase):
|
|||||||
self._smbfs_driver.local_path = mock.Mock(
|
self._smbfs_driver.local_path = mock.Mock(
|
||||||
return_value=self._FAKE_VOLUME_PATH)
|
return_value=self._FAKE_VOLUME_PATH)
|
||||||
|
|
||||||
|
def _simple_volume(self, **kwargs):
|
||||||
|
updates = {'id': 'e8d76af4-cbb9-4b70-8e9e-5a133f1a1a66',
|
||||||
|
'size': 1,
|
||||||
|
'provider_location': self._FAKE_SHARE}
|
||||||
|
updates.update(kwargs)
|
||||||
|
ctxt = context.get_admin_context()
|
||||||
|
return fake_volume.fake_volume_obj(ctxt, **updates)
|
||||||
|
|
||||||
|
def _simple_snapshot(self, **kwargs):
|
||||||
|
volume = self._simple_volume()
|
||||||
|
ctxt = context.get_admin_context()
|
||||||
|
updates = {'id': '35a23942-7625-4683-ad84-144b76e87a80',
|
||||||
|
'volume_size': volume.size,
|
||||||
|
'volume_id': volume.id}
|
||||||
|
updates.update(kwargs)
|
||||||
|
snapshot = fake_snapshot.fake_snapshot_obj(ctxt, **updates)
|
||||||
|
snapshot.volume = volume
|
||||||
|
return snapshot
|
||||||
|
|
||||||
def _test_create_volume(self, volume_exists=False, volume_format='vhdx'):
|
def _test_create_volume(self, volume_exists=False, volume_format='vhdx'):
|
||||||
self._smbfs_driver.create_dynamic_vhd = mock.MagicMock()
|
self._smbfs_driver.create_dynamic_vhd = mock.MagicMock()
|
||||||
fake_create = self._smbfs_driver._vhdutils.create_dynamic_vhd
|
fake_create = self._smbfs_driver._vhdutils.create_dynamic_vhd
|
||||||
@ -63,15 +79,16 @@ class WindowsSmbFsTestCase(test.TestCase):
|
|||||||
return_value=volume_format)
|
return_value=volume_format)
|
||||||
|
|
||||||
with mock.patch('os.path.exists', new=lambda x: volume_exists):
|
with mock.patch('os.path.exists', new=lambda x: volume_exists):
|
||||||
|
volume = self._simple_volume()
|
||||||
if volume_exists or volume_format not in ('vhd', 'vhdx'):
|
if volume_exists or volume_format not in ('vhd', 'vhdx'):
|
||||||
self.assertRaises(exception.InvalidVolume,
|
self.assertRaises(exception.InvalidVolume,
|
||||||
self._smbfs_driver._do_create_volume,
|
self._smbfs_driver._do_create_volume,
|
||||||
self._FAKE_VOLUME)
|
volume)
|
||||||
else:
|
else:
|
||||||
fake_vol_path = self._FAKE_VOLUME_PATH
|
fake_vol_path = self._FAKE_VOLUME_PATH
|
||||||
self._smbfs_driver._do_create_volume(self._FAKE_VOLUME)
|
self._smbfs_driver._do_create_volume(volume)
|
||||||
fake_create.assert_called_once_with(
|
fake_create.assert_called_once_with(
|
||||||
fake_vol_path, self._FAKE_VOLUME['size'] << 30)
|
fake_vol_path, volume.size << 30)
|
||||||
|
|
||||||
def test_create_volume(self):
|
def test_create_volume(self):
|
||||||
self._test_create_volume()
|
self._test_create_volume()
|
||||||
@ -120,7 +137,7 @@ class WindowsSmbFsTestCase(test.TestCase):
|
|||||||
self._smbfs_driver._vhdutils.create_differencing_vhd)
|
self._smbfs_driver._vhdutils.create_differencing_vhd)
|
||||||
|
|
||||||
self._smbfs_driver._do_create_snapshot(
|
self._smbfs_driver._do_create_snapshot(
|
||||||
self._FAKE_SNAPSHOT,
|
self._simple_snapshot(),
|
||||||
os.path.basename(self._FAKE_VOLUME_PATH),
|
os.path.basename(self._FAKE_VOLUME_PATH),
|
||||||
self._FAKE_SNAPSHOT_PATH)
|
self._FAKE_SNAPSHOT_PATH)
|
||||||
|
|
||||||
@ -156,8 +173,9 @@ class WindowsSmbFsTestCase(test.TestCase):
|
|||||||
|
|
||||||
with mock.patch.object(image_utils, 'upload_volume') as (
|
with mock.patch.object(image_utils, 'upload_volume') as (
|
||||||
fake_upload_volume):
|
fake_upload_volume):
|
||||||
|
volume = self._simple_volume()
|
||||||
drv.copy_volume_to_image(
|
drv.copy_volume_to_image(
|
||||||
mock.sentinel.context, self._FAKE_VOLUME,
|
mock.sentinel.context, volume,
|
||||||
mock.sentinel.image_service, fake_image_meta)
|
mock.sentinel.image_service, fake_image_meta)
|
||||||
|
|
||||||
expected_conversion = (
|
expected_conversion = (
|
||||||
@ -165,7 +183,7 @@ class WindowsSmbFsTestCase(test.TestCase):
|
|||||||
|
|
||||||
if expected_conversion:
|
if expected_conversion:
|
||||||
fake_temp_image_name = '%s.temp_image.%s.%s' % (
|
fake_temp_image_name = '%s.temp_image.%s.%s' % (
|
||||||
self._FAKE_VOLUME['id'],
|
volume.id,
|
||||||
fake_image_meta['id'],
|
fake_image_meta['id'],
|
||||||
drv._DISK_FORMAT_VHD)
|
drv._DISK_FORMAT_VHD)
|
||||||
fake_temp_image_path = os.path.join(
|
fake_temp_image_path = os.path.join(
|
||||||
@ -209,8 +227,9 @@ class WindowsSmbFsTestCase(test.TestCase):
|
|||||||
|
|
||||||
with mock.patch.object(image_utils,
|
with mock.patch.object(image_utils,
|
||||||
'fetch_to_volume_format') as fake_fetch:
|
'fetch_to_volume_format') as fake_fetch:
|
||||||
|
volume = self._simple_volume()
|
||||||
drv.copy_image_to_volume(
|
drv.copy_image_to_volume(
|
||||||
mock.sentinel.context, self._FAKE_VOLUME,
|
mock.sentinel.context, volume,
|
||||||
mock.sentinel.image_service,
|
mock.sentinel.image_service,
|
||||||
mock.sentinel.image_id)
|
mock.sentinel.image_id)
|
||||||
fake_fetch.assert_called_once_with(
|
fake_fetch.assert_called_once_with(
|
||||||
@ -221,13 +240,14 @@ class WindowsSmbFsTestCase(test.TestCase):
|
|||||||
mock.sentinel.block_size)
|
mock.sentinel.block_size)
|
||||||
drv._vhdutils.resize_vhd.assert_called_once_with(
|
drv._vhdutils.resize_vhd.assert_called_once_with(
|
||||||
self._FAKE_VOLUME_PATH,
|
self._FAKE_VOLUME_PATH,
|
||||||
self._FAKE_VOLUME['size'] * units.Gi,
|
volume.size * units.Gi,
|
||||||
is_file_max_size=False)
|
is_file_max_size=False)
|
||||||
|
|
||||||
def test_copy_volume_from_snapshot(self):
|
def test_copy_volume_from_snapshot(self):
|
||||||
drv = self._smbfs_driver
|
drv = self._smbfs_driver
|
||||||
|
snapshot = self._simple_snapshot()
|
||||||
fake_volume_info = {
|
fake_volume_info = {
|
||||||
self._FAKE_SNAPSHOT['id']: 'fake_snapshot_file_name'}
|
snapshot.id: 'fake_snapshot_file_name'}
|
||||||
fake_img_info = mock.MagicMock()
|
fake_img_info = mock.MagicMock()
|
||||||
fake_img_info.backing_file = self._FAKE_VOLUME_NAME + '.vhdx'
|
fake_img_info.backing_file = self._FAKE_VOLUME_NAME + '.vhdx'
|
||||||
|
|
||||||
@ -242,9 +262,9 @@ class WindowsSmbFsTestCase(test.TestCase):
|
|||||||
drv.local_path = mock.Mock(
|
drv.local_path = mock.Mock(
|
||||||
return_value=mock.sentinel.new_volume_path)
|
return_value=mock.sentinel.new_volume_path)
|
||||||
|
|
||||||
drv._copy_volume_from_snapshot(
|
volume = self._simple_volume()
|
||||||
self._FAKE_SNAPSHOT, self._FAKE_VOLUME,
|
drv._copy_volume_from_snapshot(snapshot,
|
||||||
self._FAKE_VOLUME['size'])
|
volume, volume.size)
|
||||||
|
|
||||||
drv._delete.assert_called_once_with(mock.sentinel.new_volume_path)
|
drv._delete.assert_called_once_with(mock.sentinel.new_volume_path)
|
||||||
drv._vhdutils.convert_vhd.assert_called_once_with(
|
drv._vhdutils.convert_vhd.assert_called_once_with(
|
||||||
@ -252,7 +272,7 @@ class WindowsSmbFsTestCase(test.TestCase):
|
|||||||
mock.sentinel.new_volume_path)
|
mock.sentinel.new_volume_path)
|
||||||
drv._vhdutils.resize_vhd.assert_called_once_with(
|
drv._vhdutils.resize_vhd.assert_called_once_with(
|
||||||
mock.sentinel.new_volume_path,
|
mock.sentinel.new_volume_path,
|
||||||
self._FAKE_VOLUME['size'] * units.Gi,
|
volume.size * units.Gi,
|
||||||
is_file_max_size=False)
|
is_file_max_size=False)
|
||||||
|
|
||||||
def test_rebase_img(self):
|
def test_rebase_img(self):
|
||||||
|
@ -146,7 +146,7 @@ class GlusterfsDriver(remotefs_drv.RemoteFSSnapDriver,
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def _local_volume_dir(self, volume):
|
def _local_volume_dir(self, volume):
|
||||||
hashed = self._get_hash_str(volume['provider_location'])
|
hashed = self._get_hash_str(volume.provider_location)
|
||||||
path = '%s/%s' % (self.configuration.glusterfs_mount_point_base,
|
path = '%s/%s' % (self.configuration.glusterfs_mount_point_base,
|
||||||
hashed)
|
hashed)
|
||||||
return path
|
return path
|
||||||
@ -185,13 +185,13 @@ class GlusterfsDriver(remotefs_drv.RemoteFSSnapDriver,
|
|||||||
|
|
||||||
self._ensure_shares_mounted()
|
self._ensure_shares_mounted()
|
||||||
|
|
||||||
volume['provider_location'] = self._find_share(volume['size'])
|
volume.provider_location = self._find_share(volume.size)
|
||||||
|
|
||||||
LOG.info(_LI('casted to %s'), volume['provider_location'])
|
LOG.info(_LI('casted to %s'), volume.provider_location)
|
||||||
|
|
||||||
self._do_create_volume(volume)
|
self._do_create_volume(volume)
|
||||||
|
|
||||||
return {'provider_location': volume['provider_location']}
|
return {'provider_location': volume.provider_location}
|
||||||
|
|
||||||
def _copy_volume_from_snapshot(self, snapshot, volume, volume_size):
|
def _copy_volume_from_snapshot(self, snapshot, volume, volume_size):
|
||||||
"""Copy data from snapshot to destination volume.
|
"""Copy data from snapshot to destination volume.
|
||||||
@ -202,20 +202,20 @@ class GlusterfsDriver(remotefs_drv.RemoteFSSnapDriver,
|
|||||||
|
|
||||||
LOG.debug("snapshot: %(snap)s, volume: %(vol)s, "
|
LOG.debug("snapshot: %(snap)s, volume: %(vol)s, "
|
||||||
"volume_size: %(size)s",
|
"volume_size: %(size)s",
|
||||||
{'snap': snapshot['id'],
|
{'snap': snapshot.id,
|
||||||
'vol': volume['id'],
|
'vol': volume.id,
|
||||||
'size': volume_size})
|
'size': volume_size})
|
||||||
|
|
||||||
info_path = self._local_path_volume_info(snapshot['volume'])
|
info_path = self._local_path_volume_info(snapshot.volume)
|
||||||
snap_info = self._read_info_file(info_path)
|
snap_info = self._read_info_file(info_path)
|
||||||
vol_path = self._local_volume_dir(snapshot['volume'])
|
vol_path = self._local_volume_dir(snapshot.volume)
|
||||||
forward_file = snap_info[snapshot['id']]
|
forward_file = snap_info[snapshot.id]
|
||||||
forward_path = os.path.join(vol_path, forward_file)
|
forward_path = os.path.join(vol_path, forward_file)
|
||||||
|
|
||||||
# Find the file which backs this file, which represents the point
|
# Find the file which backs this file, which represents the point
|
||||||
# when this snapshot was created.
|
# when this snapshot was created.
|
||||||
img_info = self._qemu_img_info(forward_path,
|
img_info = self._qemu_img_info(forward_path,
|
||||||
snapshot['volume']['name'])
|
snapshot.volume.name)
|
||||||
path_to_snap_img = os.path.join(vol_path, img_info.backing_file)
|
path_to_snap_img = os.path.join(vol_path, img_info.backing_file)
|
||||||
|
|
||||||
path_to_new_vol = self._local_path_volume(volume)
|
path_to_new_vol = self._local_path_volume(volume)
|
||||||
@ -237,13 +237,13 @@ class GlusterfsDriver(remotefs_drv.RemoteFSSnapDriver,
|
|||||||
def delete_volume(self, volume):
|
def delete_volume(self, volume):
|
||||||
"""Deletes a logical volume."""
|
"""Deletes a logical volume."""
|
||||||
|
|
||||||
if not volume['provider_location']:
|
if not volume.provider_location:
|
||||||
LOG.warning(_LW('Volume %s does not have '
|
LOG.warning(_LW('Volume %s does not have '
|
||||||
'provider_location specified, '
|
'provider_location specified, '
|
||||||
'skipping'), volume['name'])
|
'skipping'), volume.name)
|
||||||
return
|
return
|
||||||
|
|
||||||
self._ensure_share_mounted(volume['provider_location'])
|
self._ensure_share_mounted(volume.provider_location)
|
||||||
|
|
||||||
mounted_path = self._active_volume_path(volume)
|
mounted_path = self._active_volume_path(volume)
|
||||||
|
|
||||||
@ -264,7 +264,7 @@ class GlusterfsDriver(remotefs_drv.RemoteFSSnapDriver,
|
|||||||
def ensure_export(self, ctx, volume):
|
def ensure_export(self, ctx, volume):
|
||||||
"""Synchronously recreates an export for a logical volume."""
|
"""Synchronously recreates an export for a logical volume."""
|
||||||
|
|
||||||
self._ensure_share_mounted(volume['provider_location'])
|
self._ensure_share_mounted(volume.provider_location)
|
||||||
|
|
||||||
def create_export(self, ctx, volume, connector):
|
def create_export(self, ctx, volume, connector):
|
||||||
"""Exports the volume."""
|
"""Exports the volume."""
|
||||||
@ -285,16 +285,16 @@ class GlusterfsDriver(remotefs_drv.RemoteFSSnapDriver,
|
|||||||
# Find active qcow2 file
|
# Find active qcow2 file
|
||||||
active_file = self.get_active_image_from_info(volume)
|
active_file = self.get_active_image_from_info(volume)
|
||||||
path = '%s/%s/%s' % (self.configuration.glusterfs_mount_point_base,
|
path = '%s/%s/%s' % (self.configuration.glusterfs_mount_point_base,
|
||||||
self._get_hash_str(volume['provider_location']),
|
self._get_hash_str(volume.provider_location),
|
||||||
active_file)
|
active_file)
|
||||||
|
|
||||||
data = {'export': volume['provider_location'],
|
data = {'export': volume.provider_location,
|
||||||
'name': active_file}
|
'name': active_file}
|
||||||
if volume['provider_location'] in self.shares:
|
if volume.provider_location in self.shares:
|
||||||
data['options'] = self.shares[volume['provider_location']]
|
data['options'] = self.shares[volume.provider_location]
|
||||||
|
|
||||||
# Test file for raw vs. qcow2 format
|
# Test file for raw vs. qcow2 format
|
||||||
info = self._qemu_img_info(path, volume['name'])
|
info = self._qemu_img_info(path, volume.name)
|
||||||
data['format'] = info.file_format
|
data['format'] = info.file_format
|
||||||
if data['format'] not in ['raw', 'qcow2']:
|
if data['format'] not in ['raw', 'qcow2']:
|
||||||
msg = _('%s must be a valid raw or qcow2 image.') % path
|
msg = _('%s must be a valid raw or qcow2 image.') % path
|
||||||
@ -314,7 +314,7 @@ class GlusterfsDriver(remotefs_drv.RemoteFSSnapDriver,
|
|||||||
def extend_volume(self, volume, size_gb):
|
def extend_volume(self, volume, size_gb):
|
||||||
volume_path = self._active_volume_path(volume)
|
volume_path = self._active_volume_path(volume)
|
||||||
|
|
||||||
info = self._qemu_img_info(volume_path, volume['name'])
|
info = self._qemu_img_info(volume_path, volume.name)
|
||||||
backing_fmt = info.file_format
|
backing_fmt = info.file_format
|
||||||
|
|
||||||
if backing_fmt not in ['raw', 'qcow2']:
|
if backing_fmt not in ['raw', 'qcow2']:
|
||||||
@ -331,7 +331,7 @@ class GlusterfsDriver(remotefs_drv.RemoteFSSnapDriver,
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
volume_path = self.local_path(volume)
|
volume_path = self.local_path(volume)
|
||||||
volume_size = volume['size']
|
volume_size = volume.size
|
||||||
|
|
||||||
LOG.debug("creating new volume at %s", volume_path)
|
LOG.debug("creating new volume at %s", volume_path)
|
||||||
|
|
||||||
@ -452,7 +452,7 @@ class GlusterfsDriver(remotefs_drv.RemoteFSSnapDriver,
|
|||||||
|
|
||||||
active_file_path = self._active_volume_path(volume)
|
active_file_path = self._active_volume_path(volume)
|
||||||
|
|
||||||
info = self._qemu_img_info(active_file_path, volume['name'])
|
info = self._qemu_img_info(active_file_path, volume.name)
|
||||||
|
|
||||||
if info.backing_file is not None:
|
if info.backing_file is not None:
|
||||||
LOG.error(_LE('No snapshots found in database, but %(path)s has '
|
LOG.error(_LE('No snapshots found in database, but %(path)s has '
|
||||||
|
@ -300,13 +300,13 @@ class NfsDriver(driver.ExtendVD, remotefs.RemoteFSDriver):
|
|||||||
|
|
||||||
def extend_volume(self, volume, new_size):
|
def extend_volume(self, volume, new_size):
|
||||||
"""Extend an existing volume to the new size."""
|
"""Extend an existing volume to the new size."""
|
||||||
LOG.info(_LI('Extending volume %s.'), volume['id'])
|
LOG.info(_LI('Extending volume %s.'), volume.id)
|
||||||
extend_by = int(new_size) - volume['size']
|
extend_by = int(new_size) - volume.size
|
||||||
if not self._is_share_eligible(volume['provider_location'],
|
if not self._is_share_eligible(volume.provider_location,
|
||||||
extend_by):
|
extend_by):
|
||||||
raise exception.ExtendVolumeError(reason='Insufficient space to'
|
raise exception.ExtendVolumeError(reason='Insufficient space to'
|
||||||
' extend volume %s to %sG'
|
' extend volume %s to %sG'
|
||||||
% (volume['id'], new_size))
|
% (volume.id, new_size))
|
||||||
path = self.local_path(volume)
|
path = self.local_path(volume)
|
||||||
LOG.info(_LI('Resizing file to %sG...'), new_size)
|
LOG.info(_LI('Resizing file to %sG...'), new_size)
|
||||||
image_utils.resize_image(path, new_size,
|
image_utils.resize_image(path, new_size,
|
||||||
@ -396,8 +396,8 @@ class NfsDriver(driver.ExtendVD, remotefs.RemoteFSDriver):
|
|||||||
# NFS snapshots are introduced.
|
# NFS snapshots are introduced.
|
||||||
name_id = None
|
name_id = None
|
||||||
if original_volume_status == 'available':
|
if original_volume_status == 'available':
|
||||||
current_name = CONF.volume_name_template % new_volume['id']
|
current_name = CONF.volume_name_template % new_volume.id
|
||||||
original_volume_name = CONF.volume_name_template % volume['id']
|
original_volume_name = CONF.volume_name_template % volume.id
|
||||||
current_path = self.local_path(new_volume)
|
current_path = self.local_path(new_volume)
|
||||||
# Replace the volume name with the original volume name
|
# Replace the volume name with the original volume name
|
||||||
original_path = current_path.replace(current_name,
|
original_path = current_path.replace(current_name,
|
||||||
@ -406,16 +406,16 @@ class NfsDriver(driver.ExtendVD, remotefs.RemoteFSDriver):
|
|||||||
os.rename(current_path, original_path)
|
os.rename(current_path, original_path)
|
||||||
except OSError:
|
except OSError:
|
||||||
LOG.error(_LE('Unable to rename the logical volume '
|
LOG.error(_LE('Unable to rename the logical volume '
|
||||||
'for volume: %s'), volume['id'])
|
'for volume: %s'), volume.id)
|
||||||
# If the rename fails, _name_id should be set to the new
|
# If the rename fails, _name_id should be set to the new
|
||||||
# volume id and provider_location should be set to the
|
# volume id and provider_location should be set to the
|
||||||
# one from the new volume as well.
|
# one from the new volume as well.
|
||||||
name_id = new_volume['_name_id'] or new_volume['id']
|
name_id = new_volume._name_id or new_volume.id
|
||||||
else:
|
else:
|
||||||
# The back-end will not be renamed.
|
# The back-end will not be renamed.
|
||||||
name_id = new_volume['_name_id'] or new_volume['id']
|
name_id = new_volume._name_id or new_volume.id
|
||||||
return {'_name_id': name_id,
|
return {'_name_id': name_id,
|
||||||
'provider_location': new_volume['provider_location']}
|
'provider_location': new_volume.provider_location}
|
||||||
|
|
||||||
def _update_volume_stats(self):
|
def _update_volume_stats(self):
|
||||||
"""Retrieve stats info from volume group."""
|
"""Retrieve stats info from volume group."""
|
||||||
|
@ -185,20 +185,20 @@ class QuobyteDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
LOG.debug("snapshot: %(snap)s, volume: %(vol)s, ",
|
LOG.debug("snapshot: %(snap)s, volume: %(vol)s, ",
|
||||||
{'snap': snapshot['id'],
|
{'snap': snapshot.id,
|
||||||
'vol': volume['id'],
|
'vol': volume.id,
|
||||||
'size': volume_size})
|
'size': volume_size})
|
||||||
|
|
||||||
info_path = self._local_path_volume_info(snapshot['volume'])
|
info_path = self._local_path_volume_info(snapshot.volume)
|
||||||
snap_info = self._read_info_file(info_path)
|
snap_info = self._read_info_file(info_path)
|
||||||
vol_path = self._local_volume_dir(snapshot['volume'])
|
vol_path = self._local_volume_dir(snapshot.volume)
|
||||||
forward_file = snap_info[snapshot['id']]
|
forward_file = snap_info[snapshot.id]
|
||||||
forward_path = os.path.join(vol_path, forward_file)
|
forward_path = os.path.join(vol_path, forward_file)
|
||||||
|
|
||||||
# Find the file which backs this file, which represents the point
|
# Find the file which backs this file, which represents the point
|
||||||
# when this snapshot was created.
|
# when this snapshot was created.
|
||||||
img_info = self._qemu_img_info(forward_path,
|
img_info = self._qemu_img_info(forward_path,
|
||||||
snapshot['volume']['name'])
|
snapshot.volume.name)
|
||||||
path_to_snap_img = os.path.join(vol_path, img_info.backing_file)
|
path_to_snap_img = os.path.join(vol_path, img_info.backing_file)
|
||||||
|
|
||||||
path_to_new_vol = self._local_path_volume(volume)
|
path_to_new_vol = self._local_path_volume(volume)
|
||||||
@ -221,12 +221,12 @@ class QuobyteDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
def delete_volume(self, volume):
|
def delete_volume(self, volume):
|
||||||
"""Deletes a logical volume."""
|
"""Deletes a logical volume."""
|
||||||
|
|
||||||
if not volume['provider_location']:
|
if not volume.provider_location:
|
||||||
LOG.warning(_LW('Volume %s does not have provider_location '
|
LOG.warning(_LW('Volume %s does not have provider_location '
|
||||||
'specified, skipping'), volume['name'])
|
'specified, skipping'), volume.name)
|
||||||
return
|
return
|
||||||
|
|
||||||
self._ensure_share_mounted(volume['provider_location'])
|
self._ensure_share_mounted(volume.provider_location)
|
||||||
|
|
||||||
volume_dir = self._local_volume_dir(volume)
|
volume_dir = self._local_volume_dir(volume)
|
||||||
mounted_path = os.path.join(volume_dir,
|
mounted_path = os.path.join(volume_dir,
|
||||||
@ -261,16 +261,16 @@ class QuobyteDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
# Find active qcow2 file
|
# Find active qcow2 file
|
||||||
active_file = self.get_active_image_from_info(volume)
|
active_file = self.get_active_image_from_info(volume)
|
||||||
path = '%s/%s/%s' % (self.configuration.quobyte_mount_point_base,
|
path = '%s/%s/%s' % (self.configuration.quobyte_mount_point_base,
|
||||||
self._get_hash_str(volume['provider_location']),
|
self._get_hash_str(volume.provider_location),
|
||||||
active_file)
|
active_file)
|
||||||
|
|
||||||
data = {'export': volume['provider_location'],
|
data = {'export': volume.provider_location,
|
||||||
'name': active_file}
|
'name': active_file}
|
||||||
if volume['provider_location'] in self.shares:
|
if volume.provider_location in self.shares:
|
||||||
data['options'] = self.shares[volume['provider_location']]
|
data['options'] = self.shares[volume.provider_location]
|
||||||
|
|
||||||
# Test file for raw vs. qcow2 format
|
# Test file for raw vs. qcow2 format
|
||||||
info = self._qemu_img_info(path, volume['name'])
|
info = self._qemu_img_info(path, volume.name)
|
||||||
data['format'] = info.file_format
|
data['format'] = info.file_format
|
||||||
if data['format'] not in ['raw', 'qcow2']:
|
if data['format'] not in ['raw', 'qcow2']:
|
||||||
msg = _('%s must be a valid raw or qcow2 image.') % path
|
msg = _('%s must be a valid raw or qcow2 image.') % path
|
||||||
@ -299,7 +299,7 @@ class QuobyteDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
' driver when no snapshots exist.')
|
' driver when no snapshots exist.')
|
||||||
raise exception.InvalidVolume(msg)
|
raise exception.InvalidVolume(msg)
|
||||||
|
|
||||||
info = self._qemu_img_info(volume_path, volume['name'])
|
info = self._qemu_img_info(volume_path, volume.name)
|
||||||
backing_fmt = info.file_format
|
backing_fmt = info.file_format
|
||||||
|
|
||||||
if backing_fmt not in ['raw', 'qcow2']:
|
if backing_fmt not in ['raw', 'qcow2']:
|
||||||
@ -315,7 +315,7 @@ class QuobyteDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
:param volume: volume reference
|
:param volume: volume reference
|
||||||
"""
|
"""
|
||||||
volume_path = self.local_path(volume)
|
volume_path = self.local_path(volume)
|
||||||
volume_size = volume['size']
|
volume_size = volume.size
|
||||||
|
|
||||||
if self.configuration.quobyte_qcow2_volumes:
|
if self.configuration.quobyte_qcow2_volumes:
|
||||||
self._create_qcow2_file(volume_path, volume_size)
|
self._create_qcow2_file(volume_path, volume_size)
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import collections
|
||||||
import hashlib
|
import hashlib
|
||||||
import inspect
|
import inspect
|
||||||
import json
|
import json
|
||||||
@ -118,9 +119,9 @@ def locked_volume_id_operation(f, external=False):
|
|||||||
call_args = inspect.getcallargs(f, inst, *args, **kwargs)
|
call_args = inspect.getcallargs(f, inst, *args, **kwargs)
|
||||||
|
|
||||||
if call_args.get('volume'):
|
if call_args.get('volume'):
|
||||||
volume_id = call_args['volume']['id']
|
volume_id = call_args['volume'].id
|
||||||
elif call_args.get('snapshot'):
|
elif call_args.get('snapshot'):
|
||||||
volume_id = call_args['snapshot']['volume']['id']
|
volume_id = call_args['snapshot'].volume.id
|
||||||
else:
|
else:
|
||||||
err_msg = _('The decorated method must accept either a volume or '
|
err_msg = _('The decorated method must accept either a volume or '
|
||||||
'a snapshot object')
|
'a snapshot object')
|
||||||
@ -163,10 +164,10 @@ class RemoteFSDriver(driver.LocalVD, driver.TransferVD, driver.BaseVD):
|
|||||||
:param volume: volume reference
|
:param volume: volume reference
|
||||||
:param connector: connector reference
|
:param connector: connector reference
|
||||||
"""
|
"""
|
||||||
data = {'export': volume['provider_location'],
|
data = {'export': volume.provider_location,
|
||||||
'name': volume['name']}
|
'name': volume.name}
|
||||||
if volume['provider_location'] in self.shares:
|
if volume.provider_location in self.shares:
|
||||||
data['options'] = self.shares[volume['provider_location']]
|
data['options'] = self.shares[volume.provider_location]
|
||||||
return {
|
return {
|
||||||
'driver_volume_type': self.driver_volume_type,
|
'driver_volume_type': self.driver_volume_type,
|
||||||
'data': data,
|
'data': data,
|
||||||
@ -232,13 +233,13 @@ class RemoteFSDriver(driver.LocalVD, driver.TransferVD, driver.BaseVD):
|
|||||||
"""
|
"""
|
||||||
self._ensure_shares_mounted()
|
self._ensure_shares_mounted()
|
||||||
|
|
||||||
volume['provider_location'] = self._find_share(volume['size'])
|
volume.provider_location = self._find_share(volume.size)
|
||||||
|
|
||||||
LOG.info(_LI('casted to %s'), volume['provider_location'])
|
LOG.info(_LI('casted to %s'), volume.provider_location)
|
||||||
|
|
||||||
self._do_create_volume(volume)
|
self._do_create_volume(volume)
|
||||||
|
|
||||||
return {'provider_location': volume['provider_location']}
|
return {'provider_location': volume.provider_location}
|
||||||
|
|
||||||
def _do_create_volume(self, volume):
|
def _do_create_volume(self, volume):
|
||||||
"""Create a volume on given remote share.
|
"""Create a volume on given remote share.
|
||||||
@ -246,7 +247,7 @@ class RemoteFSDriver(driver.LocalVD, driver.TransferVD, driver.BaseVD):
|
|||||||
:param volume: volume reference
|
:param volume: volume reference
|
||||||
"""
|
"""
|
||||||
volume_path = self.local_path(volume)
|
volume_path = self.local_path(volume)
|
||||||
volume_size = volume['size']
|
volume_size = volume.size
|
||||||
|
|
||||||
if getattr(self.configuration,
|
if getattr(self.configuration,
|
||||||
self.driver_prefix + '_sparsed_volumes'):
|
self.driver_prefix + '_sparsed_volumes'):
|
||||||
@ -280,13 +281,13 @@ class RemoteFSDriver(driver.LocalVD, driver.TransferVD, driver.BaseVD):
|
|||||||
|
|
||||||
:param volume: volume reference
|
:param volume: volume reference
|
||||||
"""
|
"""
|
||||||
if not volume['provider_location']:
|
if not volume.provider_location:
|
||||||
LOG.warning(_LW('Volume %s does not have '
|
LOG.warning(_LW('Volume %s does not have '
|
||||||
'provider_location specified, '
|
'provider_location specified, '
|
||||||
'skipping'), volume['name'])
|
'skipping'), volume.name)
|
||||||
return
|
return
|
||||||
|
|
||||||
self._ensure_share_mounted(volume['provider_location'])
|
self._ensure_share_mounted(volume.provider_location)
|
||||||
|
|
||||||
mounted_path = self.local_path(volume)
|
mounted_path = self.local_path(volume)
|
||||||
|
|
||||||
@ -294,7 +295,7 @@ class RemoteFSDriver(driver.LocalVD, driver.TransferVD, driver.BaseVD):
|
|||||||
|
|
||||||
def ensure_export(self, ctx, volume):
|
def ensure_export(self, ctx, volume):
|
||||||
"""Synchronously recreates an export for a logical volume."""
|
"""Synchronously recreates an export for a logical volume."""
|
||||||
self._ensure_share_mounted(volume['provider_location'])
|
self._ensure_share_mounted(volume.provider_location)
|
||||||
|
|
||||||
def create_export(self, ctx, volume, connector):
|
def create_export(self, ctx, volume, connector):
|
||||||
"""Exports the volume.
|
"""Exports the volume.
|
||||||
@ -387,9 +388,9 @@ class RemoteFSDriver(driver.LocalVD, driver.TransferVD, driver.BaseVD):
|
|||||||
|
|
||||||
:param volume: volume reference
|
:param volume: volume reference
|
||||||
"""
|
"""
|
||||||
remotefs_share = volume['provider_location']
|
remotefs_share = volume.provider_location
|
||||||
return os.path.join(self._get_mount_point_for_share(remotefs_share),
|
return os.path.join(self._get_mount_point_for_share(remotefs_share),
|
||||||
volume['name'])
|
volume.name)
|
||||||
|
|
||||||
def copy_image_to_volume(self, context, volume, image_service, image_id):
|
def copy_image_to_volume(self, context, volume, image_service, image_id):
|
||||||
"""Fetch the image from image_service and write it to the volume."""
|
"""Fetch the image from image_service and write it to the volume."""
|
||||||
@ -400,7 +401,7 @@ class RemoteFSDriver(driver.LocalVD, driver.TransferVD, driver.BaseVD):
|
|||||||
image_id,
|
image_id,
|
||||||
self.local_path(volume),
|
self.local_path(volume),
|
||||||
self.configuration.volume_dd_blocksize,
|
self.configuration.volume_dd_blocksize,
|
||||||
size=volume['size'],
|
size=volume.size,
|
||||||
run_as_root=run_as_root)
|
run_as_root=run_as_root)
|
||||||
|
|
||||||
# NOTE (leseb): Set the virtual size of the image
|
# NOTE (leseb): Set the virtual size of the image
|
||||||
@ -410,16 +411,16 @@ class RemoteFSDriver(driver.LocalVD, driver.TransferVD, driver.BaseVD):
|
|||||||
# thus the initial 'size' parameter is not honored
|
# thus the initial 'size' parameter is not honored
|
||||||
# this sets the size to the one asked in the first place by the user
|
# this sets the size to the one asked in the first place by the user
|
||||||
# and then verify the final virtual size
|
# and then verify the final virtual size
|
||||||
image_utils.resize_image(self.local_path(volume), volume['size'],
|
image_utils.resize_image(self.local_path(volume), volume.size,
|
||||||
run_as_root=run_as_root)
|
run_as_root=run_as_root)
|
||||||
|
|
||||||
data = image_utils.qemu_img_info(self.local_path(volume),
|
data = image_utils.qemu_img_info(self.local_path(volume),
|
||||||
run_as_root=run_as_root)
|
run_as_root=run_as_root)
|
||||||
virt_size = data.virtual_size / units.Gi
|
virt_size = data.virtual_size / units.Gi
|
||||||
if virt_size != volume['size']:
|
if virt_size != volume.size:
|
||||||
raise exception.ImageUnacceptable(
|
raise exception.ImageUnacceptable(
|
||||||
image_id=image_id,
|
image_id=image_id,
|
||||||
reason=(_("Expected volume size was %d") % volume['size'])
|
reason=(_("Expected volume size was %d") % volume.size)
|
||||||
+ (_(" but size is now %d") % virt_size))
|
+ (_(" but size is now %d") % virt_size))
|
||||||
|
|
||||||
def copy_volume_to_image(self, context, volume, image_service, image_meta):
|
def copy_volume_to_image(self, context, volume, image_service, image_meta):
|
||||||
@ -647,20 +648,20 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
self._nova = compute.API()
|
self._nova = compute.API()
|
||||||
|
|
||||||
def _local_volume_dir(self, volume):
|
def _local_volume_dir(self, volume):
|
||||||
share = volume['provider_location']
|
share = volume.provider_location
|
||||||
local_dir = self._get_mount_point_for_share(share)
|
local_dir = self._get_mount_point_for_share(share)
|
||||||
return local_dir
|
return local_dir
|
||||||
|
|
||||||
def _local_path_volume(self, volume):
|
def _local_path_volume(self, volume):
|
||||||
path_to_disk = os.path.join(
|
path_to_disk = os.path.join(
|
||||||
self._local_volume_dir(volume),
|
self._local_volume_dir(volume),
|
||||||
volume['name'])
|
volume.name)
|
||||||
|
|
||||||
return path_to_disk
|
return path_to_disk
|
||||||
|
|
||||||
def _get_new_snap_path(self, snapshot):
|
def _get_new_snap_path(self, snapshot):
|
||||||
vol_path = self.local_path(snapshot['volume'])
|
vol_path = self.local_path(snapshot.volume)
|
||||||
snap_path = '%s.%s' % (vol_path, snapshot['id'])
|
snap_path = '%s.%s' % (vol_path, snapshot.id)
|
||||||
return snap_path
|
return snap_path
|
||||||
|
|
||||||
def _local_path_volume_info(self, volume):
|
def _local_path_volume_info(self, volume):
|
||||||
@ -757,7 +758,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
|
|
||||||
output = []
|
output = []
|
||||||
|
|
||||||
info = self._qemu_img_info(path, volume['name'])
|
info = self._qemu_img_info(path, volume.name)
|
||||||
new_info = {}
|
new_info = {}
|
||||||
new_info['filename'] = os.path.basename(path)
|
new_info['filename'] = os.path.basename(path)
|
||||||
new_info['backing-filename'] = info.backing_file
|
new_info['backing-filename'] = info.backing_file
|
||||||
@ -767,7 +768,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
while new_info['backing-filename']:
|
while new_info['backing-filename']:
|
||||||
filename = new_info['backing-filename']
|
filename = new_info['backing-filename']
|
||||||
path = os.path.join(self._local_volume_dir(volume), filename)
|
path = os.path.join(self._local_volume_dir(volume), filename)
|
||||||
info = self._qemu_img_info(path, volume['name'])
|
info = self._qemu_img_info(path, volume.name)
|
||||||
backing_filename = info.backing_file
|
backing_filename = info.backing_file
|
||||||
new_info = {}
|
new_info = {}
|
||||||
new_info['filename'] = filename
|
new_info['filename'] = filename
|
||||||
@ -846,13 +847,13 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
active_file = self.get_active_image_from_info(volume)
|
active_file = self.get_active_image_from_info(volume)
|
||||||
active_file_path = os.path.join(self._local_volume_dir(volume),
|
active_file_path = os.path.join(self._local_volume_dir(volume),
|
||||||
active_file)
|
active_file)
|
||||||
info = self._qemu_img_info(active_file_path, volume['name'])
|
info = self._qemu_img_info(active_file_path, volume.name)
|
||||||
backing_file = info.backing_file
|
backing_file = info.backing_file
|
||||||
|
|
||||||
root_file_fmt = info.file_format
|
root_file_fmt = info.file_format
|
||||||
|
|
||||||
tmp_params = {
|
tmp_params = {
|
||||||
'prefix': '%s.temp_image.%s' % (volume['id'], image_meta['id']),
|
'prefix': '%s.temp_image.%s' % (volume.id, image_meta['id']),
|
||||||
'suffix': '.img'
|
'suffix': '.img'
|
||||||
}
|
}
|
||||||
with image_utils.temporary_file(**tmp_params) as temp_path:
|
with image_utils.temporary_file(**tmp_params) as temp_path:
|
||||||
@ -886,52 +887,64 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
|
|
||||||
def _create_cloned_volume(self, volume, src_vref):
|
def _create_cloned_volume(self, volume, src_vref):
|
||||||
LOG.info(_LI('Cloning volume %(src)s to volume %(dst)s'),
|
LOG.info(_LI('Cloning volume %(src)s to volume %(dst)s'),
|
||||||
{'src': src_vref['id'],
|
{'src': src_vref.id,
|
||||||
'dst': volume['id']})
|
'dst': volume.id})
|
||||||
|
|
||||||
if src_vref['status'] != 'available':
|
if src_vref.status != 'available':
|
||||||
msg = _("Volume status must be 'available'.")
|
msg = _("Volume status must be 'available'.")
|
||||||
raise exception.InvalidVolume(msg)
|
raise exception.InvalidVolume(msg)
|
||||||
|
|
||||||
volume_name = CONF.volume_name_template % volume['id']
|
volume_name = CONF.volume_name_template % volume.id
|
||||||
|
|
||||||
|
# Create fake volume and snapshot objects
|
||||||
|
vol_attrs = ['provider_location', 'size', 'id', 'name', 'status',
|
||||||
|
'volume_type', 'metadata']
|
||||||
|
Volume = collections.namedtuple('Volume', vol_attrs)
|
||||||
|
|
||||||
|
snap_attrs = ['volume_name', 'volume_size', 'name',
|
||||||
|
'volume_id', 'id', 'volume']
|
||||||
|
Snapshot = collections.namedtuple('Snapshot', snap_attrs)
|
||||||
|
|
||||||
|
volume_info = Volume(provider_location=src_vref.provider_location,
|
||||||
|
size=src_vref.size,
|
||||||
|
id=volume.id,
|
||||||
|
name=volume_name,
|
||||||
|
status=src_vref.status,
|
||||||
|
volume_type=src_vref.volume_type,
|
||||||
|
metadata=src_vref.metadata)
|
||||||
|
|
||||||
|
temp_snapshot = Snapshot(volume_name=volume_name,
|
||||||
|
volume_size=src_vref.size,
|
||||||
|
name='clone-snap-%s' % src_vref.id,
|
||||||
|
volume_id=src_vref.id,
|
||||||
|
id='tmp-snap-%s' % src_vref.id,
|
||||||
|
volume=src_vref)
|
||||||
|
|
||||||
volume_info = {'provider_location': src_vref['provider_location'],
|
|
||||||
'size': src_vref['size'],
|
|
||||||
'id': volume['id'],
|
|
||||||
'name': volume_name,
|
|
||||||
'status': src_vref['status']}
|
|
||||||
temp_snapshot = {'volume_name': volume_name,
|
|
||||||
'size': src_vref['size'],
|
|
||||||
'volume_size': src_vref['size'],
|
|
||||||
'name': 'clone-snap-%s' % src_vref['id'],
|
|
||||||
'volume_id': src_vref['id'],
|
|
||||||
'id': 'tmp-snap-%s' % src_vref['id'],
|
|
||||||
'volume': src_vref}
|
|
||||||
self._create_snapshot(temp_snapshot)
|
self._create_snapshot(temp_snapshot)
|
||||||
try:
|
try:
|
||||||
self._copy_volume_from_snapshot(temp_snapshot,
|
self._copy_volume_from_snapshot(temp_snapshot,
|
||||||
volume_info,
|
volume_info,
|
||||||
volume['size'])
|
volume.size)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
self._delete_snapshot(temp_snapshot)
|
self._delete_snapshot(temp_snapshot)
|
||||||
|
|
||||||
return {'provider_location': src_vref['provider_location']}
|
return {'provider_location': src_vref.provider_location}
|
||||||
|
|
||||||
def _delete_stale_snapshot(self, snapshot):
|
def _delete_stale_snapshot(self, snapshot):
|
||||||
info_path = self._local_path_volume_info(snapshot['volume'])
|
info_path = self._local_path_volume_info(snapshot.volume)
|
||||||
snap_info = self._read_info_file(info_path)
|
snap_info = self._read_info_file(info_path)
|
||||||
|
|
||||||
snapshot_file = snap_info[snapshot['id']]
|
snapshot_file = snap_info[snapshot.id]
|
||||||
active_file = self.get_active_image_from_info(snapshot['volume'])
|
active_file = self.get_active_image_from_info(snapshot.volume)
|
||||||
snapshot_path = os.path.join(
|
snapshot_path = os.path.join(
|
||||||
self._local_volume_dir(snapshot['volume']), snapshot_file)
|
self._local_volume_dir(snapshot.volume), snapshot_file)
|
||||||
if (snapshot_file == active_file):
|
if (snapshot_file == active_file):
|
||||||
return
|
return
|
||||||
|
|
||||||
LOG.info(_LI('Deleting stale snapshot: %s'), snapshot['id'])
|
LOG.info(_LI('Deleting stale snapshot: %s'), snapshot.id)
|
||||||
self._delete(snapshot_path)
|
self._delete(snapshot_path)
|
||||||
del(snap_info[snapshot['id']])
|
del(snap_info[snapshot.id])
|
||||||
self._write_info_file(info_path, snap_info)
|
self._write_info_file(info_path, snap_info)
|
||||||
|
|
||||||
def _delete_snapshot(self, snapshot):
|
def _delete_snapshot(self, snapshot):
|
||||||
@ -949,39 +962,39 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
LOG.debug('Deleting snapshot %s:', snapshot['id'])
|
LOG.debug('Deleting snapshot %s:', snapshot.id)
|
||||||
|
|
||||||
volume_status = snapshot['volume']['status']
|
volume_status = snapshot.volume.status
|
||||||
if volume_status not in ['available', 'in-use']:
|
if volume_status not in ['available', 'in-use']:
|
||||||
msg = _('Volume status must be "available" or "in-use".')
|
msg = _('Volume status must be "available" or "in-use".')
|
||||||
raise exception.InvalidVolume(msg)
|
raise exception.InvalidVolume(msg)
|
||||||
|
|
||||||
vol_path = self._local_volume_dir(snapshot['volume'])
|
vol_path = self._local_volume_dir(snapshot.volume)
|
||||||
self._ensure_share_writable(vol_path)
|
self._ensure_share_writable(vol_path)
|
||||||
|
|
||||||
# Determine the true snapshot file for this snapshot
|
# Determine the true snapshot file for this snapshot
|
||||||
# based on the .info file
|
# based on the .info file
|
||||||
info_path = self._local_path_volume_info(snapshot['volume'])
|
info_path = self._local_path_volume_info(snapshot.volume)
|
||||||
snap_info = self._read_info_file(info_path, empty_if_missing=True)
|
snap_info = self._read_info_file(info_path, empty_if_missing=True)
|
||||||
|
|
||||||
if snapshot['id'] not in snap_info:
|
if snapshot.id not in snap_info:
|
||||||
# If snapshot info file is present, but snapshot record does not
|
# If snapshot info file is present, but snapshot record does not
|
||||||
# exist, do not attempt to delete.
|
# exist, do not attempt to delete.
|
||||||
# (This happens, for example, if snapshot_create failed due to lack
|
# (This happens, for example, if snapshot_create failed due to lack
|
||||||
# of permission to write to the share.)
|
# of permission to write to the share.)
|
||||||
LOG.info(_LI('Snapshot record for %s is not present, allowing '
|
LOG.info(_LI('Snapshot record for %s is not present, allowing '
|
||||||
'snapshot_delete to proceed.'), snapshot['id'])
|
'snapshot_delete to proceed.'), snapshot.id)
|
||||||
return
|
return
|
||||||
|
|
||||||
snapshot_file = snap_info[snapshot['id']]
|
snapshot_file = snap_info[snapshot.id]
|
||||||
LOG.debug('snapshot_file for this snap is: %s', snapshot_file)
|
LOG.debug('snapshot_file for this snap is: %s', snapshot_file)
|
||||||
snapshot_path = os.path.join(
|
snapshot_path = os.path.join(
|
||||||
self._local_volume_dir(snapshot['volume']),
|
self._local_volume_dir(snapshot.volume),
|
||||||
snapshot_file)
|
snapshot_file)
|
||||||
|
|
||||||
snapshot_path_img_info = self._qemu_img_info(
|
snapshot_path_img_info = self._qemu_img_info(
|
||||||
snapshot_path,
|
snapshot_path,
|
||||||
snapshot['volume']['name'])
|
snapshot.volume.name)
|
||||||
|
|
||||||
base_file = snapshot_path_img_info.backing_file
|
base_file = snapshot_path_img_info.backing_file
|
||||||
if base_file is None:
|
if base_file is None:
|
||||||
@ -996,15 +1009,15 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
|
|
||||||
base_path = os.path.join(vol_path, base_file)
|
base_path = os.path.join(vol_path, base_file)
|
||||||
base_file_img_info = self._qemu_img_info(base_path,
|
base_file_img_info = self._qemu_img_info(base_path,
|
||||||
snapshot['volume']['name'])
|
snapshot.volume.name)
|
||||||
|
|
||||||
# Find what file has this as its backing file
|
# Find what file has this as its backing file
|
||||||
active_file = self.get_active_image_from_info(snapshot['volume'])
|
active_file = self.get_active_image_from_info(snapshot.volume)
|
||||||
active_file_path = os.path.join(vol_path, active_file)
|
active_file_path = os.path.join(vol_path, active_file)
|
||||||
|
|
||||||
if volume_status == 'in-use':
|
if volume_status == 'in-use':
|
||||||
# Online delete
|
# Online delete
|
||||||
context = snapshot['context']
|
context = snapshot._context
|
||||||
|
|
||||||
new_base_file = base_file_img_info.backing_file
|
new_base_file = base_file_img_info.backing_file
|
||||||
|
|
||||||
@ -1048,7 +1061,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
# used here) | | ptr update) |
|
# used here) | | ptr update) |
|
||||||
|
|
||||||
backing_chain = self._get_backing_chain_for_path(
|
backing_chain = self._get_backing_chain_for_path(
|
||||||
snapshot['volume'], active_file_path)
|
snapshot.volume, active_file_path)
|
||||||
# This file is guaranteed to exist since we aren't operating on
|
# This file is guaranteed to exist since we aren't operating on
|
||||||
# the active file.
|
# the active file.
|
||||||
higher_file = next((os.path.basename(f['filename'])
|
higher_file = next((os.path.basename(f['filename'])
|
||||||
@ -1077,7 +1090,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
self._rebase_img(higher_file_path, base_file, base_file_fmt)
|
self._rebase_img(higher_file_path, base_file, base_file_fmt)
|
||||||
|
|
||||||
# Remove snapshot_file from info
|
# Remove snapshot_file from info
|
||||||
del(snap_info[snapshot['id']])
|
del(snap_info[snapshot.id])
|
||||||
self._write_info_file(info_path, snap_info)
|
self._write_info_file(info_path, snap_info)
|
||||||
|
|
||||||
def _create_volume_from_snapshot(self, volume, snapshot):
|
def _create_volume_from_snapshot(self, volume, snapshot):
|
||||||
@ -1086,21 +1099,21 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
Snapshot must not be the active snapshot. (offline)
|
Snapshot must not be the active snapshot. (offline)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if snapshot['status'] != 'available':
|
if snapshot.status != 'available':
|
||||||
msg = _('Snapshot status must be "available" to clone.')
|
msg = _('Snapshot status must be "available" to clone.')
|
||||||
raise exception.InvalidSnapshot(msg)
|
raise exception.InvalidSnapshot(msg)
|
||||||
|
|
||||||
self._ensure_shares_mounted()
|
self._ensure_shares_mounted()
|
||||||
|
|
||||||
volume['provider_location'] = self._find_share(volume['size'])
|
volume.provider_location = self._find_share(volume.size)
|
||||||
|
|
||||||
self._do_create_volume(volume)
|
self._do_create_volume(volume)
|
||||||
|
|
||||||
self._copy_volume_from_snapshot(snapshot,
|
self._copy_volume_from_snapshot(snapshot,
|
||||||
volume,
|
volume,
|
||||||
volume['size'])
|
volume.size)
|
||||||
|
|
||||||
return {'provider_location': volume['provider_location']}
|
return {'provider_location': volume.provider_location}
|
||||||
|
|
||||||
def _copy_volume_from_snapshot(self, snapshot, volume, volume_size):
|
def _copy_volume_from_snapshot(self, snapshot, volume, volume_size):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
@ -1116,7 +1129,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
backing_path_full_path = os.path.join(
|
backing_path_full_path = os.path.join(
|
||||||
self._local_volume_dir(snapshot['volume']),
|
self._local_volume_dir(snapshot.volume),
|
||||||
backing_filename)
|
backing_filename)
|
||||||
|
|
||||||
command = ['qemu-img', 'create', '-f', 'qcow2', '-o',
|
command = ['qemu-img', 'create', '-f', 'qcow2', '-o',
|
||||||
@ -1124,7 +1137,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
self._execute(*command, run_as_root=self._execute_as_root)
|
self._execute(*command, run_as_root=self._execute_as_root)
|
||||||
|
|
||||||
info = self._qemu_img_info(backing_path_full_path,
|
info = self._qemu_img_info(backing_path_full_path,
|
||||||
snapshot['volume']['name'])
|
snapshot.volume.name)
|
||||||
backing_fmt = info.file_format
|
backing_fmt = info.file_format
|
||||||
|
|
||||||
command = ['qemu-img', 'rebase', '-u',
|
command = ['qemu-img', 'rebase', '-u',
|
||||||
@ -1239,16 +1252,16 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
info file: { 'active': 'volume-1234' } (* changed!)
|
info file: { 'active': 'volume-1234' } (* changed!)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
status = snapshot['volume']['status']
|
status = snapshot.volume.status
|
||||||
if status not in ['available', 'in-use']:
|
if status not in ['available', 'in-use']:
|
||||||
msg = _('Volume status must be "available" or "in-use"'
|
msg = _('Volume status must be "available" or "in-use"'
|
||||||
' for snapshot. (is %s)') % status
|
' for snapshot. (is %s)') % status
|
||||||
raise exception.InvalidVolume(msg)
|
raise exception.InvalidVolume(msg)
|
||||||
|
|
||||||
info_path = self._local_path_volume_info(snapshot['volume'])
|
info_path = self._local_path_volume_info(snapshot.volume)
|
||||||
snap_info = self._read_info_file(info_path, empty_if_missing=True)
|
snap_info = self._read_info_file(info_path, empty_if_missing=True)
|
||||||
backing_filename = self.get_active_image_from_info(
|
backing_filename = self.get_active_image_from_info(
|
||||||
snapshot['volume'])
|
snapshot.volume)
|
||||||
new_snap_path = self._get_new_snap_path(snapshot)
|
new_snap_path = self._get_new_snap_path(snapshot)
|
||||||
|
|
||||||
if status == 'in-use':
|
if status == 'in-use':
|
||||||
@ -1261,13 +1274,13 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
new_snap_path)
|
new_snap_path)
|
||||||
|
|
||||||
snap_info['active'] = os.path.basename(new_snap_path)
|
snap_info['active'] = os.path.basename(new_snap_path)
|
||||||
snap_info[snapshot['id']] = os.path.basename(new_snap_path)
|
snap_info[snapshot.id] = os.path.basename(new_snap_path)
|
||||||
self._write_info_file(info_path, snap_info)
|
self._write_info_file(info_path, snap_info)
|
||||||
|
|
||||||
def _create_snapshot_online(self, snapshot, backing_filename,
|
def _create_snapshot_online(self, snapshot, backing_filename,
|
||||||
new_snap_path):
|
new_snap_path):
|
||||||
# Perform online snapshot via Nova
|
# Perform online snapshot via Nova
|
||||||
context = snapshot['context']
|
context = snapshot._context
|
||||||
|
|
||||||
self._do_create_snapshot(snapshot,
|
self._do_create_snapshot(snapshot,
|
||||||
backing_filename,
|
backing_filename,
|
||||||
@ -1276,13 +1289,13 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
connection_info = {
|
connection_info = {
|
||||||
'type': 'qcow2',
|
'type': 'qcow2',
|
||||||
'new_file': os.path.basename(new_snap_path),
|
'new_file': os.path.basename(new_snap_path),
|
||||||
'snapshot_id': snapshot['id']
|
'snapshot_id': snapshot.id
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = self._nova.create_volume_snapshot(
|
result = self._nova.create_volume_snapshot(
|
||||||
context,
|
context,
|
||||||
snapshot['volume_id'],
|
snapshot.volume_id,
|
||||||
connection_info)
|
connection_info)
|
||||||
LOG.debug('nova call result: %s', result)
|
LOG.debug('nova call result: %s', result)
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -1296,7 +1309,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
increment = 1
|
increment = 1
|
||||||
timeout = 600
|
timeout = 600
|
||||||
while True:
|
while True:
|
||||||
s = db.snapshot_get(context, snapshot['id'])
|
s = db.snapshot_get(context, snapshot.id)
|
||||||
|
|
||||||
LOG.debug('Status of snapshot %(id)s is now %(status)s',
|
LOG.debug('Status of snapshot %(id)s is now %(status)s',
|
||||||
{'id': snapshot['id'],
|
{'id': snapshot['id'],
|
||||||
@ -1320,7 +1333,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
msg = _('Snapshot %(id)s has been asked to be deleted while '
|
msg = _('Snapshot %(id)s has been asked to be deleted while '
|
||||||
'waiting for it to become available. Perhaps a '
|
'waiting for it to become available. Perhaps a '
|
||||||
'concurrent request was made.') % {'id':
|
'concurrent request was made.') % {'id':
|
||||||
snapshot['id']}
|
snapshot.id}
|
||||||
raise exception.RemoteFSConcurrentRequest(msg)
|
raise exception.RemoteFSConcurrentRequest(msg)
|
||||||
|
|
||||||
if 10 < seconds_elapsed <= 20:
|
if 10 < seconds_elapsed <= 20:
|
||||||
@ -1332,13 +1345,13 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
|
|
||||||
if seconds_elapsed > timeout:
|
if seconds_elapsed > timeout:
|
||||||
msg = _('Timed out while waiting for Nova update '
|
msg = _('Timed out while waiting for Nova update '
|
||||||
'for creation of snapshot %s.') % snapshot['id']
|
'for creation of snapshot %s.') % snapshot.id
|
||||||
raise exception.RemoteFSException(msg)
|
raise exception.RemoteFSException(msg)
|
||||||
|
|
||||||
def _delete_snapshot_online(self, context, snapshot, info):
|
def _delete_snapshot_online(self, context, snapshot, info):
|
||||||
# Update info over the course of this method
|
# Update info over the course of this method
|
||||||
# active file never changes
|
# active file never changes
|
||||||
info_path = self._local_path_volume_info(snapshot['volume'])
|
info_path = self._local_path_volume_info(snapshot.volume)
|
||||||
snap_info = self._read_info_file(info_path)
|
snap_info = self._read_info_file(info_path)
|
||||||
|
|
||||||
if info['active_file'] == info['snapshot_file']:
|
if info['active_file'] == info['snapshot_file']:
|
||||||
@ -1357,9 +1370,9 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
delete_info = {'file_to_merge': new_base,
|
delete_info = {'file_to_merge': new_base,
|
||||||
'merge_target_file': None, # current
|
'merge_target_file': None, # current
|
||||||
'type': 'qcow2',
|
'type': 'qcow2',
|
||||||
'volume_id': snapshot['volume']['id']}
|
'volume_id': snapshot.volume.id}
|
||||||
|
|
||||||
del(snap_info[snapshot['id']])
|
del(snap_info[snapshot.id])
|
||||||
else:
|
else:
|
||||||
# blockCommit snapshot into base
|
# blockCommit snapshot into base
|
||||||
# info['base'] <= snapshot_file
|
# info['base'] <= snapshot_file
|
||||||
@ -1369,14 +1382,14 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
delete_info = {'file_to_merge': info['snapshot_file'],
|
delete_info = {'file_to_merge': info['snapshot_file'],
|
||||||
'merge_target_file': info['base_file'],
|
'merge_target_file': info['base_file'],
|
||||||
'type': 'qcow2',
|
'type': 'qcow2',
|
||||||
'volume_id': snapshot['volume']['id']}
|
'volume_id': snapshot.volume.id}
|
||||||
|
|
||||||
del(snap_info[snapshot['id']])
|
del(snap_info[snapshot.id])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._nova.delete_volume_snapshot(
|
self._nova.delete_volume_snapshot(
|
||||||
context,
|
context,
|
||||||
snapshot['id'],
|
snapshot.id,
|
||||||
delete_info)
|
delete_info)
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.exception(_LE('Call to Nova delete snapshot failed'))
|
LOG.exception(_LE('Call to Nova delete snapshot failed'))
|
||||||
@ -1389,7 +1402,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
increment = 1
|
increment = 1
|
||||||
timeout = 7200
|
timeout = 7200
|
||||||
while True:
|
while True:
|
||||||
s = db.snapshot_get(context, snapshot['id'])
|
s = db.snapshot_get(context, snapshot.id)
|
||||||
|
|
||||||
if s['status'] == fields.SnapshotStatus.DELETING:
|
if s['status'] == fields.SnapshotStatus.DELETING:
|
||||||
if s['progress'] == '90%':
|
if s['progress'] == '90%':
|
||||||
@ -1397,12 +1410,12 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
LOG.debug('status of snapshot %s is still "deleting"... '
|
LOG.debug('status of snapshot %s is still "deleting"... '
|
||||||
'waiting', snapshot['id'])
|
'waiting', snapshot.id)
|
||||||
time.sleep(increment)
|
time.sleep(increment)
|
||||||
seconds_elapsed += increment
|
seconds_elapsed += increment
|
||||||
else:
|
else:
|
||||||
msg = _('Unable to delete snapshot %(id)s, '
|
msg = _('Unable to delete snapshot %(id)s, '
|
||||||
'status: %(status)s.') % {'id': snapshot['id'],
|
'status: %(status)s.') % {'id': snapshot.id,
|
||||||
'status': s['status']}
|
'status': s['status']}
|
||||||
raise exception.RemoteFSException(msg)
|
raise exception.RemoteFSException(msg)
|
||||||
|
|
||||||
@ -1416,7 +1429,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
if seconds_elapsed > timeout:
|
if seconds_elapsed > timeout:
|
||||||
msg = _('Timed out while waiting for Nova update '
|
msg = _('Timed out while waiting for Nova update '
|
||||||
'for deletion of snapshot %(id)s.') %\
|
'for deletion of snapshot %(id)s.') %\
|
||||||
{'id': snapshot['id']}
|
{'id': snapshot.id}
|
||||||
raise exception.RemoteFSException(msg)
|
raise exception.RemoteFSException(msg)
|
||||||
|
|
||||||
# Write info file updated above
|
# Write info file updated above
|
||||||
@ -1424,7 +1437,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
|
|||||||
|
|
||||||
# Delete stale file
|
# Delete stale file
|
||||||
path_to_delete = os.path.join(
|
path_to_delete = os.path.join(
|
||||||
self._local_volume_dir(snapshot['volume']), file_to_delete)
|
self._local_volume_dir(snapshot.volume), file_to_delete)
|
||||||
self._execute('rm', '-f', path_to_delete, run_as_root=True)
|
self._execute('rm', '-f', path_to_delete, run_as_root=True)
|
||||||
|
|
||||||
@locked_volume_id_operation
|
@locked_volume_id_operation
|
||||||
|
@ -186,14 +186,14 @@ class ScalityDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
active_file = self.get_active_image_from_info(volume)
|
active_file = self.get_active_image_from_info(volume)
|
||||||
path = '%s/%s' % (self._get_mount_point_for_share(), active_file)
|
path = '%s/%s' % (self._get_mount_point_for_share(), active_file)
|
||||||
sofs_rel_path = os.path.join(self.sofs_rel_volume_dir, "00",
|
sofs_rel_path = os.path.join(self.sofs_rel_volume_dir, "00",
|
||||||
volume['name'])
|
volume.name)
|
||||||
|
|
||||||
data = {'export': volume['provider_location'],
|
data = {'export': volume.provider_location,
|
||||||
'name': active_file,
|
'name': active_file,
|
||||||
'sofs_path': sofs_rel_path}
|
'sofs_path': sofs_rel_path}
|
||||||
|
|
||||||
# Test file for raw vs. qcow2 format
|
# Test file for raw vs. qcow2 format
|
||||||
info = self._qemu_img_info(path, volume['name'])
|
info = self._qemu_img_info(path, volume.name)
|
||||||
data['format'] = info.file_format
|
data['format'] = info.file_format
|
||||||
if data['format'] not in ['raw', 'qcow2']:
|
if data['format'] not in ['raw', 'qcow2']:
|
||||||
msg = _('%s must be a valid raw or qcow2 image.') % path
|
msg = _('%s must be a valid raw or qcow2 image.') % path
|
||||||
@ -213,7 +213,7 @@ class ScalityDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
def extend_volume(self, volume, size_gb):
|
def extend_volume(self, volume, size_gb):
|
||||||
volume_path = self.local_path(volume)
|
volume_path = self.local_path(volume)
|
||||||
|
|
||||||
info = self._qemu_img_info(volume_path, volume['name'])
|
info = self._qemu_img_info(volume_path, volume.name)
|
||||||
backing_fmt = info.file_format
|
backing_fmt = info.file_format
|
||||||
|
|
||||||
if backing_fmt not in ['raw', 'qcow2']:
|
if backing_fmt not in ['raw', 'qcow2']:
|
||||||
@ -230,7 +230,7 @@ class ScalityDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
qcow2.
|
qcow2.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
info_path = self._local_path_volume_info(snapshot['volume'])
|
info_path = self._local_path_volume_info(snapshot.volume)
|
||||||
|
|
||||||
# For BC compat' with version < 2 of this driver
|
# For BC compat' with version < 2 of this driver
|
||||||
try:
|
try:
|
||||||
@ -241,15 +241,15 @@ class ScalityDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
else:
|
else:
|
||||||
path_to_snap_img = self.local_path(snapshot)
|
path_to_snap_img = self.local_path(snapshot)
|
||||||
else:
|
else:
|
||||||
vol_path = self._local_volume_dir(snapshot['volume'])
|
vol_path = self._local_volume_dir(snapshot.volume)
|
||||||
|
|
||||||
forward_file = snap_info[snapshot['id']]
|
forward_file = snap_info[snapshot.id]
|
||||||
forward_path = os.path.join(vol_path, forward_file)
|
forward_path = os.path.join(vol_path, forward_file)
|
||||||
|
|
||||||
# Find the file which backs this file, which represents the point
|
# Find the file which backs this file, which represents the point
|
||||||
# when this snapshot was created.
|
# when this snapshot was created.
|
||||||
img_info = self._qemu_img_info(forward_path,
|
img_info = self._qemu_img_info(forward_path,
|
||||||
snapshot['volume']['name'])
|
snapshot.volume.name)
|
||||||
|
|
||||||
path_to_snap_img = os.path.join(vol_path, img_info.backing_file)
|
path_to_snap_img = os.path.join(vol_path, img_info.backing_file)
|
||||||
|
|
||||||
@ -270,7 +270,7 @@ class ScalityDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
"""Create a new backup from an existing volume."""
|
"""Create a new backup from an existing volume."""
|
||||||
volume = self.db.volume_get(context, backup['volume_id'])
|
volume = self.db.volume_get(context, backup['volume_id'])
|
||||||
volume_local_path = self.local_path(volume)
|
volume_local_path = self.local_path(volume)
|
||||||
LOG.info(_LI('Begin backup of volume %s.'), volume['name'])
|
LOG.info(_LI('Begin backup of volume %s.'), volume.name)
|
||||||
|
|
||||||
qemu_img_info = image_utils.qemu_img_info(volume_local_path)
|
qemu_img_info = image_utils.qemu_img_info(volume_local_path)
|
||||||
if qemu_img_info.file_format != 'raw':
|
if qemu_img_info.file_format != 'raw':
|
||||||
@ -290,8 +290,8 @@ class ScalityDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
def restore_backup(self, context, backup, volume, backup_service):
|
def restore_backup(self, context, backup, volume, backup_service):
|
||||||
"""Restore an existing backup to a new or existing volume."""
|
"""Restore an existing backup to a new or existing volume."""
|
||||||
LOG.info(_LI('Restoring backup %(backup)s to volume %(volume)s.'),
|
LOG.info(_LI('Restoring backup %(backup)s to volume %(volume)s.'),
|
||||||
{'backup': backup['id'], 'volume': volume['name']})
|
{'backup': backup['id'], 'volume': volume.name})
|
||||||
volume_local_path = self.local_path(volume)
|
volume_local_path = self.local_path(volume)
|
||||||
with utils.temporary_chown(volume_local_path):
|
with utils.temporary_chown(volume_local_path):
|
||||||
with open(volume_local_path, 'wb') as volume_file:
|
with open(volume_local_path, 'wb') as volume_file:
|
||||||
backup_service.restore(backup, volume['id'], volume_file)
|
backup_service.restore(backup, volume.id, volume_file)
|
||||||
|
@ -90,7 +90,7 @@ def update_allocation_data(delete=False):
|
|||||||
if delete:
|
if delete:
|
||||||
allocated_size_gb = None
|
allocated_size_gb = None
|
||||||
else:
|
else:
|
||||||
allocated_size_gb = requested_size or volume['size']
|
allocated_size_gb = requested_size or volume.size
|
||||||
|
|
||||||
inst.update_disk_allocation_data(volume, allocated_size_gb)
|
inst.update_disk_allocation_data(volume, allocated_size_gb)
|
||||||
return ret_val
|
return ret_val
|
||||||
@ -149,11 +149,11 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
active_file = self.get_active_image_from_info(volume)
|
active_file = self.get_active_image_from_info(volume)
|
||||||
fmt = self.get_volume_format(volume)
|
fmt = self.get_volume_format(volume)
|
||||||
|
|
||||||
data = {'export': volume['provider_location'],
|
data = {'export': volume.provider_location,
|
||||||
'format': fmt,
|
'format': fmt,
|
||||||
'name': active_file}
|
'name': active_file}
|
||||||
if volume['provider_location'] in self.shares:
|
if volume.provider_location in self.shares:
|
||||||
data['options'] = self.shares[volume['provider_location']]
|
data['options'] = self.shares[volume.provider_location]
|
||||||
return {
|
return {
|
||||||
'driver_volume_type': self.driver_volume_type,
|
'driver_volume_type': self.driver_volume_type,
|
||||||
'data': data,
|
'data': data,
|
||||||
@ -206,8 +206,8 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
self._allocation_data = json.load(f)
|
self._allocation_data = json.load(f)
|
||||||
|
|
||||||
def update_disk_allocation_data(self, volume, virtual_size_gb=None):
|
def update_disk_allocation_data(self, volume, virtual_size_gb=None):
|
||||||
volume_name = volume['name']
|
volume_name = volume.name
|
||||||
smbfs_share = volume['provider_location']
|
smbfs_share = volume.provider_location
|
||||||
if smbfs_share:
|
if smbfs_share:
|
||||||
share_hash = self._get_hash_str(smbfs_share)
|
share_hash = self._get_hash_str(smbfs_share)
|
||||||
else:
|
else:
|
||||||
@ -257,7 +257,7 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
|
|
||||||
def _get_local_volume_path_template(self, volume):
|
def _get_local_volume_path_template(self, volume):
|
||||||
local_dir = self._local_volume_dir(volume)
|
local_dir = self._local_volume_dir(volume)
|
||||||
local_path_template = os.path.join(local_dir, volume['name'])
|
local_path_template = os.path.join(local_dir, volume.name)
|
||||||
return local_path_template
|
return local_path_template
|
||||||
|
|
||||||
def _lookup_local_volume_path(self, volume_path_template):
|
def _lookup_local_volume_path(self, volume_path_template):
|
||||||
@ -271,9 +271,9 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
return '%s%s' % (self.local_path(volume), '.info')
|
return '%s%s' % (self.local_path(volume), '.info')
|
||||||
|
|
||||||
def _get_new_snap_path(self, snapshot):
|
def _get_new_snap_path(self, snapshot):
|
||||||
vol_path = self.local_path(snapshot['volume'])
|
vol_path = self.local_path(snapshot.volume)
|
||||||
snap_path, ext = os.path.splitext(vol_path)
|
snap_path, ext = os.path.splitext(vol_path)
|
||||||
snap_path += '.' + snapshot['id'] + ext
|
snap_path += '.' + snapshot.id + ext
|
||||||
return snap_path
|
return snap_path
|
||||||
|
|
||||||
def get_volume_format(self, volume, qemu_format=False):
|
def get_volume_format(self, volume, qemu_format=False):
|
||||||
@ -285,7 +285,7 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
if ext in self._SUPPORTED_IMAGE_FORMATS:
|
if ext in self._SUPPORTED_IMAGE_FORMATS:
|
||||||
volume_format = ext
|
volume_format = ext
|
||||||
else:
|
else:
|
||||||
info = self._qemu_img_info(volume_path, volume['name'])
|
info = self._qemu_img_info(volume_path, volume.name)
|
||||||
volume_format = info.file_format
|
volume_format = info.file_format
|
||||||
else:
|
else:
|
||||||
volume_format = (
|
volume_format = (
|
||||||
@ -303,12 +303,12 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
@update_allocation_data(delete=True)
|
@update_allocation_data(delete=True)
|
||||||
def delete_volume(self, volume):
|
def delete_volume(self, volume):
|
||||||
"""Deletes a logical volume."""
|
"""Deletes a logical volume."""
|
||||||
if not volume['provider_location']:
|
if not volume.provider_location:
|
||||||
LOG.warning(_LW('Volume %s does not have provider_location '
|
LOG.warning(_LW('Volume %s does not have provider_location '
|
||||||
'specified, skipping.'), volume['name'])
|
'specified, skipping.'), volume.name)
|
||||||
return
|
return
|
||||||
|
|
||||||
self._ensure_share_mounted(volume['provider_location'])
|
self._ensure_share_mounted(volume.provider_location)
|
||||||
volume_dir = self._local_volume_dir(volume)
|
volume_dir = self._local_volume_dir(volume)
|
||||||
mounted_path = os.path.join(volume_dir,
|
mounted_path = os.path.join(volume_dir,
|
||||||
self.get_active_image_from_info(volume))
|
self.get_active_image_from_info(volume))
|
||||||
@ -343,7 +343,7 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
"""
|
"""
|
||||||
volume_format = self.get_volume_format(volume)
|
volume_format = self.get_volume_format(volume)
|
||||||
volume_path = self.local_path(volume)
|
volume_path = self.local_path(volume)
|
||||||
volume_size = volume['size']
|
volume_size = volume.size
|
||||||
|
|
||||||
LOG.debug("Creating new volume at %s.", volume_path)
|
LOG.debug("Creating new volume at %s.", volume_path)
|
||||||
|
|
||||||
@ -470,7 +470,7 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
snapshot, backing_filename, new_snap_path)
|
snapshot, backing_filename, new_snap_path)
|
||||||
|
|
||||||
def _check_snapshot_support(self, snapshot):
|
def _check_snapshot_support(self, snapshot):
|
||||||
volume_format = self.get_volume_format(snapshot['volume'])
|
volume_format = self.get_volume_format(snapshot.volume)
|
||||||
# qemu-img does not yet support differencing vhd/vhdx
|
# qemu-img does not yet support differencing vhd/vhdx
|
||||||
if volume_format in (self._DISK_FORMAT_VHD, self._DISK_FORMAT_VHDX):
|
if volume_format in (self._DISK_FORMAT_VHD, self._DISK_FORMAT_VHDX):
|
||||||
err_msg = _("Snapshots are not supported for this volume "
|
err_msg = _("Snapshots are not supported for this volume "
|
||||||
@ -480,7 +480,7 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
@remotefs_drv.locked_volume_id_operation
|
@remotefs_drv.locked_volume_id_operation
|
||||||
@update_allocation_data()
|
@update_allocation_data()
|
||||||
def extend_volume(self, volume, size_gb):
|
def extend_volume(self, volume, size_gb):
|
||||||
LOG.info(_LI('Extending volume %s.'), volume['id'])
|
LOG.info(_LI('Extending volume %s.'), volume.id)
|
||||||
self._extend_volume(volume, size_gb)
|
self._extend_volume(volume, size_gb)
|
||||||
|
|
||||||
def _extend_volume(self, volume, size_gb):
|
def _extend_volume(self, volume, size_gb):
|
||||||
@ -489,7 +489,7 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
self._check_extend_volume_support(volume, size_gb)
|
self._check_extend_volume_support(volume, size_gb)
|
||||||
LOG.info(_LI('Resizing file to %sG...'), size_gb)
|
LOG.info(_LI('Resizing file to %sG...'), size_gb)
|
||||||
|
|
||||||
self._do_extend_volume(volume_path, size_gb, volume['name'])
|
self._do_extend_volume(volume_path, size_gb, volume.name)
|
||||||
|
|
||||||
def _do_extend_volume(self, volume_path, size_gb, volume_name):
|
def _do_extend_volume(self, volume_path, size_gb, volume_name):
|
||||||
info = self._qemu_img_info(volume_path, volume_name)
|
info = self._qemu_img_info(volume_path, volume_name)
|
||||||
@ -523,12 +523,12 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
'driver when no snapshots exist.')
|
'driver when no snapshots exist.')
|
||||||
raise exception.InvalidVolume(msg)
|
raise exception.InvalidVolume(msg)
|
||||||
|
|
||||||
extend_by = int(size_gb) - volume['size']
|
extend_by = int(size_gb) - volume.size
|
||||||
if not self._is_share_eligible(volume['provider_location'],
|
if not self._is_share_eligible(volume.provider_location,
|
||||||
extend_by):
|
extend_by):
|
||||||
raise exception.ExtendVolumeError(reason='Insufficient space to '
|
raise exception.ExtendVolumeError(reason='Insufficient space to '
|
||||||
'extend volume %s to %sG.'
|
'extend volume %s to %sG.'
|
||||||
% (volume['id'], size_gb))
|
% (volume.id, size_gb))
|
||||||
|
|
||||||
@remotefs_drv.locked_volume_id_operation
|
@remotefs_drv.locked_volume_id_operation
|
||||||
@update_allocation_data()
|
@update_allocation_data()
|
||||||
@ -544,22 +544,22 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
|
|
||||||
LOG.debug("Snapshot: %(snap)s, volume: %(vol)s, "
|
LOG.debug("Snapshot: %(snap)s, volume: %(vol)s, "
|
||||||
"volume_size: %(size)s",
|
"volume_size: %(size)s",
|
||||||
{'snap': snapshot['id'],
|
{'snap': snapshot.id,
|
||||||
'vol': volume['id'],
|
'vol': volume.id,
|
||||||
'size': volume_size})
|
'size': volume_size})
|
||||||
|
|
||||||
info_path = self._local_path_volume_info(snapshot['volume'])
|
info_path = self._local_path_volume_info(snapshot.volume)
|
||||||
snap_info = self._read_info_file(info_path)
|
snap_info = self._read_info_file(info_path)
|
||||||
vol_dir = self._local_volume_dir(snapshot['volume'])
|
vol_dir = self._local_volume_dir(snapshot.volume)
|
||||||
out_format = self.get_volume_format(volume, qemu_format=True)
|
out_format = self.get_volume_format(volume, qemu_format=True)
|
||||||
|
|
||||||
forward_file = snap_info[snapshot['id']]
|
forward_file = snap_info[snapshot.id]
|
||||||
forward_path = os.path.join(vol_dir, forward_file)
|
forward_path = os.path.join(vol_dir, forward_file)
|
||||||
|
|
||||||
# Find the file which backs this file, which represents the point
|
# Find the file which backs this file, which represents the point
|
||||||
# when this snapshot was created.
|
# when this snapshot was created.
|
||||||
img_info = self._qemu_img_info(forward_path,
|
img_info = self._qemu_img_info(forward_path,
|
||||||
snapshot['volume']['name'])
|
snapshot.volume.name)
|
||||||
path_to_snap_img = os.path.join(vol_dir, img_info.backing_file)
|
path_to_snap_img = os.path.join(vol_dir, img_info.backing_file)
|
||||||
|
|
||||||
LOG.debug("Will copy from snapshot at %s", path_to_snap_img)
|
LOG.debug("Will copy from snapshot at %s", path_to_snap_img)
|
||||||
@ -581,15 +581,15 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
self.configuration.volume_dd_blocksize)
|
self.configuration.volume_dd_blocksize)
|
||||||
|
|
||||||
self._do_extend_volume(self.local_path(volume),
|
self._do_extend_volume(self.local_path(volume),
|
||||||
volume['size'],
|
volume.size,
|
||||||
volume['name'])
|
volume.name)
|
||||||
|
|
||||||
data = image_utils.qemu_img_info(self.local_path(volume))
|
data = image_utils.qemu_img_info(self.local_path(volume))
|
||||||
virt_size = data.virtual_size / units.Gi
|
virt_size = data.virtual_size / units.Gi
|
||||||
if virt_size != volume['size']:
|
if virt_size != volume.size:
|
||||||
raise exception.ImageUnacceptable(
|
raise exception.ImageUnacceptable(
|
||||||
image_id=image_id,
|
image_id=image_id,
|
||||||
reason=(_("Expected volume size was %d") % volume['size'])
|
reason=(_("Expected volume size was %d") % volume.size)
|
||||||
+ (_(" but size is now %d.") % virt_size))
|
+ (_(" but size is now %d.") % virt_size))
|
||||||
|
|
||||||
@remotefs_drv.locked_volume_id_operation
|
@remotefs_drv.locked_volume_id_operation
|
||||||
@ -639,38 +639,15 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
return flags.strip(',')
|
return flags.strip(',')
|
||||||
|
|
||||||
def _get_volume_format_spec(self, volume):
|
def _get_volume_format_spec(self, volume):
|
||||||
# This method needs to be able to parse metadata/volume type
|
vol_type = volume.volume_type
|
||||||
# specs for volume SQLAlchemy objects and versioned objects,
|
extra_specs = {}
|
||||||
# as the transition to versioned objects is not complete and the
|
if vol_type and vol_type.extra_specs:
|
||||||
# driver may receive either of them.
|
extra_specs = vol_type.extra_specs
|
||||||
#
|
|
||||||
# TODO(lpetrut): once the transition to oslo.versionedobjects is
|
|
||||||
# complete, we can skip some of those checks.
|
|
||||||
volume_metadata_specs = {}
|
|
||||||
volume_type_specs = {}
|
|
||||||
|
|
||||||
if volume.get('metadata') and isinstance(volume.metadata, dict):
|
extra_specs.update(volume.metadata or {})
|
||||||
volume_metadata_specs.update(volume.metadata)
|
|
||||||
elif volume.get('volume_metadata'):
|
|
||||||
volume_metadata_specs.update(
|
|
||||||
{spec.key: spec.value for spec in volume.volume_metadata})
|
|
||||||
|
|
||||||
vol_type = volume.get('volume_type')
|
return (extra_specs.get('volume_format') or
|
||||||
if vol_type:
|
self.configuration.smbfs_default_volume_format)
|
||||||
specs = vol_type.get('extra_specs') or {}
|
|
||||||
if isinstance(specs, dict):
|
|
||||||
volume_type_specs.update(specs)
|
|
||||||
else:
|
|
||||||
volume_type_specs.update(
|
|
||||||
{spec.key: spec.value for spec in specs})
|
|
||||||
|
|
||||||
# In this case, we want the volume metadata specs to take
|
|
||||||
# precedence over the volume type specs.
|
|
||||||
for specs in [volume_metadata_specs, volume_type_specs]:
|
|
||||||
for key, val in specs.items():
|
|
||||||
if 'volume_format' in key:
|
|
||||||
return val
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _is_file_size_equal(self, path, size):
|
def _is_file_size_equal(self, path, size):
|
||||||
"""Checks if file size at path is equal to size."""
|
"""Checks if file size at path is equal to size."""
|
||||||
|
@ -110,10 +110,10 @@ class VZStorageDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
active_file = self.get_active_image_from_info(volume)
|
active_file = self.get_active_image_from_info(volume)
|
||||||
active_file_path = os.path.join(self._local_volume_dir(volume),
|
active_file_path = os.path.join(self._local_volume_dir(volume),
|
||||||
active_file)
|
active_file)
|
||||||
info = self._qemu_img_info(active_file_path, volume['name'])
|
info = self._qemu_img_info(active_file_path, volume.name)
|
||||||
fmt = info.file_format
|
fmt = info.file_format
|
||||||
|
|
||||||
data = {'export': volume['provider_location'],
|
data = {'export': volume.provider_location,
|
||||||
'format': fmt,
|
'format': fmt,
|
||||||
'name': active_file,
|
'name': active_file,
|
||||||
}
|
}
|
||||||
@ -228,7 +228,7 @@ class VZStorageDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
|
|
||||||
@remotefs_drv.locked_volume_id_operation
|
@remotefs_drv.locked_volume_id_operation
|
||||||
def extend_volume(self, volume, size_gb):
|
def extend_volume(self, volume, size_gb):
|
||||||
LOG.info(_LI('Extending volume %s.'), volume['id'])
|
LOG.info(_LI('Extending volume %s.'), volume.id)
|
||||||
self._extend_volume(volume, size_gb)
|
self._extend_volume(volume, size_gb)
|
||||||
|
|
||||||
def _extend_volume(self, volume, size_gb):
|
def _extend_volume(self, volume, size_gb):
|
||||||
@ -257,12 +257,12 @@ class VZStorageDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
'driver when no snapshots exist.')
|
'driver when no snapshots exist.')
|
||||||
raise exception.InvalidVolume(msg)
|
raise exception.InvalidVolume(msg)
|
||||||
|
|
||||||
extend_by = int(size_gb) - volume['size']
|
extend_by = int(size_gb) - volume.size
|
||||||
if not self._is_share_eligible(volume['provider_location'],
|
if not self._is_share_eligible(volume.provider_location,
|
||||||
extend_by):
|
extend_by):
|
||||||
raise exception.ExtendVolumeError(reason='Insufficient space to '
|
raise exception.ExtendVolumeError(reason='Insufficient space to '
|
||||||
'extend volume %s to %sG.'
|
'extend volume %s to %sG.'
|
||||||
% (volume['id'], size_gb))
|
% (volume.id, size_gb))
|
||||||
|
|
||||||
def _is_file_size_equal(self, path, size):
|
def _is_file_size_equal(self, path, size):
|
||||||
"""Checks if file size at path is equal to size."""
|
"""Checks if file size at path is equal to size."""
|
||||||
@ -279,23 +279,23 @@ class VZStorageDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
|
|
||||||
LOG.debug("_copy_volume_from_snapshot: snapshot: %(snap)s, "
|
LOG.debug("_copy_volume_from_snapshot: snapshot: %(snap)s, "
|
||||||
"volume: %(vol)s, volume_size: %(size)s.",
|
"volume: %(vol)s, volume_size: %(size)s.",
|
||||||
{'snap': snapshot['id'],
|
{'snap': snapshot.id,
|
||||||
'vol': volume['id'],
|
'vol': volume.id,
|
||||||
'size': volume_size,
|
'size': volume_size,
|
||||||
})
|
})
|
||||||
|
|
||||||
info_path = self._local_path_volume_info(snapshot['volume'])
|
info_path = self._local_path_volume_info(snapshot.volume)
|
||||||
snap_info = self._read_info_file(info_path)
|
snap_info = self._read_info_file(info_path)
|
||||||
vol_dir = self._local_volume_dir(snapshot['volume'])
|
vol_dir = self._local_volume_dir(snapshot.volume)
|
||||||
out_format = "raw"
|
out_format = "raw"
|
||||||
|
|
||||||
forward_file = snap_info[snapshot['id']]
|
forward_file = snap_info[snapshot.id]
|
||||||
forward_path = os.path.join(vol_dir, forward_file)
|
forward_path = os.path.join(vol_dir, forward_file)
|
||||||
|
|
||||||
# Find the file which backs this file, which represents the point
|
# Find the file which backs this file, which represents the point
|
||||||
# when this snapshot was created.
|
# when this snapshot was created.
|
||||||
img_info = self._qemu_img_info(forward_path,
|
img_info = self._qemu_img_info(forward_path,
|
||||||
snapshot['volume']['name'])
|
snapshot.volume.name)
|
||||||
path_to_snap_img = os.path.join(vol_dir, img_info.backing_file)
|
path_to_snap_img = os.path.join(vol_dir, img_info.backing_file)
|
||||||
|
|
||||||
LOG.debug("_copy_volume_from_snapshot: will copy "
|
LOG.debug("_copy_volume_from_snapshot: will copy "
|
||||||
@ -309,13 +309,13 @@ class VZStorageDriver(remotefs_drv.RemoteFSSnapDriver):
|
|||||||
@remotefs_drv.locked_volume_id_operation
|
@remotefs_drv.locked_volume_id_operation
|
||||||
def delete_volume(self, volume):
|
def delete_volume(self, volume):
|
||||||
"""Deletes a logical volume."""
|
"""Deletes a logical volume."""
|
||||||
if not volume['provider_location']:
|
if not volume.provider_location:
|
||||||
msg = (_('Volume %s does not have provider_location '
|
msg = (_('Volume %s does not have provider_location '
|
||||||
'specified, skipping.') % volume['name'])
|
'specified, skipping.') % volume.name)
|
||||||
LOG.error(msg)
|
LOG.error(msg)
|
||||||
raise exception.VzStorageException(msg)
|
raise exception.VzStorageException(msg)
|
||||||
|
|
||||||
self._ensure_share_mounted(volume['provider_location'])
|
self._ensure_share_mounted(volume.provider_location)
|
||||||
volume_dir = self._local_volume_dir(volume)
|
volume_dir = self._local_volume_dir(volume)
|
||||||
mounted_path = os.path.join(volume_dir,
|
mounted_path = os.path.join(volume_dir,
|
||||||
self.get_active_image_from_info(volume))
|
self.get_active_image_from_info(volume))
|
||||||
|
Loading…
Reference in New Issue
Block a user