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:
Dmitry Guryanov 2016-01-21 19:39:42 +03:00 committed by Evgeny Antyshev
parent ec51a682db
commit 369572f5b2
16 changed files with 872 additions and 844 deletions

View File

@ -34,8 +34,9 @@ from cinder import db
from cinder import exception
from cinder.i18n import _
from cinder.image import image_utils
from cinder.objects import fields
from cinder import test
from cinder.tests.unit import fake_snapshot
from cinder.tests.unit import fake_volume
from cinder import utils
from cinder.volume import driver as base_driver
from cinder.volume.drivers import glusterfs
@ -45,16 +46,6 @@ from cinder.volume.drivers import remotefs as remotefs_drv
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):
msg = "Tests are broken: mock this out."
@ -66,6 +57,17 @@ class FakeDb(object):
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):
"""Test case for GlusterFS driver."""
@ -75,12 +77,10 @@ class GlusterFsDriverTestCase(test.TestCase):
TEST_SIZE_IN_GB = 1
TEST_MNT_POINT = '/mnt/glusterfs'
TEST_MNT_POINT_BASE = '/mnt/test'
TEST_LOCAL_PATH = '/mnt/glusterfs/volume-123'
TEST_FILE_NAME = 'test.txt'
TEST_SHARES_CONFIG_FILE = '/etc/cinder/test-shares.conf'
TEST_TMP_FILE = '/tmp/tempfile'
VOLUME_UUID = 'abcdefab-cdef-abcd-efab-cdefabcdefab'
VOLUME_NAME = 'volume-%s' % VOLUME_UUID
SNAP_UUID = 'bacadaca-baca-daca-baca-dacadacadaca'
SNAP_UUID_2 = 'bebedede-bebe-dede-bebe-dedebebedede'
@ -102,6 +102,7 @@ class GlusterFsDriverTestCase(test.TestCase):
db=FakeDb())
self._driver.shares = {}
compute.API = mock.MagicMock()
self.context = context.get_admin_context()
def assertRaisesAndMessageMatches(
self, excClass, msg, callableObj, *args, **kwargs):
@ -126,13 +127,12 @@ class GlusterFsDriverTestCase(test.TestCase):
self.TEST_MNT_POINT_BASE)
drv = self._driver
volume = DumbVolume()
volume['id'] = self.VOLUME_UUID
volume['provider_location'] = self.TEST_EXPORT1
volume['name'] = 'volume-123'
volume = fake_volume.fake_volume_obj(
self.context,
provider_location=self.TEST_EXPORT1)
self.assertEqual(
'/mnt/test/ab03ab34eaca46a5fb81878f7e9b91fc/volume-123',
'/mnt/test/ab03ab34eaca46a5fb81878f7e9b91fc/%s' % volume.name,
drv.local_path(volume))
def test_mount_glusterfs(self):
@ -470,17 +470,20 @@ class GlusterFsDriverTestCase(test.TestCase):
drv._find_share,
self.TEST_SIZE_IN_GB)
def _simple_volume(self, id=None):
volume = DumbVolume()
volume['provider_location'] = self.TEST_EXPORT1
def _simple_volume(self, id=None, **updates):
if id is None:
volume['id'] = self.VOLUME_UUID
else:
volume['id'] = id
# volume['name'] mirrors format from db/sqlalchemy/models.py
volume['name'] = 'volume-%s' % volume['id']
volume['size'] = 10
volume['status'] = 'available'
id = self.VOLUME_UUID
if 'id' not in updates:
updates['id'] = self.VOLUME_UUID
if 'name' not in updates:
updates['name'] = 'volume-%s' % id
if 'status' not in updates:
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
@ -497,7 +500,7 @@ class GlusterFsDriverTestCase(test.TestCase):
drv._do_create_volume(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,
volume_size)
mock_set_rw_permissions_for_all.\
@ -516,7 +519,7 @@ class GlusterFsDriverTestCase(test.TestCase):
drv._do_create_volume(volume)
volume_path = drv.local_path(volume)
volume_size = volume['size']
volume_size = volume.size
mock_fallocate.assert_called_once_with(volume_path,
volume_size)
mock_set_rw_permissions_for_all.\
@ -539,7 +542,7 @@ class GlusterFsDriverTestCase(test.TestCase):
drv._do_create_volume(volume)
volume_path = drv.local_path(volume)
volume_size = volume['size']
volume_size = volume.size
mock_fallocate.assert_called_once_with(volume_path,
volume_size)
mock_create_regular_file.assert_called_once_with(volume_path,
@ -556,9 +559,10 @@ class GlusterFsDriverTestCase(test.TestCase):
mock_do_create_volume,\
mock.patch.object(drv, '_ensure_shares_mounted') as \
mock_ensure_shares_mounted:
volume = DumbVolume()
volume['size'] = self.TEST_SIZE_IN_GB
volume['id'] = self.VOLUME_UUID
volume = fake_volume.fake_volume_obj(self.context,
size=self.TEST_SIZE_IN_GB,
id=self.VOLUME_UUID)
mock_find_share.return_value = self.TEST_EXPORT2
drv.create_volume(volume)
self.assertTrue(mock_ensure_shares_mounted.called)
self.assertTrue(mock_do_create_volume.called)
@ -575,9 +579,9 @@ class GlusterFsDriverTestCase(test.TestCase):
mock_ensure_shares_mounted:
mock_find_share.return_value = self.TEST_EXPORT1
volume = DumbVolume()
volume['size'] = self.TEST_SIZE_IN_GB
volume['id'] = self.VOLUME_UUID
volume = fake_volume.fake_volume_obj(self.context,
size=self.TEST_SIZE_IN_GB,
id=self.VOLUME_UUID)
result = drv.create_volume(volume)
self.assertEqual(self.TEST_EXPORT1, result['provider_location'])
self.assertTrue(mock_ensure_shares_mounted.called)
@ -610,7 +614,7 @@ class GlusterFsDriverTestCase(test.TestCase):
self._driver.delete_volume(volume)
mock_ensure_share_mounted.assert_called_once_with(
volume['provider_location'])
volume.provider_location)
mock_local_volume_dir.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,
@ -827,10 +831,12 @@ class GlusterFsDriverTestCase(test.TestCase):
with mock.patch.object(drv, '_execute') as mock_execute,\
mock.patch.object(drv, '_ensure_share_mounted') as \
mock_ensure_share_mounted:
volume = DumbVolume()
volume['id'] = self.VOLUME_UUID
volume['name'] = 'volume-123'
volume['provider_location'] = self.TEST_EXPORT1
volume = fake_volume.fake_volume_obj(
self.context,
id=self.VOLUME_UUID,
display_name='volume-123',
provider_location=self.TEST_EXPORT1)
drv.delete_volume(volume)
@ -845,10 +851,10 @@ class GlusterFsDriverTestCase(test.TestCase):
with mock.patch.object(drv, '_execute') as mock_execute,\
mock.patch.object(drv, '_ensure_share_mounted') as \
mock_ensure_share_mounted:
volume = DumbVolume()
volume['id'] = self.VOLUME_UUID
volume['name'] = 'volume-123'
volume['provider_location'] = None
volume = fake_volume.fake_volume_obj(self.context,
id=self.VOLUME_UUID,
name='volume-123',
provider_location=None)
drv.delete_volume(volume)
@ -868,10 +874,6 @@ class GlusterFsDriverTestCase(test.TestCase):
mock_read_file.return_value = '{"%(id)s": "volume-%(id)s"}' %\
{'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)
self.assertEqual('volume-%s' % self.VOLUME_UUID,
@ -897,7 +899,7 @@ class GlusterFsDriverTestCase(test.TestCase):
mock_qemu_img_info,\
mock.patch.object(image_utils, 'resize_image') as \
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_qemu_img_info.return_value = img_info
@ -940,9 +942,6 @@ class GlusterFsDriverTestCase(test.TestCase):
def test_create_snapshot_online(self):
drv = self._driver
volume = self._simple_volume()
volume['status'] = 'in-use'
hashed = drv._get_hash_str(self.TEST_EXPORT1)
volume_file = 'volume-%s' % self.VOLUME_UUID
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')
snap_ref = {'name': 'test snap (online)',
'volume_id': self.VOLUME_UUID,
'volume': volume,
'id': self.SNAP_UUID,
'context': ctxt,
'status': fields.SnapshotStatus.CREATING,
'progress': 'asdf'}
snap_ref = fake_snapshot.fake_snapshot_obj(
ctxt,
display_name='test snap (online)',
volume_id=self.VOLUME_UUID,
id=self.SNAP_UUID,
status='creating',
progress='asdf')
snap_ref.context = ctxt
snap_path = '%s.%s' % (volume_path, 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(drv, '_nova') as mock_nova,\
mock.patch.object(time, 'sleep') as mock_sleep:
create_info = {'snapshot_id': snap_ref['id'],
create_info = {'snapshot_id': snap_ref.id,
'type': 'qcow2',
'new_file': snap_file}
snap_ref_progress = snap_ref.copy()
snap_ref_progress['status'] = fields.SnapshotStatus.CREATING
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
]
mock_snapshot_get.side_effect = SideEffectList(
snap_ref,
progress = ['0%', '50%', '90%'])
drv._create_snapshot_online(snap_ref, snap_file, snap_path)
mock_do_create_snapshot.\
@ -999,7 +986,7 @@ class GlusterFsDriverTestCase(test.TestCase):
drv = self._driver
volume = self._simple_volume()
volume['status'] = 'in-use'
volume.status = 'in-use'
hashed = drv._get_hash_str(self.TEST_EXPORT1)
volume_file = 'volume-%s' % self.VOLUME_UUID
@ -1009,11 +996,12 @@ class GlusterFsDriverTestCase(test.TestCase):
ctxt = context.RequestContext('fake_user', 'fake_project')
snap_ref = {'name': 'test snap (online)',
'volume_id': self.VOLUME_UUID,
'volume': volume,
'id': self.SNAP_UUID,
'context': ctxt}
snap_ref = fake_snapshot.fake_snapshot_obj(
ctxt,
display_name='test snap (online)',
volume_id=self.VOLUME_UUID,
id=self.SNAP_UUID)
snap_ref.context = ctxt
snap_path = '%s.%s' % (volume_path, 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(drv, '_nova') as mock_nova,\
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()
snap_ref_progress_0p['progress'] = '0%'
snap_ref_progress_50p = snap_ref_progress.copy()
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
]
mock_snapshot_get.side_effect = SideEffectList(
snap_ref,
progress = ['0%', '50%', '99%'],
status = ["creating", "creating", "error"])
self.assertRaisesAndMessageMatches(
exception.RemoteFSException,
@ -1054,15 +1030,19 @@ class GlusterFsDriverTestCase(test.TestCase):
drv = self._driver
volume = self._simple_volume()
volume['status'] = 'in-use'
volume.status = 'in-use'
ctxt = context.RequestContext('fake_user', 'fake_project')
snap_ref = {'name': 'test snap to delete (online)',
'volume_id': self.VOLUME_UUID,
'volume': volume,
'id': self.SNAP_UUID,
'context': ctxt}
snap_ref = fake_snapshot.fake_snapshot_obj(
ctxt,
display_name='test snap to delete (online)',
volume_id=self.VOLUME_UUID,
status="deleting",
id=self.SNAP_UUID)
snap_ref.context = ctxt
snap_ref.volume = volume
hashed = drv._get_hash_str(self.TEST_EXPORT1)
volume_file = 'volume-%s' % self.VOLUME_UUID
@ -1120,22 +1100,8 @@ class GlusterFsDriverTestCase(test.TestCase):
'volume_id': self.VOLUME_UUID
}
snap_ref_progress = snap_ref.copy()
snap_ref_progress['status'] = 'deleting'
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
]
mock_snapshot_get.side_effect = SideEffectList(
snap_ref, progress = ['0%', '50%', '90%'])
drv.delete_snapshot(snap_ref)
@ -1156,15 +1122,18 @@ class GlusterFsDriverTestCase(test.TestCase):
drv = self._driver
volume = self._simple_volume()
volume['status'] = 'in-use'
volume.status = 'in-use'
ctxt = context.RequestContext('fake_user', 'fake_project')
snap_ref = {'name': 'test snap to delete (online)',
'volume_id': self.VOLUME_UUID,
'volume': volume,
'id': self.SNAP_UUID,
'context': ctxt}
snap_ref = fake_snapshot.fake_snapshot_obj(
ctxt,
display_name='test snap to delete (online)',
volume_id=self.VOLUME_UUID,
status='deleting',
id=self.SNAP_UUID)
snap_ref.volume = volume
snap_ref.context = ctxt
hashed = drv._get_hash_str(self.TEST_EXPORT1)
volume_file = 'volume-%s' % self.VOLUME_UUID
@ -1225,21 +1194,8 @@ class GlusterFsDriverTestCase(test.TestCase):
'file_to_merge': snap_file,
'volume_id': self.VOLUME_UUID}
snap_ref_progress = snap_ref.copy()
snap_ref_progress['status'] = 'deleting'
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]
mock_snapshot_get.side_effect = SideEffectList(
snap_ref, progress = ['0%', '50%', '90%'])
drv.delete_snapshot(snap_ref)
@ -1260,15 +1216,17 @@ class GlusterFsDriverTestCase(test.TestCase):
drv = self._driver
volume = self._simple_volume()
volume['status'] = 'in-use'
volume.status = 'in-use'
ctxt = context.RequestContext('fake_user', 'fake_project')
snap_ref = {'name': 'test snap to delete (online)',
'volume_id': self.VOLUME_UUID,
'volume': volume,
'id': self.SNAP_UUID,
'context': ctxt}
snap_ref = fake_snapshot.fake_snapshot_obj(
ctxt,
display_name='test snap to delete (online)',
volume_id=self.VOLUME_UUID,
id=self.SNAP_UUID)
snap_ref.volume = volume
snap_ref.context = ctxt
hashed = drv._get_hash_str(self.TEST_EXPORT1)
volume_file = 'volume-%s' % self.VOLUME_UUID
@ -1320,23 +1278,10 @@ class GlusterFsDriverTestCase(test.TestCase):
return paths[args[0]]
mock_qemu_img_info.side_effect = img_info_side_effect
snap_ref_progress = snap_ref.copy()
snap_ref_progress['status'] = 'deleting'
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]
mock_snapshot_get.side_effect = SideEffectList(
snap_ref,
progress = ['0%', '50%', '99%'],
status = ['deleting', 'deleting', 'error'])
self.assertRaisesAndMessageMatches(exception.RemoteFSException,
'Unable to delete snapshot',
drv.delete_snapshot,
@ -1355,9 +1300,9 @@ class GlusterFsDriverTestCase(test.TestCase):
self.TEST_MNT_POINT_BASE)
volume = self._simple_volume()
vol_filename = volume['name']
vol_filename_2 = volume['name'] + '.abcd'
vol_filename_3 = volume['name'] + '.efef'
vol_filename = volume.name
vol_filename_2 = volume.name + '.abcd'
vol_filename_3 = volume.name + '.efef'
hashed = drv._get_hash_str(self.TEST_EXPORT1)
vol_dir = '%s/%s' % (self.TEST_MNT_POINT_BASE, hashed)
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,
drv._get_hash_str(self.TEST_EXPORT1))
src_vol_path = os.path.join(vol_dir, src_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'],
'size': src_volume['size'],
'volume_size': src_volume['size'],
'volume_id': src_volume['id'],
'id': 'tmp-snap-%s' % src_volume['id'],
'volume': src_volume}
snap_file = dest_volume['name'] + '.' + snapshot['id']
size = dest_volume['size']
src_vol_path = os.path.join(vol_dir, src_volume.name)
dest_vol_path = os.path.join(vol_dir, dest_volume.name)
snapshot = fake_snapshot.fake_snapshot_obj(
self.context,
volume_name=src_volume.name,
display_name='clone-snap-%s' % src_volume.id,
size=src_volume.size,
volume_size=src_volume.size,
volume_id=src_volume.id,
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,
snapshot['id']: snap_file}
snapshot.id: snap_file}
qemu_img_output = """image: %s
file format: raw
virtual size: 1.0G (1073741824 bytes)
disk size: 173K
backing file: %s
""" % (snap_file, src_volume['name'])
""" % (snap_file, src_volume.name)
img_info = imageutils.QemuImgInfo(qemu_img_output)
mock_qemu_img_info.return_value = img_info
@ -1464,18 +1413,20 @@ class GlusterFsDriverTestCase(test.TestCase):
drv = self._driver
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'}
snap_ref = fake_snapshot.fake_snapshot_obj(
self.context,
volume_name=src_volume.name,
display_name='clone-snap-%s' % src_volume.id,
size=src_volume.size,
volume_size=src_volume.size,
volume_id=src_volume.id,
id=self.SNAP_UUID,
status='available')
snap_ref.volume = src_volume
new_volume = DumbVolume()
new_volume['id'] = self.VOLUME_UUID
new_volume['size'] = snap_ref['size']
new_volume = fake_volume.fake_volume_obj(self.context,
id=self.VOLUME_UUID,
size=snap_ref.volume.size)
with mock.patch.object(drv, '_ensure_shares_mounted') as \
mock_ensure_shares_mounted,\
@ -1492,7 +1443,7 @@ class GlusterFsDriverTestCase(test.TestCase):
mock_do_create_volume.assert_called_once_with(new_volume)
mock_copy_volume.assert_called_once_with(snap_ref,
new_volume,
new_volume['size'])
new_volume.size)
def test_initialize_connection(self):
drv = self._driver
@ -1502,14 +1453,14 @@ class GlusterFsDriverTestCase(test.TestCase):
file format: raw
virtual size: 1.0G (1073741824 bytes)
disk size: 173K
""" % volume['name']
""" % volume.name
img_info = imageutils.QemuImgInfo(qemu_img_output)
with mock.patch.object(drv, 'get_active_image_from_info') as \
mock_get_active_image_from_info,\
mock.patch.object(image_utils, 'qemu_img_info') as \
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
conn_info = drv.initialize_connection(volume, None)
@ -1539,7 +1490,7 @@ class GlusterFsDriverTestCase(test.TestCase):
mock_backup_volume:
ctxt = context.RequestContext('fake_user', 'fake_project')
volume = self._simple_volume()
backup = {'volume_id': volume['id']}
backup = {'volume_id': volume.id}
mock_volume_get.return_value = volume
mock_get_active_image_from_info.return_value = '/some/path'
@ -1566,7 +1517,7 @@ class GlusterFsDriverTestCase(test.TestCase):
mock_backup_volume:
ctxt = context.RequestContext('fake_user', 'fake_project')
volume = self._simple_volume()
backup = {'volume_id': volume['id']}
backup = {'volume_id': volume.id}
mock_volume_get.return_value = volume
mock_get_active_image_from_info.return_value = '/some/file2'
@ -1586,7 +1537,7 @@ class GlusterFsDriverTestCase(test.TestCase):
mock_snapshot_get_all_for_volume:
ctxt = context.RequestContext('fake_user', 'fake_project')
volume = self._simple_volume()
backup = {'volume_id': volume['id']}
backup = {'volume_id': volume.id}
mock_snapshot_get_all_for_volume.return_value = [
{'snap1': 'a'},
{'snap2': 'b'}
@ -1606,7 +1557,7 @@ class GlusterFsDriverTestCase(test.TestCase):
mock_qemu_img_info:
ctxt = context.RequestContext('fake_user', 'fake_project')
volume = self._simple_volume()
backup = {'volume_id': volume['id']}
backup = {'volume_id': volume.id}
mock_volume_get.return_value = volume
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:
ctxt = context.RequestContext('fake_user', 'fake_project')
volume = self._simple_volume()
backup = {'volume_id': volume['id']}
backup = {'volume_id': volume.id}
mock_volume_get.return_value = volume
mock_get_active_image_from_info.return_value = '/some/path'
@ -1651,7 +1602,7 @@ class GlusterFsDriverTestCase(test.TestCase):
drv = self._driver
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'}
with mock.patch.object(drv, 'get_active_image_from_info') as \
@ -1664,7 +1615,7 @@ class GlusterFsDriverTestCase(test.TestCase):
mock_upload_volume, \
mock.patch.object(image_utils, 'create_temporary_file') as \
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
@ -1674,7 +1625,7 @@ class GlusterFsDriverTestCase(test.TestCase):
file format: raw
virtual size: 1.0G (1073741824 bytes)
disk size: 173K
""" % volume['name']
""" % volume.name
img_info = imageutils.QemuImgInfo(qemu_img_output)
mock_qemu_img_info.return_value = img_info
@ -1694,7 +1645,7 @@ class GlusterFsDriverTestCase(test.TestCase):
drv = self._driver
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'}
with mock.patch.object(drv, 'get_active_image_from_info') as \
@ -1709,7 +1660,7 @@ class GlusterFsDriverTestCase(test.TestCase):
mock_upload_volume, \
mock.patch.object(image_utils, 'create_temporary_file') as \
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
@ -1719,7 +1670,7 @@ class GlusterFsDriverTestCase(test.TestCase):
file format: qcow2
virtual size: 1.0G (1073741824 bytes)
disk size: 173K
""" % volume['name']
""" % volume.name
img_info = imageutils.QemuImgInfo(qemu_img_output)
mock_qemu_img_info.return_value = img_info
@ -1757,7 +1708,7 @@ class GlusterFsDriverTestCase(test.TestCase):
mock_upload_volume, \
mock.patch.object(image_utils, 'create_temporary_file') as \
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

View File

@ -23,9 +23,11 @@ import mock
from mox3 import mox as mox_lib
import six
from cinder import context
from cinder import exception
from cinder.image import image_utils
from cinder import test
from cinder.tests.unit import fake_volume
from cinder import utils as cinder_utils
from cinder.volume import configuration as conf
from cinder.volume.drivers.netapp import common
@ -158,6 +160,7 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
self._driver.ssc_library = mock.Mock()
config = self._driver.configuration
config.netapp_vserver = FAKE_VSERVER
self.context = context.get_admin_context()
def test_create_snapshot(self):
"""Test snapshot can be created and deleted."""
@ -519,7 +522,8 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
def test_clone_image_cloneableshare_raw(self):
drv = self._driver
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(drv, '_find_image_in_cache')
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).\
AndReturn(self.get_img_info('raw'))
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._discover_file_till_timeout(mox_lib.IgnoreArg()).AndReturn(True)
drv._set_rw_permissions('/mnt/vol')
drv._resize_image_file({'name': 'vol'}, mox_lib.IgnoreArg())
drv._set_rw_permissions('/mnt/%s' % volume_name)
drv._resize_image_file({'name': volume_name}, mox_lib.IgnoreArg())
mox.ReplayAll()
drv.clone_image(
@ -559,7 +563,8 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
def test_clone_image_cloneableshare_notraw(self):
drv = self._driver
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(drv, '_find_image_in_cache')
mox.StubOutWithMock(drv, '_is_cloneable_share')
@ -572,6 +577,7 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
mox.StubOutWithMock(image_utils, 'convert_image')
mox.StubOutWithMock(drv, '_register_image_in_cache')
mox.StubOutWithMock(drv, '_is_share_clone_compatible')
mox.StubOutWithMock(drv, '_do_qos_for_volume')
utils.get_volume_extra_specs(mox_lib.IgnoreArg())
drv._find_image_in_cache(mox_lib.IgnoreArg()).AndReturn([])
@ -585,13 +591,15 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
image_utils.convert_image(mox_lib.IgnoreArg(),
mox_lib.IgnoreArg(),
'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'))
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._discover_file_till_timeout(mox_lib.IgnoreArg()).AndReturn(True)
drv._set_rw_permissions('/mnt/vol')
drv._resize_image_file({'name': 'vol'}, mox_lib.IgnoreArg())
drv._set_rw_permissions('/mnt/%s' % volume_name)
drv._resize_image_file({'name': volume_name}, mox_lib.IgnoreArg())
mox.ReplayAll()
drv.clone_image(
@ -605,7 +613,8 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
def test_clone_image_file_not_discovered(self):
drv = self._driver
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(drv, '_find_image_in_cache')
mox.StubOutWithMock(drv, '_is_cloneable_share')
@ -631,12 +640,12 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
image_utils.convert_image(mox_lib.IgnoreArg(),
mox_lib.IgnoreArg(),
'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'))
drv._register_image_in_cache(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)
mox.ReplayAll()
@ -1180,6 +1189,8 @@ class NetAppCmodeNfsDriverOnlyTestCase(test.TestCase):
'spec': None,
}
self.context = context.get_admin_context()
@mock.patch.object(utils, 'LOG', mock.Mock())
def test_create_volume(self):
drv = self._driver
@ -1234,47 +1245,48 @@ class NetAppCmodeNfsDriverOnlyTestCase(test.TestCase):
def test_copy_img_to_vol_copyoffload_success(self):
drv = self._driver
context = object()
volume = {'id': 'vol_id', 'name': 'name'}
volume = fake_volume.fake_volume_obj(self.context)
image_service = object()
image_id = 'image_id'
drv.zapi_client.get_ontapi_version = mock.Mock(return_value=(1, 20))
drv._copy_from_img_service = mock.Mock()
drv._get_provider_location = mock.Mock(return_value='share')
drv._get_vol_for_share = mock.Mock(return_value='vol')
drv._get_vol_for_share = mock.Mock(return_value=volume.id)
drv._update_stale_vols = mock.Mock()
drv.copy_image_to_volume(context, volume, image_service, image_id)
drv._copy_from_img_service.assert_called_once_with(context, volume,
drv.copy_image_to_volume(self.context, volume, image_service, image_id)
drv._copy_from_img_service.assert_called_once_with(self.context,
volume,
image_service,
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):
drv = self._driver
context = object()
volume = {'id': 'vol_id', 'name': 'name'}
volume = fake_volume.fake_volume_obj(self.context)
image_service = object()
image_id = 'image_id'
drv.zapi_client.get_ontapi_version = mock.Mock(return_value=(1, 20))
drv._copy_from_img_service = mock.Mock(side_effect=Exception())
nfs_base.NetAppNfsDriver.copy_image_to_volume = mock.Mock()
drv._get_provider_location = mock.Mock(return_value='share')
drv._get_vol_for_share = mock.Mock(return_value='vol')
drv._get_vol_for_share = mock.Mock(return_value=volume.id)
drv._update_stale_vols = mock.Mock()
drv.copy_image_to_volume(context, volume, image_service, image_id)
drv._copy_from_img_service.assert_called_once_with(context, volume,
drv.copy_image_to_volume(self.context, volume, image_service, image_id)
drv._copy_from_img_service.assert_called_once_with(self.context,
volume,
image_service,
image_id)
nfs_base.NetAppNfsDriver.copy_image_to_volume. \
assert_called_once_with(context, volume, image_service, image_id)
drv._update_stale_vols.assert_called_once_with('vol')
assert_called_once_with(self.context, volume,
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):
drv = self._driver
context = object()
volume = {'id': 'vol_id', 'name': 'name'}
volume = fake_volume.fake_volume_obj(self.context)
image_service = mock.Mock()
image_service.get_location.return_value = (mock.Mock(), mock.Mock())
image_service.show.return_value = {'size': 0}
@ -1296,15 +1308,14 @@ class NetAppCmodeNfsDriverOnlyTestCase(test.TestCase):
# Verify the original error is propagated
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')
def test_img_service_raw_copyoffload_workflow_success(self,
mock_qemu_img_info):
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'
context = object()
image_service = mock.Mock()
image_service.get_location.return_value = ('nfs://ip1/openstack/img',
None)
@ -1329,9 +1340,10 @@ class NetAppCmodeNfsDriverOnlyTestCase(test.TestCase):
drv._clone_file_dst_exists = 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_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)
assert drv._execute.call_count == 1
@ -1344,9 +1356,8 @@ class NetAppCmodeNfsDriverOnlyTestCase(test.TestCase):
mock_qemu_img_info,
mock_cvrt_image):
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'
context = object()
image_service = mock.Mock()
image_service.get_location.return_value = ('nfs://ip1/openstack/img',
None)
@ -1371,9 +1382,10 @@ class NetAppCmodeNfsDriverOnlyTestCase(test.TestCase):
drv._clone_file_dst_exists = 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_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)
assert mock_cvrt_image.call_count == 1
assert drv._execute.call_count == 1
@ -1393,6 +1405,7 @@ class NetApp7modeNfsDriverTestCase(NetAppCmodeNfsDriverTestCase):
self._driver = netapp_nfs_7mode.NetApp7modeNfsDriver(
configuration=create_configuration())
self._driver.zapi_client = mock.Mock()
self.context = context.get_admin_context()
def _prepare_delete_snapshot_mock(self, snapshot_exists):
drv = self._driver

View File

@ -21,25 +21,16 @@ import os
import mock
from oslo_utils import units
from cinder import context
from cinder import exception
from cinder.image import image_utils
from cinder import test
from cinder.tests.unit import fake_volume
from cinder.volume import configuration as conf
from cinder.volume.drivers import nfs
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):
TEST_FILE_NAME = 'test.txt'
TEST_EXPORT = 'nas-host1:/export'
@ -346,18 +337,19 @@ class NfsDriverTestCase(test.TestCase):
mock_exc = mock.patch.object(self._driver, '_execute')
self._execute = mock_exc.start()
self.addCleanup(mock_exc.stop)
self.context = context.get_admin_context()
def test_local_path(self):
"""local_path common use case."""
self.configuration.nfs_mount_point_base = self.TEST_MNT_POINT_BASE
drv = self._driver
volume = DumbVolume()
volume['provider_location'] = self.TEST_NFS_EXPORT1
volume['name'] = 'volume-123'
volume = fake_volume.fake_volume_obj(
self.context,
provider_location=self.TEST_NFS_EXPORT1)
self.assertEqual(
'/mnt/test/2f4f60214cf43c595666dd815f0360a4/volume-123',
'/mnt/test/2f4f60214cf43c595666dd815f0360a4/%s' % volume.name,
drv.local_path(volume))
@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):
"""resize_image common case usage."""
drv = self._driver
TEST_IMG_SOURCE = 'foo.img'
volume = {'size': self.TEST_SIZE_IN_GB, 'name': TEST_IMG_SOURCE}
volume = fake_volume.fake_volume_obj(self.context,
size=self.TEST_SIZE_IN_GB)
TEST_IMG_SOURCE = 'volume-%s' % volume.id
with mock.patch.object(drv, 'local_path',
return_value=TEST_IMG_SOURCE):
@ -581,12 +574,10 @@ class NfsDriverTestCase(test.TestCase):
self.assertEqual(2, mock_get_capacity_info.call_count)
def _simple_volume(self):
volume = DumbVolume()
volume['provider_location'] = '127.0.0.1:/mnt'
volume['name'] = 'volume_name'
volume['size'] = 10
return volume
return fake_volume.fake_volume_obj(self.context,
display_name='volume_name',
provider_location='127.0.0.1:/mnt',
size=10)
def test_create_sparsed_volume(self):
drv = self._driver
@ -626,13 +617,14 @@ class NfsDriverTestCase(test.TestCase):
"""create_volume ensures shares provided in config are mounted."""
drv = self._driver
drv._find_share = mock.Mock()
drv._find_share.return_value = self.TEST_NFS_EXPORT1
drv._do_create_volume = mock.Mock()
with mock.patch.object(
drv, '_ensure_share_mounted') as mock_ensure_share:
drv._ensure_share_mounted()
volume = DumbVolume()
volume['size'] = self.TEST_SIZE_IN_GB
volume = fake_volume.fake_volume_obj(self.context,
size=self.TEST_SIZE_IN_GB)
drv.create_volume(volume)
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:
mock_find_share.return_value = self.TEST_NFS_EXPORT1
volume = DumbVolume()
volume['size'] = self.TEST_SIZE_IN_GB
volume = fake_volume.fake_volume_obj(self.context,
size=self.TEST_SIZE_IN_GB)
result = drv.create_volume(volume)
self.assertEqual(self.TEST_NFS_EXPORT1,
result['provider_location'])
@ -658,9 +650,10 @@ class NfsDriverTestCase(test.TestCase):
drv = self._driver
drv._ensure_share_mounted = mock.Mock()
volume = DumbVolume()
volume['name'] = 'volume-123'
volume['provider_location'] = self.TEST_NFS_EXPORT1
volume = fake_volume.fake_volume_obj(
self.context,
display_name='volume-123',
provider_location=self.TEST_NFS_EXPORT1)
with mock.patch.object(drv, 'local_path') as mock_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):
"""delete_volume should ensure that corresponding share is mounted."""
drv = self._driver
volume = DumbVolume()
volume['name'] = 'volume-123'
volume['provider_location'] = self.TEST_NFS_EXPORT1
volume = fake_volume.fake_volume_obj(
self.context,
display_name='volume-123',
provider_location=self.TEST_NFS_EXPORT1)
with mock.patch.object(
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):
"""delete_volume shouldn't delete if provider_location missed."""
drv = self._driver
volume = DumbVolume()
volume['name'] = 'volume-123'
volume['provider_location'] = None
volume = fake_volume.fake_volume_obj(self.context,
name='volume-123',
provider_location=None)
with mock.patch.object(drv, '_ensure_share_mounted'):
drv.delete_volume(volume)
@ -846,8 +840,11 @@ class NfsDriverTestCase(test.TestCase):
def test_extend_volume(self):
"""Extend a volume by 1."""
drv = self._driver
volume = {'id': '80ee16b6-75d2-4d54-9539-ffc1b4b0fb10', 'size': 1,
'provider_location': 'nfs_share'}
volume = fake_volume.fake_volume_obj(
self.context,
id='80ee16b6-75d2-4d54-9539-ffc1b4b0fb10',
size=1,
provider_location='nfs_share')
path = 'path'
newSize = volume['size'] + 1
@ -865,8 +862,11 @@ class NfsDriverTestCase(test.TestCase):
def test_extend_volume_failure(self):
"""Error during extend operation."""
drv = self._driver
volume = {'id': '80ee16b6-75d2-4d54-9539-ffc1b4b0fb10', 'size': 1,
'provider_location': 'nfs_share'}
volume = fake_volume.fake_volume_obj(
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(drv, 'local_path', return_value='path'):
@ -880,8 +880,11 @@ class NfsDriverTestCase(test.TestCase):
def test_extend_volume_insufficient_space(self):
"""Insufficient space on nfs_share during extend operation."""
drv = self._driver
volume = {'id': '80ee16b6-75d2-4d54-9539-ffc1b4b0fb10', 'size': 1,
'provider_location': 'nfs_share'}
volume = fake_volume.fake_volume_obj(
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(drv, 'local_path', return_value='path'):
@ -1125,8 +1128,8 @@ class NfsDriverDoSetupTestCase(test.TestCase):
def _test_update_migrated_volume(self, volume_status, rename_volume,
rename_exception=False):
drv = nfs.NfsDriver(configuration=self.configuration)
fake_volume_id = 'vol1'
fake_new_volume_id = 'vol2'
fake_volume_id = 'f51b5730-13b7-11e6-a238-fa163e67a298'
fake_new_volume_id = '12341234-13b7-11e6-a238-fa163e67a298'
fake_provider_source = 'fake_provider_source'
fake_provider = 'fake_provider'
base_dir = '/dir_base/'
@ -1135,27 +1138,34 @@ class NfsDriverDoSetupTestCase(test.TestCase):
current_name = volume_name_template % fake_new_volume_id
original_volume_path = base_dir + original_volume_name
current_path = base_dir + current_name
fake_volume = {'size': 1, 'id': fake_volume_id,
'provider_location': fake_provider_source,
'_name_id': None}
fake_new_volume = {'size': 1, 'id': fake_new_volume_id,
'provider_location': fake_provider,
'_name_id': None}
volume = fake_volume.fake_volume_obj(
self.context,
id=fake_volume_id,
size=1,
provider_location=fake_provider_source,
_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:
local_path.return_value = base_dir + current_name
if volume_status == 'in-use':
update = drv.update_migrated_volume(self.context,
fake_volume,
fake_new_volume,
volume,
new_volume,
volume_status)
self.assertEqual({'_name_id': fake_new_volume_id,
'provider_location': fake_provider}, update)
elif rename_exception:
rename_volume.side_effect = OSError
update = drv.update_migrated_volume(self.context,
fake_volume,
fake_new_volume,
volume,
new_volume,
volume_status)
rename_volume.assert_called_once_with(current_path,
original_volume_path)
@ -1163,8 +1173,8 @@ class NfsDriverDoSetupTestCase(test.TestCase):
'provider_location': fake_provider}, update)
else:
update = drv.update_migrated_volume(self.context,
fake_volume,
fake_new_volume,
volume,
new_volume,
volume_status)
rename_volume.assert_called_once_with(current_path,
original_volume_path)
@ -1175,7 +1185,7 @@ class NfsDriverDoSetupTestCase(test.TestCase):
"Ensure that driver.retype() is there."""
drv = nfs.NfsDriver(configuration=self.configuration)
v1 = DumbVolume()
v1 = fake_volume.fake_volume_obj(self.context)
ret = drv.retype(self.context,
v1,

View File

@ -30,6 +30,8 @@ from cinder import context
from cinder import exception
from cinder.image import image_utils
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.drivers import quobyte
@ -37,16 +39,6 @@ from cinder.volume.drivers import quobyte
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):
msg = "Tests are broken: mock this out."
@ -66,7 +58,6 @@ class QuobyteDriverTestCase(test.TestCase):
TEST_SIZE_IN_GB = 1
TEST_MNT_POINT = '/mnt/quobyte'
TEST_MNT_POINT_BASE = '/mnt'
TEST_LOCAL_PATH = '/mnt/quobyte/volume-123'
TEST_FILE_NAME = 'test.txt'
TEST_SHARES_CONFIG_FILE = '/etc/cinder/test-shares.conf'
TEST_TMP_FILE = '/tmp/tempfile'
@ -94,6 +85,7 @@ class QuobyteDriverTestCase(test.TestCase):
db=FakeDb())
self._driver.shares = {}
self._driver.set_nas_security_options(is_new_cinder_install=False)
self.context = context.get_admin_context()
def assertRaisesAndMessageMatches(
self, excClass, msg, callableObj, *args, **kwargs):
@ -115,13 +107,11 @@ class QuobyteDriverTestCase(test.TestCase):
def test_local_path(self):
"""local_path common use case."""
drv = self._driver
volume = DumbVolume()
volume['provider_location'] = self.TEST_QUOBYTE_VOLUME
volume['name'] = 'volume-123'
vol_id = self.VOLUME_UUID
volume = self._simple_volume(_name_id=vol_id)
self.assertEqual(
'/mnt/1331538734b757ed52d0e18c0a7210cd/volume-123',
'/mnt/1331538734b757ed52d0e18c0a7210cd/volume-%s' % vol_id,
drv.local_path(volume))
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.
self.assertGreaterEqual(mock_get_available_capacity.call_count, 0)
def _simple_volume(self, uuid=None):
volume = DumbVolume()
volume['provider_location'] = self.TEST_QUOBYTE_VOLUME
if uuid is None:
volume['id'] = self.VOLUME_UUID
else:
volume['id'] = uuid
# volume['name'] mirrors format from db/sqlalchemy/models.py
volume['name'] = 'volume-%s' % volume['id']
volume['size'] = 10
volume['status'] = 'available'
def _simple_volume(self, **kwargs):
updates = {'id': self.VOLUME_UUID,
'provider_location': self.TEST_QUOBYTE_VOLUME,
'display_name': 'volume-%s' % self.VOLUME_UUID,
'size': 10,
'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):
drv = self._driver
@ -501,11 +490,11 @@ class QuobyteDriverTestCase(test.TestCase):
drv.LOG = mock.Mock()
drv._find_share = mock.Mock()
drv._find_share.return_value = self.TEST_QUOBYTE_VOLUME
drv._do_create_volume = mock.Mock()
drv._ensure_shares_mounted = mock.Mock()
volume = DumbVolume()
volume['size'] = self.TEST_SIZE_IN_GB
volume = self._simple_volume(size=self.TEST_SIZE_IN_GB)
drv.create_volume(volume)
drv._find_share.assert_called_once_with(mock.ANY)
@ -521,8 +510,7 @@ class QuobyteDriverTestCase(test.TestCase):
drv._do_create_volume = mock.Mock()
drv._find_share = mock.Mock(return_value=self.TEST_QUOBYTE_VOLUME)
volume = DumbVolume()
volume['size'] = self.TEST_SIZE_IN_GB
volume = self._simple_volume(size=self.TEST_SIZE_IN_GB)
result = drv.create_volume(volume)
self.assertEqual(self.TEST_QUOBYTE_VOLUME, result['provider_location'])
@ -575,9 +563,7 @@ class QuobyteDriverTestCase(test.TestCase):
drv._execute = mock.Mock()
volume = DumbVolume()
volume['name'] = 'volume-123'
volume['provider_location'] = self.TEST_QUOBYTE_VOLUME
volume = self._simple_volume(display_name='volume-123')
drv._ensure_share_mounted = mock.Mock()
@ -596,9 +582,8 @@ class QuobyteDriverTestCase(test.TestCase):
drv._ensure_share_mounted = mock.Mock()
drv._execute = mock.Mock()
volume = DumbVolume()
volume['name'] = 'volume-123'
volume['provider_location'] = None
volume = self._simple_volume(display_name='volume-123',
provider_location=None)
drv.delete_volume(volume)
@ -638,7 +623,7 @@ class QuobyteDriverTestCase(test.TestCase):
# lots of test vars to be prepared at first
dest_volume = self._simple_volume(
'c1073000-0000-0000-0000-0000000c1073')
id='c1073000-0000-0000-0000-0000000c1073')
src_volume = self._simple_volume()
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'])
info_path = os.path.join(vol_dir, src_volume['name']) + '.info'
snapshot = {'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}
snapshot = fake_snapshot.fake_snapshot_obj(
self.context,
volume_name=src_volume.name,
display_name='clone-snap-%s' % src_volume.id,
size=src_volume.size,
volume_size=src_volume.size,
volume_id=src_volume.id,
id=self.SNAP_UUID)
snapshot.volume = src_volume
snap_file = dest_volume['name'] + '.' + snapshot['id']
snap_path = os.path.join(vol_dir, snap_file)
@ -692,17 +679,18 @@ class QuobyteDriverTestCase(test.TestCase):
drv = self._driver
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()
new_volume['size'] = snap_ref['size']
snap_ref = fake_snapshot.fake_snapshot_obj(
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,
drv.create_volume_from_snapshot,
@ -713,17 +701,18 @@ class QuobyteDriverTestCase(test.TestCase):
drv = self._driver
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()
new_volume['size'] = snap_ref['size']
snap_ref = fake_snapshot.fake_snapshot_obj(
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._find_share = mock.Mock(return_value=self.TEST_QUOBYTE_VOLUME)

View File

@ -12,15 +12,19 @@
# License for the specific language governing permissions and limitations
# under the License.
import collections
import copy
import os
import ddt
import mock
from cinder import context
from cinder import exception
from cinder.image import image_utils
from cinder import test
from cinder.tests.unit import fake_snapshot
from cinder.tests.unit import fake_volume
from cinder import utils
from cinder.volume.drivers import remotefs
@ -28,25 +32,7 @@ from cinder.volume.drivers import remotefs
@ddt.ddt
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_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):
super(RemoteFsSnapDriverTestCase, self).setUp()
@ -55,21 +41,32 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
self._driver._execute = 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,
stale_snapshot=False,
is_active_image=True):
# If the snapshot is not the active image, it is guaranteed that
# 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,
self._FAKE_SNAPSHOT['id']: fake_snapshot_name}
self._fake_snapshot.id: fake_snapshot_name}
fake_snap_img_info = mock.Mock()
fake_base_img_info = mock.Mock()
if stale_snapshot:
fake_snap_img_info.backing_file = None
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_base_img_info.backing_file = None
fake_base_img_info.file_format = 'raw'
@ -91,72 +88,71 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
expected_info = {
'active': fake_snapshot_name,
self._FAKE_SNAPSHOT_ID: fake_snapshot_name
self._fake_snapshot.id: fake_snapshot_name
}
if volume_in_use:
fake_snapshot = copy.deepcopy(self._FAKE_SNAPSHOT)
fake_snapshot['volume']['status'] = 'in-use'
self._fake_snapshot.volume.status = 'in-use'
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:
self._driver._delete_stale_snapshot.assert_called_once_with(
fake_snapshot)
self._fake_snapshot)
else:
expected_online_delete_info = {
'active_file': fake_snapshot_name,
'snapshot_file': fake_snapshot_name,
'base_file': self._FAKE_VOLUME_NAME,
'base_file': self._fake_volume.name,
'base_id': None,
'new_base_file': None
}
self._driver._delete_snapshot_online.assert_called_once_with(
self._FAKE_CONTEXT, fake_snapshot,
self.context, self._fake_snapshot,
expected_online_delete_info)
elif is_active_image:
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._FAKE_SNAPSHOT_PATH)
self.assertNotIn(self._FAKE_SNAPSHOT_ID, fake_info)
self._fake_snapshot_path)
self.assertNotIn(self._fake_snapshot.id, fake_info)
self._driver._write_info_file.assert_called_once_with(
mock.sentinel.fake_info_path, fake_info)
else:
fake_upper_snap_id = 'fake_upper_snap_id'
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_backing_chain = [
{'filename': fake_upper_snap_name,
'backing-filename': fake_snapshot_name},
{'filename': fake_snapshot_name,
'backing-filename': self._FAKE_VOLUME_NAME},
{'filename': self._FAKE_VOLUME_NAME,
'backing-filename': self._fake_volume.name},
{'filename': self._fake_volume.name,
'backing-filename': None}]
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
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._get_backing_chain_for_path = mock.Mock(
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._FAKE_SNAPSHOT_PATH)
self._fake_snapshot_path)
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)
self._driver._write_info_file.assert_called_once_with(
mock.sentinel.fake_info_path, expected_info)
@ -175,12 +171,12 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
self._test_delete_snapshot(is_active_image=False)
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 = {
'active': self._FAKE_VOLUME_NAME,
self._FAKE_SNAPSHOT_ID: fake_snapshot_name
'active': self._fake_volume.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(
return_value=mock.sentinel.fake_info_path)
@ -190,42 +186,41 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
return_value=self._FAKE_MNT_POINT)
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(
mock.sentinel.fake_info_path, expected_info)
def test_do_create_snapshot(self):
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(
self._driver._local_volume_dir(),
self._FAKE_VOLUME_NAME)
self._fake_volume.name)
self._driver._execute = mock.Mock()
self._driver._set_rw_permissions = mock.Mock()
self._driver._qemu_img_info = mock.Mock(
return_value=mock.Mock(file_format=mock.sentinel.backing_fmt))
self._driver._do_create_snapshot(self._FAKE_SNAPSHOT,
self._FAKE_VOLUME_NAME,
self._FAKE_SNAPSHOT_PATH)
self._driver._do_create_snapshot(self._fake_snapshot,
self._fake_volume.name,
self._fake_snapshot_path)
command1 = ['qemu-img', 'create', '-f', 'qcow2', '-o',
'backing_file=%s' % fake_backing_path,
self._FAKE_SNAPSHOT_PATH]
self._fake_snapshot_path]
command2 = ['qemu-img', 'rebase', '-u',
'-b', self._FAKE_VOLUME_NAME,
'-b', self._fake_volume.name,
'-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(*command2, run_as_root=True)
def _test_create_snapshot(self, volume_in_use=False):
fake_snapshot = copy.deepcopy(self._FAKE_SNAPSHOT)
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(
return_value=mock.sentinel.fake_info_path)
@ -235,28 +230,28 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
self._driver._create_snapshot_online = mock.Mock()
self._driver._write_info_file = 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(
return_value=self._FAKE_SNAPSHOT_PATH)
return_value=self._fake_snapshot_path)
expected_snapshot_info = {
'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:
fake_snapshot['volume']['status'] = 'in-use'
self._fake_snapshot.volume.status = 'in-use'
expected_method_called = '_create_snapshot_online'
else:
fake_snapshot['volume']['status'] = 'available'
self._fake_snapshot.volume.status = 'available'
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.assert_called_with(
fake_snapshot, self._FAKE_VOLUME_NAME,
self._FAKE_SNAPSHOT_PATH)
self._fake_snapshot, self._fake_volume.name,
self._fake_snapshot_path)
self._driver._write_info_file.assert_called_with(
mock.sentinel.fake_info_path,
expected_snapshot_info)
@ -268,12 +263,10 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
self._test_create_snapshot(volume_in_use=True)
def test_create_snapshot_invalid_volume(self):
fake_snapshot = copy.deepcopy(self._FAKE_SNAPSHOT)
fake_snapshot['volume']['status'] = 'error'
self._fake_snapshot.volume.status = 'error'
self.assertRaises(exception.InvalidVolume,
self._driver._create_snapshot,
fake_snapshot)
self._fake_snapshot)
@mock.patch('cinder.db.snapshot_get')
@mock.patch('time.sleep')
@ -294,18 +287,18 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
mock_do_create_snapshot:
self.assertRaises(exception.RemoteFSConcurrentRequest,
self._driver._create_snapshot_online,
self._FAKE_SNAPSHOT,
self._FAKE_VOLUME_NAME,
self._FAKE_SNAPSHOT_PATH)
self._fake_snapshot,
self._fake_volume.name,
self._fake_snapshot_path)
mock_do_create_snapshot.assert_called_once_with(
self._FAKE_SNAPSHOT, self._FAKE_VOLUME_NAME,
self._FAKE_SNAPSHOT_PATH)
self._fake_snapshot, self._fake_volume.name,
self._fake_snapshot_path)
self.assertEqual([mock.call(1), mock.call(1)],
mock_sleep.call_args_list)
self.assertEqual(3, mock_snapshot_get.call_count)
mock_snapshot_get.assert_called_with(self._FAKE_SNAPSHOT['context'],
self._FAKE_SNAPSHOT['id'])
mock_snapshot_get.assert_called_with(self._fake_snapshot._context,
self._fake_snapshot.id)
@mock.patch.object(utils, 'synchronized')
def _locked_volume_operation_test_helper(self, mock_synchronized, func,
@ -318,7 +311,7 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
mock_synchronized.side_effect = mock_decorator
expected_lock = '%s-%s' % (self._driver.driver_prefix,
self._FAKE_VOLUME_ID)
self._fake_volume.id)
if expected_exception:
self.assertRaises(expected_exception, func,
@ -332,7 +325,8 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
self.assertEqual(mock.sentinel.ret_val, ret_val)
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
def synchronized_func(inst, volume):
@ -342,7 +336,8 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
volume=mock_volume)
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
def synchronized_func(inst, snapshot):
@ -432,22 +427,36 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
mock.patch.object(drv, '_copy_volume_from_snapshot') as \
mock_copy_volume_from_snapshot:
volume = self._FAKE_VOLUME.copy()
src_vref = self._FAKE_VOLUME.copy()
src_vref['id'] = '375e32b2-804a-49f2-b282-85d1d5a5b9e1'
src_vref['name'] = 'volume-%s' % src_vref['id']
volume_ref = {'id': volume['id'],
'name': volume['name'],
'status': volume['status'],
'provider_location': volume['provider_location'],
'size': volume['size']}
snap_ref = {'volume_name': volume['name'],
'name': 'clone-snap-%s' % src_vref['id'],
'size': src_vref['size'],
'volume_size': src_vref['size'],
'volume_id': src_vref['id'],
'id': 'tmp-snap-%s' % src_vref['id'],
'volume': src_vref}
volume = fake_volume.fake_volume_obj(self.context)
src_vref_id = '375e32b2-804a-49f2-b282-85d1d5a5b9e1'
src_vref = fake_volume.fake_volume_obj(
self.context,
id=src_vref_id,
name='volume-%s' % src_vref_id)
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_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)
mock_create_snapshot.assert_called_once_with(snap_ref)

View File

@ -26,27 +26,26 @@ from six.moves import urllib
from cinder import context
from cinder import exception
from cinder import test
from cinder.tests.unit import fake_snapshot
from cinder.tests.unit import fake_volume
from cinder.volume import configuration as conf
import cinder.volume.drivers.scality as driver
_FAKE_VOLUME = {'name': 'volume-a79d463e-1fd5-11e5-a6ff-5b81bfee8544',
'id': 'a79d463e-1fd5-11e5-a6ff-5b81bfee8544',
'provider_location': 'fake_share'}
_FAKE_SNAPSHOT = {'id': 'ae3d6da2-1fd5-11e5-967f-1b8cf3b401ab',
'volume': _FAKE_VOLUME,
'status': 'available',
'provider_location': None,
'volume_size': 1,
'name': 'snapshot-ae3d6da2-1fd5-11e5-967f-1b8cf3b401ab'}
_FAKE_VOLUME_ID = 'a79d463e-1fd5-11e5-a6ff-5b81bfee8544'
_FAKE_VOLUME_NAME = 'volume-a79d463e-1fd5-11e5-a6ff-5b81bfee8544'
_FAKE_SNAPSHOT_ID = 'ae3d6da2-1fd5-11e5-967f-1b8cf3b401ab'
_FAKE_SNAPSHOT_NAME = 'snapshot-ae3d6da2-1fd5-11e5-967f-1b8cf3b401ab'
_FAKE_BACKUP = {'id': '914849d2-2585-11e5-be54-d70ca0c343d6',
'volume_id': _FAKE_VOLUME['id']}
'volume_id': _FAKE_VOLUME_ID}
_FAKE_MNT_POINT = '/tmp'
_FAKE_SOFS_CONFIG = '/etc/sfused.conf'
_FAKE_VOLUME_DIR = 'cinder/volumes'
_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_SNAP_PATH = os.path.join(_FAKE_VOL_BASEDIR, _FAKE_SNAPSHOT['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_MOUNTS_TABLE = [['tmpfs /dev/shm\n'],
['fuse ' + _FAKE_MNT_POINT + '\n']]
@ -66,6 +65,30 @@ class ScalityDriverTestCase(test.TestCase):
self.drv = driver.ScalityDriver(configuration=self.cfg)
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('os.access')
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):
info = imageutils.QemuImgInfo()
info.file_format = 'raw'
info.image = _FAKE_VOLUME['name']
info.image = _FAKE_VOLUME_NAME
mock_qemu_img_info.return_value = info
volume = self._simple_volume()
with mock.patch.object(self.drv, 'get_active_image_from_info') as \
mock_get_active_image_from_info:
mock_get_active_image_from_info.return_value = _FAKE_VOLUME['name']
conn_info = self.drv.initialize_connection(_FAKE_VOLUME, None)
mock_get_active_image_from_info.return_value = _FAKE_VOLUME_NAME
conn_info = self.drv.initialize_connection(volume, None)
expected_conn_info = {
'driver_volume_type': driver.ScalityDriver.driver_volume_type,
'mount_point_base': _FAKE_MNT_POINT,
'data': {
'export': _FAKE_VOLUME['provider_location'],
'name': _FAKE_VOLUME['name'],
'sofs_path': 'cinder/volumes/00/' + _FAKE_VOLUME['name'],
'export': volume.provider_location,
'name': volume.name,
'sofs_path': 'cinder/volumes/00/' + volume.name,
'format': 'raw'
}
}
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.patch("cinder.image.image_utils.resize_image")
@ -236,7 +260,7 @@ class ScalityDriverTestCase(test.TestCase):
info.file_format = 'raw'
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)
@ -249,7 +273,7 @@ class ScalityDriverTestCase(test.TestCase):
mock_qemu_img_info.return_value = info
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.convert_image")
@ -260,8 +284,8 @@ class ScalityDriverTestCase(test.TestCase):
mock.patch.object(self.drv, '_set_rw_permissions_for_all') as \
mock_set_rw_permissions:
mock_read_info_file.side_effect = IOError(errno.ENOENT, '')
self.drv._copy_volume_from_snapshot(_FAKE_SNAPSHOT,
_FAKE_VOLUME, 1)
self.drv._copy_volume_from_snapshot(self._simple_snapshot(),
self._simple_volume(), 1)
mock_read_info_file.assert_called_once_with("%s.info" % _FAKE_VOL_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,
mock_convert_image, mock_resize_image):
new_volume = {'name': 'volume-3fa63b02-1fe5-11e5-b492-abf97a8fb23b',
'id': '3fa63b02-1fe5-11e5-b492-abf97a8fb23b',
'provider_location': 'fake_share'}
new_vol_path = os.path.join(_FAKE_VOL_BASEDIR, new_volume['name'])
new_volume = self._simple_volume(
display_name='volume-3fa63b02-1fe5-11e5-b492-abf97a8fb23b',
id='3fa63b02-1fe5-11e5-b492-abf97a8fb23b',
provider_location='fake_share')
new_vol_path = os.path.join(_FAKE_VOL_BASEDIR, new_volume.name)
info = imageutils.QemuImgInfo()
info.file_format = 'raw'
@ -290,7 +315,7 @@ class ScalityDriverTestCase(test.TestCase):
mock_read_info_file, \
mock.patch.object(self.drv, '_set_rw_permissions_for_all') as \
mock_set_rw_permissions:
self.drv._copy_volume_from_snapshot(_FAKE_SNAPSHOT,
self.drv._copy_volume_from_snapshot(self._simple_snapshot(),
new_volume, 1)
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'
mock_qemu_img_info.return_value = info
backup = {'volume_id': _FAKE_VOLUME['id']}
backup = {'volume_id': _FAKE_VOLUME_ID}
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)
@ -330,7 +355,7 @@ class ScalityDriverTestCase(test.TestCase):
info.file_format = 'qcow2'
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,
context, _FAKE_BACKUP, mock.MagicMock())
@ -345,8 +370,8 @@ class ScalityDriverTestCase(test.TestCase):
info.backing_file = 'fake.img'
mock_qemu_img_info.return_value = info
backup = {'volume_id': _FAKE_VOLUME['id']}
self.drv.db.volume_get.return_value = _FAKE_VOLUME
backup = {'volume_id': _FAKE_VOLUME_ID}
self.drv.db.volume_get.return_value = self._simple_volume()
self.assertRaises(exception.InvalidVolume, self.drv.backup_volume,
context, backup, mock.MagicMock())
@ -358,10 +383,10 @@ class ScalityDriverTestCase(test.TestCase):
def test_restore_bakup(self, mock_open, mock_temporary_chown):
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_temporary_chown.assert_called_once_with(_FAKE_VOL_PATH)
mock_open.assert_called_once_with(_FAKE_VOL_PATH, 'wb')
mock_backup_service.restore.assert_called_once_with(
_FAKE_BACKUP, _FAKE_VOLUME['id'], mock_open().__enter__())
_FAKE_BACKUP, _FAKE_VOLUME_ID, mock_open().__enter__())

View File

@ -21,11 +21,10 @@ import mock
from oslo_utils import fileutils
from cinder import context
from cinder import db
from cinder import exception
from cinder.image import image_utils
from cinder import objects
from cinder import test
from cinder.tests.unit import fake_snapshot
from cinder.tests.unit import fake_volume
from cinder.volume.drivers import remotefs
from cinder.volume.drivers import smbfs
@ -39,7 +38,7 @@ def requires_allocation_data_update(expected_size):
inst._smbfs_driver,
'update_disk_allocation_data') as fake_update:
func(inst, *args, **kwargs)
fake_update.assert_called_once_with(inst._FAKE_VOLUME,
fake_update.assert_called_once_with(inst.volume,
expected_size)
return inner
return wrapper
@ -55,18 +54,10 @@ class SmbFsTestCase(test.TestCase):
_FAKE_TOTAL_SIZE = '2048'
_FAKE_TOTAL_AVAILABLE = '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_VOLUME_PATH = os.path.join(_FAKE_MNT_POINT, _FAKE_VOLUME_NAME)
_FAKE_SNAPSHOT_ID = '5g811859-4928-4cb7-801a-a50c37ceacba'
_FAKE_SNAPSHOT = {'id': _FAKE_SNAPSHOT_ID,
'volume': _FAKE_VOLUME,
'status': 'available',
'volume_size': 1}
_FAKE_VOLUME_SIZE = 1
_FAKE_SNAPSHOT_ID = '50811859-4928-4cb7-801a-a50c37ceacba'
_FAKE_SNAPSHOT_PATH = (
_FAKE_VOLUME_PATH + '-snapshot' + _FAKE_SNAPSHOT_ID)
_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._alloc_info_file_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)
@ -137,24 +144,24 @@ class SmbFsTestCase(test.TestCase):
fake_alloc_data = self._get_fake_allocation_data()
if volume_exists:
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.update_disk_allocation_data(self._FAKE_VOLUME,
self._smbfs_driver.update_disk_allocation_data(self.volume,
virtual_size_gb)
vol_allocated_size = fake_alloc_data[self._FAKE_SHARE_HASH].get(
self._FAKE_VOLUME_NAME, None)
if not virtual_size_gb:
expected_total_allocated = (self._FAKE_TOTAL_ALLOCATED -
self._FAKE_VOLUME['size'])
self.volume.size)
self.assertIsNone(vol_allocated_size)
else:
expected_total_allocated = (self._FAKE_TOTAL_ALLOCATED +
virtual_size_gb -
self._FAKE_VOLUME['size'])
self.volume.size)
self.assertEqual(virtual_size_gb, vol_allocated_size)
update_func.assert_called_once_with()
@ -168,11 +175,11 @@ class SmbFsTestCase(test.TestCase):
def test_update_allocation_data_volume_extended(self):
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):
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)
def test_delete_volume(self):
@ -191,7 +198,7 @@ class SmbFsTestCase(test.TestCase):
return_value=fake_vol_info)
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)
drv._delete.assert_any_call(
@ -266,12 +273,12 @@ class SmbFsTestCase(test.TestCase):
if volume_exists:
self.assertRaises(exception.InvalidVolume,
self._smbfs_driver._do_create_volume,
self._FAKE_VOLUME)
self.volume)
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,
self._FAKE_VOLUME['size']]
self.volume.size]
if volume_format in [self._smbfs_driver._DISK_FORMAT_VHDX,
self._smbfs_driver._DISK_FORMAT_VHD]:
expected_create_args.append(volume_format)
@ -320,14 +327,14 @@ class SmbFsTestCase(test.TestCase):
if not mounted_shares:
self.assertRaises(exception.SmbfsNoSharesMounted,
self._smbfs_driver._find_share,
self._FAKE_VOLUME['size'])
self.volume.size)
elif not eligible_shares:
self.assertRaises(exception.SmbfsNoSuitableShareFound,
self._smbfs_driver._find_share,
self._FAKE_VOLUME['size'])
self.volume.size)
else:
ret_value = self._smbfs_driver._find_share(
self._FAKE_VOLUME['size'])
self.volume.size)
# The eligible share with the minimum allocated space
# will be selected
self.assertEqual('fake_share3', ret_value)
@ -404,12 +411,12 @@ class SmbFsTestCase(test.TestCase):
expected_vol_path if volume_exists else None)
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:
self.assertFalse(mock_get_volume_format.called)
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)
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):
mock_get_local_dir.return_value = self._FAKE_MNT_POINT
ret_val = self._smbfs_driver._get_local_volume_path_template(
self._FAKE_VOLUME)
self.volume)
self.assertEqual(self._FAKE_VOLUME_PATH, ret_val)
@mock.patch('os.path.exists')
@ -457,7 +464,7 @@ class SmbFsTestCase(test.TestCase):
mock_qemu_img_info.return_value.file_format = 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)
if volume_exists:
@ -465,7 +472,7 @@ class SmbFsTestCase(test.TestCase):
self._FAKE_VOLUME_NAME)
self.assertFalse(mock_get_format_spec.called)
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)
return ret_val
@ -506,7 +513,7 @@ class SmbFsTestCase(test.TestCase):
'data': fake_data,
'mount_point_base': self._FAKE_MNT_BASE}
ret_val = self._smbfs_driver.initialize_connection(
self._FAKE_VOLUME, None)
self.volume, None)
self.assertEqual(expected, ret_val)
@ -529,9 +536,9 @@ class SmbFsTestCase(test.TestCase):
if extend_failed:
self.assertRaises(exception.ExtendVolumeError,
drv.extend_volume,
self._FAKE_VOLUME, mock.sentinel.new_size)
self.volume, mock.sentinel.new_size)
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,
drv._DISK_FORMAT_VHD_LEGACY):
@ -576,14 +583,14 @@ class SmbFsTestCase(test.TestCase):
if has_snapshots:
self.assertRaises(exception.InvalidVolume,
self._smbfs_driver._check_extend_volume_support,
self._FAKE_VOLUME, 2)
self.volume, 2)
elif not is_eligible:
self.assertRaises(exception.ExtendVolumeError,
self._smbfs_driver._check_extend_volume_support,
self._FAKE_VOLUME, 2)
self.volume, 2)
else:
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._FAKE_SHARE, 1)
@ -596,35 +603,35 @@ class SmbFsTestCase(test.TestCase):
def test_check_extend_volume_uneligible_share(self):
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')
def test_create_volume_base(self, mock_create_volume):
self._smbfs_driver.create_volume(self._FAKE_VOLUME)
mock_create_volume.assert_called_once_with(self._FAKE_VOLUME)
self._smbfs_driver.create_volume(self.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,
'_create_volume_from_snapshot')
def test_create_volume_from_snapshot(self, mock_create_volume):
self._smbfs_driver.create_volume_from_snapshot(self._FAKE_VOLUME,
self._FAKE_SNAPSHOT)
mock_create_volume.assert_called_once_with(self._FAKE_VOLUME,
self._FAKE_SNAPSHOT)
self._smbfs_driver.create_volume_from_snapshot(self.volume,
self.snapshot)
mock_create_volume.assert_called_once_with(self.volume,
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')
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_create_volume.assert_called_once_with(self._FAKE_VOLUME,
mock_create_volume.assert_called_once_with(self.volume,
mock.sentinel.src_vol)
def test_create_volume_from_in_use_snapshot(self):
fake_snapshot = {'status': 'in-use'}
def test_create_volume_from_unavailable_snapshot(self):
self.snapshot.status = 'error'
self.assertRaises(
exception.InvalidSnapshot,
self._smbfs_driver.create_volume_from_snapshot,
self._FAKE_VOLUME, fake_snapshot)
self.volume, self.snapshot)
def test_copy_volume_from_snapshot(self):
drv = self._smbfs_driver
@ -651,10 +658,10 @@ class SmbFsTestCase(test.TestCase):
with mock.patch.object(image_utils, 'convert_image') as (
fake_convert_image):
drv._copy_volume_from_snapshot(
self._FAKE_SNAPSHOT, self._FAKE_VOLUME,
self._FAKE_VOLUME['size'])
self.snapshot, self.volume,
self.volume.size)
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(
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):
drv = self._smbfs_driver
vol_size_bytes = self._FAKE_VOLUME['size'] << 30
vol_size_bytes = self.volume.size << 30
fake_img_info = mock.MagicMock()
@ -696,12 +703,12 @@ class SmbFsTestCase(test.TestCase):
self.assertRaises(
exception.ImageUnacceptable,
drv.copy_image_to_volume,
mock.sentinel.context, self._FAKE_VOLUME,
mock.sentinel.context, self.volume,
mock.sentinel.image_service,
mock.sentinel.image_id)
else:
drv.copy_image_to_volume(
mock.sentinel.context, self._FAKE_VOLUME,
mock.sentinel.context, self.volume,
mock.sentinel.image_service,
mock.sentinel.image_id)
fake_fetch.assert_called_once_with(
@ -711,8 +718,8 @@ class SmbFsTestCase(test.TestCase):
mock.sentinel.block_size)
drv._do_extend_volume.assert_called_once_with(
self._FAKE_VOLUME_PATH,
self._FAKE_VOLUME['size'],
self._FAKE_VOLUME['name'])
self.volume.size,
self.volume.name)
def test_copy_image_to_volume(self):
self._test_copy_image_to_volume()
@ -740,43 +747,34 @@ class SmbFsTestCase(test.TestCase):
self._FAKE_TOTAL_ALLOCATED)
self.assertEqual(expected, ret_val)
@ddt.data([True, False, False],
[False, False, False],
[True, True, True],
[False, True, True],
[False, False, True],
[True, False, True])
@ddt.data([False, False],
[True, True],
[False, True])
@ddt.unpack
def test_get_volume_format_spec(self, volume_versioned_object,
def test_get_volume_format_spec(self,
volume_meta_contains_fmt,
volume_type_contains_fmt):
self._smbfs_driver.configuration = copy.copy(self._FAKE_SMBFS_CONFIG)
fake_vol_meta_fmt = 'vhd'
fake_vol_type_fmt = 'vhdx'
volume_metadata = {}
volume_type_extra_specs = {}
fake_vol_dict = fake_volume.fake_db_volume()
del fake_vol_dict['name']
if volume_meta_contains_fmt:
volume_metadata['volume_format'] = fake_vol_meta_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 = db.volume_type_create(
ctxt, {'extra_specs': volume_type_extra_specs,
'name': 'fake_vol_type'})
fake_vol_dict.update(metadata=volume_metadata,
volume_type_id=volume_type.id)
# We want to get a 'real' SqlA model object, not just a dict.
volume = db.volume_create(ctxt, fake_vol_dict)
volume = db.volume_get(ctxt, volume.id)
if volume_versioned_object:
volume = objects.Volume._from_db_object(ctxt, objects.Volume(),
volume)
volume_type = fake_volume.fake_volume_type_obj(self.context)
volume = fake_volume.fake_volume_obj(self.context)
# Optional arguments are not set in _from_db_object,
# so have to set explicitly here
volume.volume_type = volume_type
volume.metadata = volume_metadata
# Same for extra_specs and VolumeType
volume_type.extra_specs = volume_type_extra_specs
resulted_fmt = self._smbfs_driver._get_volume_format_spec(volume)
@ -785,6 +783,6 @@ class SmbFsTestCase(test.TestCase):
elif volume_type_contains_fmt:
expected_fmt = fake_vol_type_fmt
else:
expected_fmt = None
expected_fmt = self._FAKE_SMBFS_CONFIG.smbfs_default_volume_format
self.assertEqual(expected_fmt, resulted_fmt)

View File

@ -21,9 +21,12 @@ import mock
from os_brick.remotefs import remotefs
from oslo_utils import units
from cinder import context
from cinder import exception
from cinder.image import image_utils
from cinder import test
from cinder.tests.unit import fake_snapshot
from cinder.tests.unit import fake_volume
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_VOLUME_NAME = 'volume-4f711859-4928-4cb7-801a-a50c37ceaccc'
_FAKE_VOLUME_PATH = os.path.join(_FAKE_MNT_POINT, _FAKE_VOLUME_NAME)
_FAKE_VOLUME = {'id': '4f711859-4928-4cb7-801a-a50c37ceaccc',
'size': 1,
'provider_location': _FAKE_SHARE,
'name': _FAKE_VOLUME_NAME,
'status': 'available'}
_FAKE_SNAPSHOT_ID = '5g811859-4928-4cb7-801a-a50c37ceacba'
_FAKE_SNAPSHOT_ID = '50811859-4928-4cb7-801a-a50c37ceacba'
_FAKE_SNAPSHOT_PATH = (
_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.vzstorage_shares_config = '/fake/config/path'
_FAKE_VZ_CONFIG.vzstorage_sparsed_volumes = False
_FAKE_VZ_CONFIG.vzstorage_used_ratio = 0.7
_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_permissions = 'auto'
@ -72,6 +67,26 @@ class VZStorageTestCase(test.TestCase):
self._vz_driver._execute = mock.Mock()
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):
if path.startswith(self._FAKE_VZ_CONFIG.vzstorage_shares_config):
return True
@ -135,9 +150,13 @@ class VZStorageTestCase(test.TestCase):
file_format = 'raw'
info = mock.Mock()
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):
ret = drv.initialize_connection(self._FAKE_VOLUME, None)
name = drv.get_active_image_from_info(self._FAKE_VOLUME)
with mock.patch.object(drv, '_read_file',
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',
'data': {'export': self._FAKE_SHARE,
'format': file_format,
@ -197,9 +216,13 @@ class VZStorageTestCase(test.TestCase):
drv._check_extend_volume_support = 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',
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)
@ -218,13 +241,13 @@ class VZStorageTestCase(test.TestCase):
if has_snapshots:
self.assertRaises(exception.InvalidVolume,
drv._check_extend_volume_support,
self._FAKE_VOLUME, 2)
self.vol, 2)
elif not is_eligible:
self.assertRaises(exception.ExtendVolumeError,
drv._check_extend_volume_support,
self._FAKE_VOLUME, 2)
self.vol, 2)
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)
def test_check_extend_support(self):
@ -258,10 +281,10 @@ class VZStorageTestCase(test.TestCase):
drv._extend_volume = mock.Mock()
drv._copy_volume_from_snapshot(
self._FAKE_SNAPSHOT, self._FAKE_VOLUME,
self._FAKE_VOLUME['size'])
self.snap, self.vol,
self.vol['size'])
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(
self._FAKE_VOLUME_PATH, self._FAKE_VOLUME_PATH[:-1], 'raw')
@ -281,7 +304,7 @@ class VZStorageTestCase(test.TestCase):
return_value=fake_vol_info)
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)
drv._delete.assert_any_call(

View File

@ -17,9 +17,12 @@ import os
import mock
from oslo_utils import units
from cinder import context
from cinder import exception
from cinder.image import image_utils
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
@ -35,12 +38,6 @@ class WindowsSmbFsTestCase(test.TestCase):
_FAKE_TOTAL_SIZE = '2048'
_FAKE_TOTAL_AVAILABLE = '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_VOLUME_PATH = os.path.join(_FAKE_MNT_POINT,
_FAKE_VOLUME_NAME + '.vhdx')
@ -56,6 +53,25 @@ class WindowsSmbFsTestCase(test.TestCase):
self._smbfs_driver.local_path = mock.Mock(
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'):
self._smbfs_driver.create_dynamic_vhd = mock.MagicMock()
fake_create = self._smbfs_driver._vhdutils.create_dynamic_vhd
@ -63,15 +79,16 @@ class WindowsSmbFsTestCase(test.TestCase):
return_value=volume_format)
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'):
self.assertRaises(exception.InvalidVolume,
self._smbfs_driver._do_create_volume,
self._FAKE_VOLUME)
volume)
else:
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_vol_path, self._FAKE_VOLUME['size'] << 30)
fake_vol_path, volume.size << 30)
def test_create_volume(self):
self._test_create_volume()
@ -120,7 +137,7 @@ class WindowsSmbFsTestCase(test.TestCase):
self._smbfs_driver._vhdutils.create_differencing_vhd)
self._smbfs_driver._do_create_snapshot(
self._FAKE_SNAPSHOT,
self._simple_snapshot(),
os.path.basename(self._FAKE_VOLUME_PATH),
self._FAKE_SNAPSHOT_PATH)
@ -156,8 +173,9 @@ class WindowsSmbFsTestCase(test.TestCase):
with mock.patch.object(image_utils, 'upload_volume') as (
fake_upload_volume):
volume = self._simple_volume()
drv.copy_volume_to_image(
mock.sentinel.context, self._FAKE_VOLUME,
mock.sentinel.context, volume,
mock.sentinel.image_service, fake_image_meta)
expected_conversion = (
@ -165,7 +183,7 @@ class WindowsSmbFsTestCase(test.TestCase):
if expected_conversion:
fake_temp_image_name = '%s.temp_image.%s.%s' % (
self._FAKE_VOLUME['id'],
volume.id,
fake_image_meta['id'],
drv._DISK_FORMAT_VHD)
fake_temp_image_path = os.path.join(
@ -209,8 +227,9 @@ class WindowsSmbFsTestCase(test.TestCase):
with mock.patch.object(image_utils,
'fetch_to_volume_format') as fake_fetch:
volume = self._simple_volume()
drv.copy_image_to_volume(
mock.sentinel.context, self._FAKE_VOLUME,
mock.sentinel.context, volume,
mock.sentinel.image_service,
mock.sentinel.image_id)
fake_fetch.assert_called_once_with(
@ -221,13 +240,14 @@ class WindowsSmbFsTestCase(test.TestCase):
mock.sentinel.block_size)
drv._vhdutils.resize_vhd.assert_called_once_with(
self._FAKE_VOLUME_PATH,
self._FAKE_VOLUME['size'] * units.Gi,
volume.size * units.Gi,
is_file_max_size=False)
def test_copy_volume_from_snapshot(self):
drv = self._smbfs_driver
snapshot = self._simple_snapshot()
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.backing_file = self._FAKE_VOLUME_NAME + '.vhdx'
@ -242,9 +262,9 @@ class WindowsSmbFsTestCase(test.TestCase):
drv.local_path = mock.Mock(
return_value=mock.sentinel.new_volume_path)
drv._copy_volume_from_snapshot(
self._FAKE_SNAPSHOT, self._FAKE_VOLUME,
self._FAKE_VOLUME['size'])
volume = self._simple_volume()
drv._copy_volume_from_snapshot(snapshot,
volume, volume.size)
drv._delete.assert_called_once_with(mock.sentinel.new_volume_path)
drv._vhdutils.convert_vhd.assert_called_once_with(
@ -252,7 +272,7 @@ class WindowsSmbFsTestCase(test.TestCase):
mock.sentinel.new_volume_path)
drv._vhdutils.resize_vhd.assert_called_once_with(
mock.sentinel.new_volume_path,
self._FAKE_VOLUME['size'] * units.Gi,
volume.size * units.Gi,
is_file_max_size=False)
def test_rebase_img(self):

View File

@ -146,7 +146,7 @@ class GlusterfsDriver(remotefs_drv.RemoteFSSnapDriver,
pass
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,
hashed)
return path
@ -185,13 +185,13 @@ class GlusterfsDriver(remotefs_drv.RemoteFSSnapDriver,
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)
return {'provider_location': volume['provider_location']}
return {'provider_location': volume.provider_location}
def _copy_volume_from_snapshot(self, snapshot, volume, volume_size):
"""Copy data from snapshot to destination volume.
@ -202,20 +202,20 @@ class GlusterfsDriver(remotefs_drv.RemoteFSSnapDriver,
LOG.debug("snapshot: %(snap)s, volume: %(vol)s, "
"volume_size: %(size)s",
{'snap': snapshot['id'],
'vol': volume['id'],
{'snap': snapshot.id,
'vol': volume.id,
'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)
vol_path = self._local_volume_dir(snapshot['volume'])
forward_file = snap_info[snapshot['id']]
vol_path = self._local_volume_dir(snapshot.volume)
forward_file = snap_info[snapshot.id]
forward_path = os.path.join(vol_path, forward_file)
# Find the file which backs this file, which represents the point
# when this snapshot was created.
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_new_vol = self._local_path_volume(volume)
@ -237,13 +237,13 @@ class GlusterfsDriver(remotefs_drv.RemoteFSSnapDriver,
def delete_volume(self, 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 specified, '
'skipping'), volume['name'])
'skipping'), volume.name)
return
self._ensure_share_mounted(volume['provider_location'])
self._ensure_share_mounted(volume.provider_location)
mounted_path = self._active_volume_path(volume)
@ -264,7 +264,7 @@ class GlusterfsDriver(remotefs_drv.RemoteFSSnapDriver,
def ensure_export(self, ctx, 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):
"""Exports the volume."""
@ -285,16 +285,16 @@ class GlusterfsDriver(remotefs_drv.RemoteFSSnapDriver,
# Find active qcow2 file
active_file = self.get_active_image_from_info(volume)
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)
data = {'export': volume['provider_location'],
data = {'export': volume.provider_location,
'name': active_file}
if volume['provider_location'] in self.shares:
data['options'] = self.shares[volume['provider_location']]
if volume.provider_location in self.shares:
data['options'] = self.shares[volume.provider_location]
# 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
if data['format'] not in ['raw', 'qcow2']:
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):
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
if backing_fmt not in ['raw', 'qcow2']:
@ -331,7 +331,7 @@ class GlusterfsDriver(remotefs_drv.RemoteFSSnapDriver,
"""
volume_path = self.local_path(volume)
volume_size = volume['size']
volume_size = volume.size
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)
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:
LOG.error(_LE('No snapshots found in database, but %(path)s has '

View File

@ -300,13 +300,13 @@ class NfsDriver(driver.ExtendVD, remotefs.RemoteFSDriver):
def extend_volume(self, volume, new_size):
"""Extend an existing volume to the new size."""
LOG.info(_LI('Extending volume %s.'), volume['id'])
extend_by = int(new_size) - volume['size']
if not self._is_share_eligible(volume['provider_location'],
LOG.info(_LI('Extending volume %s.'), volume.id)
extend_by = int(new_size) - volume.size
if not self._is_share_eligible(volume.provider_location,
extend_by):
raise exception.ExtendVolumeError(reason='Insufficient space to'
' extend volume %s to %sG'
% (volume['id'], new_size))
% (volume.id, new_size))
path = self.local_path(volume)
LOG.info(_LI('Resizing file to %sG...'), new_size)
image_utils.resize_image(path, new_size,
@ -396,8 +396,8 @@ class NfsDriver(driver.ExtendVD, remotefs.RemoteFSDriver):
# NFS snapshots are introduced.
name_id = None
if original_volume_status == 'available':
current_name = CONF.volume_name_template % new_volume['id']
original_volume_name = CONF.volume_name_template % volume['id']
current_name = CONF.volume_name_template % new_volume.id
original_volume_name = CONF.volume_name_template % volume.id
current_path = self.local_path(new_volume)
# Replace the volume name with the original volume name
original_path = current_path.replace(current_name,
@ -406,16 +406,16 @@ class NfsDriver(driver.ExtendVD, remotefs.RemoteFSDriver):
os.rename(current_path, original_path)
except OSError:
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
# volume id and provider_location should be set to the
# 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:
# 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,
'provider_location': new_volume['provider_location']}
'provider_location': new_volume.provider_location}
def _update_volume_stats(self):
"""Retrieve stats info from volume group."""

View File

@ -185,20 +185,20 @@ class QuobyteDriver(remotefs_drv.RemoteFSSnapDriver):
"""
LOG.debug("snapshot: %(snap)s, volume: %(vol)s, ",
{'snap': snapshot['id'],
'vol': volume['id'],
{'snap': snapshot.id,
'vol': volume.id,
'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)
vol_path = self._local_volume_dir(snapshot['volume'])
forward_file = snap_info[snapshot['id']]
vol_path = self._local_volume_dir(snapshot.volume)
forward_file = snap_info[snapshot.id]
forward_path = os.path.join(vol_path, forward_file)
# Find the file which backs this file, which represents the point
# when this snapshot was created.
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_new_vol = self._local_path_volume(volume)
@ -221,12 +221,12 @@ class QuobyteDriver(remotefs_drv.RemoteFSSnapDriver):
def delete_volume(self, 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 '
'specified, skipping'), volume['name'])
'specified, skipping'), volume.name)
return
self._ensure_share_mounted(volume['provider_location'])
self._ensure_share_mounted(volume.provider_location)
volume_dir = self._local_volume_dir(volume)
mounted_path = os.path.join(volume_dir,
@ -261,16 +261,16 @@ class QuobyteDriver(remotefs_drv.RemoteFSSnapDriver):
# Find active qcow2 file
active_file = self.get_active_image_from_info(volume)
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)
data = {'export': volume['provider_location'],
data = {'export': volume.provider_location,
'name': active_file}
if volume['provider_location'] in self.shares:
data['options'] = self.shares[volume['provider_location']]
if volume.provider_location in self.shares:
data['options'] = self.shares[volume.provider_location]
# 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
if data['format'] not in ['raw', 'qcow2']:
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.')
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
if backing_fmt not in ['raw', 'qcow2']:
@ -315,7 +315,7 @@ class QuobyteDriver(remotefs_drv.RemoteFSSnapDriver):
:param volume: volume reference
"""
volume_path = self.local_path(volume)
volume_size = volume['size']
volume_size = volume.size
if self.configuration.quobyte_qcow2_volumes:
self._create_qcow2_file(volume_path, volume_size)

View File

@ -14,6 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import collections
import hashlib
import inspect
import json
@ -118,9 +119,9 @@ def locked_volume_id_operation(f, external=False):
call_args = inspect.getcallargs(f, inst, *args, **kwargs)
if call_args.get('volume'):
volume_id = call_args['volume']['id']
volume_id = call_args['volume'].id
elif call_args.get('snapshot'):
volume_id = call_args['snapshot']['volume']['id']
volume_id = call_args['snapshot'].volume.id
else:
err_msg = _('The decorated method must accept either a volume or '
'a snapshot object')
@ -163,10 +164,10 @@ class RemoteFSDriver(driver.LocalVD, driver.TransferVD, driver.BaseVD):
:param volume: volume reference
:param connector: connector reference
"""
data = {'export': volume['provider_location'],
'name': volume['name']}
if volume['provider_location'] in self.shares:
data['options'] = self.shares[volume['provider_location']]
data = {'export': volume.provider_location,
'name': volume.name}
if volume.provider_location in self.shares:
data['options'] = self.shares[volume.provider_location]
return {
'driver_volume_type': self.driver_volume_type,
'data': data,
@ -232,13 +233,13 @@ class RemoteFSDriver(driver.LocalVD, driver.TransferVD, driver.BaseVD):
"""
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)
return {'provider_location': volume['provider_location']}
return {'provider_location': volume.provider_location}
def _do_create_volume(self, volume):
"""Create a volume on given remote share.
@ -246,7 +247,7 @@ class RemoteFSDriver(driver.LocalVD, driver.TransferVD, driver.BaseVD):
:param volume: volume reference
"""
volume_path = self.local_path(volume)
volume_size = volume['size']
volume_size = volume.size
if getattr(self.configuration,
self.driver_prefix + '_sparsed_volumes'):
@ -280,13 +281,13 @@ class RemoteFSDriver(driver.LocalVD, driver.TransferVD, driver.BaseVD):
:param volume: volume reference
"""
if not volume['provider_location']:
if not volume.provider_location:
LOG.warning(_LW('Volume %s does not have '
'provider_location specified, '
'skipping'), volume['name'])
'skipping'), volume.name)
return
self._ensure_share_mounted(volume['provider_location'])
self._ensure_share_mounted(volume.provider_location)
mounted_path = self.local_path(volume)
@ -294,7 +295,7 @@ class RemoteFSDriver(driver.LocalVD, driver.TransferVD, driver.BaseVD):
def ensure_export(self, ctx, 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):
"""Exports the volume.
@ -387,9 +388,9 @@ class RemoteFSDriver(driver.LocalVD, driver.TransferVD, driver.BaseVD):
: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),
volume['name'])
volume.name)
def copy_image_to_volume(self, context, volume, image_service, image_id):
"""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,
self.local_path(volume),
self.configuration.volume_dd_blocksize,
size=volume['size'],
size=volume.size,
run_as_root=run_as_root)
# 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
# this sets the size to the one asked in the first place by the user
# 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)
data = image_utils.qemu_img_info(self.local_path(volume),
run_as_root=run_as_root)
virt_size = data.virtual_size / units.Gi
if virt_size != volume['size']:
if virt_size != volume.size:
raise exception.ImageUnacceptable(
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))
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()
def _local_volume_dir(self, volume):
share = volume['provider_location']
share = volume.provider_location
local_dir = self._get_mount_point_for_share(share)
return local_dir
def _local_path_volume(self, volume):
path_to_disk = os.path.join(
self._local_volume_dir(volume),
volume['name'])
volume.name)
return path_to_disk
def _get_new_snap_path(self, snapshot):
vol_path = self.local_path(snapshot['volume'])
snap_path = '%s.%s' % (vol_path, snapshot['id'])
vol_path = self.local_path(snapshot.volume)
snap_path = '%s.%s' % (vol_path, snapshot.id)
return snap_path
def _local_path_volume_info(self, volume):
@ -757,7 +758,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
output = []
info = self._qemu_img_info(path, volume['name'])
info = self._qemu_img_info(path, volume.name)
new_info = {}
new_info['filename'] = os.path.basename(path)
new_info['backing-filename'] = info.backing_file
@ -767,7 +768,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
while new_info['backing-filename']:
filename = new_info['backing-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
new_info = {}
new_info['filename'] = filename
@ -846,13 +847,13 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
active_file = self.get_active_image_from_info(volume)
active_file_path = os.path.join(self._local_volume_dir(volume),
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
root_file_fmt = info.file_format
tmp_params = {
'prefix': '%s.temp_image.%s' % (volume['id'], image_meta['id']),
'prefix': '%s.temp_image.%s' % (volume.id, image_meta['id']),
'suffix': '.img'
}
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):
LOG.info(_LI('Cloning volume %(src)s to volume %(dst)s'),
{'src': src_vref['id'],
'dst': volume['id']})
{'src': src_vref.id,
'dst': volume.id})
if src_vref['status'] != 'available':
if src_vref.status != 'available':
msg = _("Volume status must be 'available'.")
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)
try:
self._copy_volume_from_snapshot(temp_snapshot,
volume_info,
volume['size'])
volume.size)
finally:
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):
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)
snapshot_file = snap_info[snapshot['id']]
active_file = self.get_active_image_from_info(snapshot['volume'])
snapshot_file = snap_info[snapshot.id]
active_file = self.get_active_image_from_info(snapshot.volume)
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):
return
LOG.info(_LI('Deleting stale snapshot: %s'), snapshot['id'])
LOG.info(_LI('Deleting stale snapshot: %s'), snapshot.id)
self._delete(snapshot_path)
del(snap_info[snapshot['id']])
del(snap_info[snapshot.id])
self._write_info_file(info_path, snap_info)
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']:
msg = _('Volume status must be "available" or "in-use".')
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)
# Determine the true snapshot file for this snapshot
# 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)
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
# exist, do not attempt to delete.
# (This happens, for example, if snapshot_create failed due to lack
# of permission to write to the share.)
LOG.info(_LI('Snapshot record for %s is not present, allowing '
'snapshot_delete to proceed.'), snapshot['id'])
'snapshot_delete to proceed.'), snapshot.id)
return
snapshot_file = snap_info[snapshot['id']]
snapshot_file = snap_info[snapshot.id]
LOG.debug('snapshot_file for this snap is: %s', snapshot_file)
snapshot_path = os.path.join(
self._local_volume_dir(snapshot['volume']),
self._local_volume_dir(snapshot.volume),
snapshot_file)
snapshot_path_img_info = self._qemu_img_info(
snapshot_path,
snapshot['volume']['name'])
snapshot.volume.name)
base_file = snapshot_path_img_info.backing_file
if base_file is None:
@ -996,15 +1009,15 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
base_path = os.path.join(vol_path, base_file)
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
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)
if volume_status == 'in-use':
# Online delete
context = snapshot['context']
context = snapshot._context
new_base_file = base_file_img_info.backing_file
@ -1048,7 +1061,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
# used here) | | ptr update) |
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
# the active file.
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)
# Remove snapshot_file from info
del(snap_info[snapshot['id']])
del(snap_info[snapshot.id])
self._write_info_file(info_path, snap_info)
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)
"""
if snapshot['status'] != 'available':
if snapshot.status != 'available':
msg = _('Snapshot status must be "available" to clone.')
raise exception.InvalidSnapshot(msg)
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._copy_volume_from_snapshot(snapshot,
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):
raise NotImplementedError()
@ -1116,7 +1129,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
"""
backing_path_full_path = os.path.join(
self._local_volume_dir(snapshot['volume']),
self._local_volume_dir(snapshot.volume),
backing_filename)
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)
info = self._qemu_img_info(backing_path_full_path,
snapshot['volume']['name'])
snapshot.volume.name)
backing_fmt = info.file_format
command = ['qemu-img', 'rebase', '-u',
@ -1239,16 +1252,16 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
info file: { 'active': 'volume-1234' } (* changed!)
"""
status = snapshot['volume']['status']
status = snapshot.volume.status
if status not in ['available', 'in-use']:
msg = _('Volume status must be "available" or "in-use"'
' for snapshot. (is %s)') % status
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)
backing_filename = self.get_active_image_from_info(
snapshot['volume'])
snapshot.volume)
new_snap_path = self._get_new_snap_path(snapshot)
if status == 'in-use':
@ -1261,13 +1274,13 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
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)
def _create_snapshot_online(self, snapshot, backing_filename,
new_snap_path):
# Perform online snapshot via Nova
context = snapshot['context']
context = snapshot._context
self._do_create_snapshot(snapshot,
backing_filename,
@ -1276,13 +1289,13 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
connection_info = {
'type': 'qcow2',
'new_file': os.path.basename(new_snap_path),
'snapshot_id': snapshot['id']
'snapshot_id': snapshot.id
}
try:
result = self._nova.create_volume_snapshot(
context,
snapshot['volume_id'],
snapshot.volume_id,
connection_info)
LOG.debug('nova call result: %s', result)
except Exception:
@ -1296,7 +1309,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
increment = 1
timeout = 600
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',
{'id': snapshot['id'],
@ -1320,7 +1333,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
msg = _('Snapshot %(id)s has been asked to be deleted while '
'waiting for it to become available. Perhaps a '
'concurrent request was made.') % {'id':
snapshot['id']}
snapshot.id}
raise exception.RemoteFSConcurrentRequest(msg)
if 10 < seconds_elapsed <= 20:
@ -1332,13 +1345,13 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
if seconds_elapsed > timeout:
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)
def _delete_snapshot_online(self, context, snapshot, info):
# Update info over the course of this method
# 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)
if info['active_file'] == info['snapshot_file']:
@ -1357,9 +1370,9 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
delete_info = {'file_to_merge': new_base,
'merge_target_file': None, # current
'type': 'qcow2',
'volume_id': snapshot['volume']['id']}
'volume_id': snapshot.volume.id}
del(snap_info[snapshot['id']])
del(snap_info[snapshot.id])
else:
# blockCommit snapshot into base
# info['base'] <= snapshot_file
@ -1369,14 +1382,14 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
delete_info = {'file_to_merge': info['snapshot_file'],
'merge_target_file': info['base_file'],
'type': 'qcow2',
'volume_id': snapshot['volume']['id']}
'volume_id': snapshot.volume.id}
del(snap_info[snapshot['id']])
del(snap_info[snapshot.id])
try:
self._nova.delete_volume_snapshot(
context,
snapshot['id'],
snapshot.id,
delete_info)
except Exception:
LOG.exception(_LE('Call to Nova delete snapshot failed'))
@ -1389,7 +1402,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
increment = 1
timeout = 7200
while True:
s = db.snapshot_get(context, snapshot['id'])
s = db.snapshot_get(context, snapshot.id)
if s['status'] == fields.SnapshotStatus.DELETING:
if s['progress'] == '90%':
@ -1397,12 +1410,12 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
break
else:
LOG.debug('status of snapshot %s is still "deleting"... '
'waiting', snapshot['id'])
'waiting', snapshot.id)
time.sleep(increment)
seconds_elapsed += increment
else:
msg = _('Unable to delete snapshot %(id)s, '
'status: %(status)s.') % {'id': snapshot['id'],
'status: %(status)s.') % {'id': snapshot.id,
'status': s['status']}
raise exception.RemoteFSException(msg)
@ -1416,7 +1429,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
if seconds_elapsed > timeout:
msg = _('Timed out while waiting for Nova update '
'for deletion of snapshot %(id)s.') %\
{'id': snapshot['id']}
{'id': snapshot.id}
raise exception.RemoteFSException(msg)
# Write info file updated above
@ -1424,7 +1437,7 @@ class RemoteFSSnapDriver(RemoteFSDriver, driver.SnapshotVD):
# Delete stale file
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)
@locked_volume_id_operation

View File

@ -186,14 +186,14 @@ class ScalityDriver(remotefs_drv.RemoteFSSnapDriver):
active_file = self.get_active_image_from_info(volume)
path = '%s/%s' % (self._get_mount_point_for_share(), active_file)
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,
'sofs_path': sofs_rel_path}
# 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
if data['format'] not in ['raw', 'qcow2']:
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):
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
if backing_fmt not in ['raw', 'qcow2']:
@ -230,7 +230,7 @@ class ScalityDriver(remotefs_drv.RemoteFSSnapDriver):
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
try:
@ -241,15 +241,15 @@ class ScalityDriver(remotefs_drv.RemoteFSSnapDriver):
else:
path_to_snap_img = self.local_path(snapshot)
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)
# Find the file which backs this file, which represents the point
# when this snapshot was created.
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)
@ -270,7 +270,7 @@ class ScalityDriver(remotefs_drv.RemoteFSSnapDriver):
"""Create a new backup from an existing volume."""
volume = self.db.volume_get(context, backup['volume_id'])
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)
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):
"""Restore an existing backup to a new or existing volume."""
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)
with utils.temporary_chown(volume_local_path):
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)

View File

@ -90,7 +90,7 @@ def update_allocation_data(delete=False):
if delete:
allocated_size_gb = None
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)
return ret_val
@ -149,11 +149,11 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
active_file = self.get_active_image_from_info(volume)
fmt = self.get_volume_format(volume)
data = {'export': volume['provider_location'],
data = {'export': volume.provider_location,
'format': fmt,
'name': active_file}
if volume['provider_location'] in self.shares:
data['options'] = self.shares[volume['provider_location']]
if volume.provider_location in self.shares:
data['options'] = self.shares[volume.provider_location]
return {
'driver_volume_type': self.driver_volume_type,
'data': data,
@ -206,8 +206,8 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
self._allocation_data = json.load(f)
def update_disk_allocation_data(self, volume, virtual_size_gb=None):
volume_name = volume['name']
smbfs_share = volume['provider_location']
volume_name = volume.name
smbfs_share = volume.provider_location
if smbfs_share:
share_hash = self._get_hash_str(smbfs_share)
else:
@ -257,7 +257,7 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
def _get_local_volume_path_template(self, 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
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')
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 += '.' + snapshot['id'] + ext
snap_path += '.' + snapshot.id + ext
return snap_path
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:
volume_format = ext
else:
info = self._qemu_img_info(volume_path, volume['name'])
info = self._qemu_img_info(volume_path, volume.name)
volume_format = info.file_format
else:
volume_format = (
@ -303,12 +303,12 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
@update_allocation_data(delete=True)
def delete_volume(self, 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 '
'specified, skipping.'), volume['name'])
'specified, skipping.'), volume.name)
return
self._ensure_share_mounted(volume['provider_location'])
self._ensure_share_mounted(volume.provider_location)
volume_dir = self._local_volume_dir(volume)
mounted_path = os.path.join(volume_dir,
self.get_active_image_from_info(volume))
@ -343,7 +343,7 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
"""
volume_format = self.get_volume_format(volume)
volume_path = self.local_path(volume)
volume_size = volume['size']
volume_size = volume.size
LOG.debug("Creating new volume at %s.", volume_path)
@ -470,7 +470,7 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
snapshot, backing_filename, new_snap_path)
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
if volume_format in (self._DISK_FORMAT_VHD, self._DISK_FORMAT_VHDX):
err_msg = _("Snapshots are not supported for this volume "
@ -480,7 +480,7 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
@remotefs_drv.locked_volume_id_operation
@update_allocation_data()
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)
def _extend_volume(self, volume, size_gb):
@ -489,7 +489,7 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
self._check_extend_volume_support(volume, 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):
info = self._qemu_img_info(volume_path, volume_name)
@ -523,12 +523,12 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
'driver when no snapshots exist.')
raise exception.InvalidVolume(msg)
extend_by = int(size_gb) - volume['size']
if not self._is_share_eligible(volume['provider_location'],
extend_by = int(size_gb) - volume.size
if not self._is_share_eligible(volume.provider_location,
extend_by):
raise exception.ExtendVolumeError(reason='Insufficient space to '
'extend volume %s to %sG.'
% (volume['id'], size_gb))
% (volume.id, size_gb))
@remotefs_drv.locked_volume_id_operation
@update_allocation_data()
@ -544,22 +544,22 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
LOG.debug("Snapshot: %(snap)s, volume: %(vol)s, "
"volume_size: %(size)s",
{'snap': snapshot['id'],
'vol': volume['id'],
{'snap': snapshot.id,
'vol': volume.id,
'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)
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)
forward_file = snap_info[snapshot['id']]
forward_file = snap_info[snapshot.id]
forward_path = os.path.join(vol_dir, forward_file)
# Find the file which backs this file, which represents the point
# when this snapshot was created.
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)
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._do_extend_volume(self.local_path(volume),
volume['size'],
volume['name'])
volume.size,
volume.name)
data = image_utils.qemu_img_info(self.local_path(volume))
virt_size = data.virtual_size / units.Gi
if virt_size != volume['size']:
if virt_size != volume.size:
raise exception.ImageUnacceptable(
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))
@remotefs_drv.locked_volume_id_operation
@ -639,38 +639,15 @@ class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
return flags.strip(',')
def _get_volume_format_spec(self, volume):
# This method needs to be able to parse metadata/volume type
# specs for volume SQLAlchemy objects and versioned objects,
# as the transition to versioned objects is not complete and the
# driver may receive either of them.
#
# TODO(lpetrut): once the transition to oslo.versionedobjects is
# complete, we can skip some of those checks.
volume_metadata_specs = {}
volume_type_specs = {}
vol_type = volume.volume_type
extra_specs = {}
if vol_type and vol_type.extra_specs:
extra_specs = vol_type.extra_specs
if volume.get('metadata') and isinstance(volume.metadata, dict):
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})
extra_specs.update(volume.metadata or {})
vol_type = volume.get('volume_type')
if vol_type:
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
return (extra_specs.get('volume_format') or
self.configuration.smbfs_default_volume_format)
def _is_file_size_equal(self, path, size):
"""Checks if file size at path is equal to size."""

View File

@ -110,10 +110,10 @@ class VZStorageDriver(remotefs_drv.RemoteFSSnapDriver):
active_file = self.get_active_image_from_info(volume)
active_file_path = os.path.join(self._local_volume_dir(volume),
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
data = {'export': volume['provider_location'],
data = {'export': volume.provider_location,
'format': fmt,
'name': active_file,
}
@ -228,7 +228,7 @@ class VZStorageDriver(remotefs_drv.RemoteFSSnapDriver):
@remotefs_drv.locked_volume_id_operation
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)
def _extend_volume(self, volume, size_gb):
@ -257,12 +257,12 @@ class VZStorageDriver(remotefs_drv.RemoteFSSnapDriver):
'driver when no snapshots exist.')
raise exception.InvalidVolume(msg)
extend_by = int(size_gb) - volume['size']
if not self._is_share_eligible(volume['provider_location'],
extend_by = int(size_gb) - volume.size
if not self._is_share_eligible(volume.provider_location,
extend_by):
raise exception.ExtendVolumeError(reason='Insufficient space to '
'extend volume %s to %sG.'
% (volume['id'], size_gb))
% (volume.id, size_gb))
def _is_file_size_equal(self, path, 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, "
"volume: %(vol)s, volume_size: %(size)s.",
{'snap': snapshot['id'],
'vol': volume['id'],
{'snap': snapshot.id,
'vol': volume.id,
'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)
vol_dir = self._local_volume_dir(snapshot['volume'])
vol_dir = self._local_volume_dir(snapshot.volume)
out_format = "raw"
forward_file = snap_info[snapshot['id']]
forward_file = snap_info[snapshot.id]
forward_path = os.path.join(vol_dir, forward_file)
# Find the file which backs this file, which represents the point
# when this snapshot was created.
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)
LOG.debug("_copy_volume_from_snapshot: will copy "
@ -309,13 +309,13 @@ class VZStorageDriver(remotefs_drv.RemoteFSSnapDriver):
@remotefs_drv.locked_volume_id_operation
def delete_volume(self, volume):
"""Deletes a logical volume."""
if not volume['provider_location']:
if not volume.provider_location:
msg = (_('Volume %s does not have provider_location '
'specified, skipping.') % volume['name'])
'specified, skipping.') % volume.name)
LOG.error(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)
mounted_path = os.path.join(volume_dir,
self.get_active_image_from_info(volume))