from cinder import context
from cinder import db
from cinder import exception
+from cinder.image import image_utils
from cinder.openstack.common import processutils as putils
from cinder import test
from cinder.tests.compute import test_nova
mox.VerifyAll()
- def _simple_volume(self):
+ def _simple_volume(self, id=None):
volume = DumbVolume()
volume['provider_location'] = self.TEST_EXPORT1
+ 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' % self.VOLUME_UUID
+ volume['name'] = 'volume-%s' % volume['id']
volume['size'] = 10
- volume['id'] = self.VOLUME_UUID
volume['status'] = 'available'
return volume
mox.VerifyAll()
+ def test_create_cloned_volume(self):
+ (mox, drv) = self._mox, self._driver
+
+ mox.StubOutWithMock(drv, 'create_snapshot')
+ mox.StubOutWithMock(drv, 'delete_snapshot')
+ mox.StubOutWithMock(drv, '_read_info_file')
+ mox.StubOutWithMock(image_utils, 'convert_image')
+ mox.StubOutWithMock(drv, '_copy_volume_from_snapshot')
+
+ volume_file = 'volume-%s' % self.VOLUME_UUID
+ volume_path = '%s/%s/%s' % (self.TEST_MNT_POINT_BASE,
+ drv._get_hash_str(self.TEST_EXPORT1),
+ volume_file)
+
+ volume = self._simple_volume()
+ src_vref = self._simple_volume()
+ src_vref['id'] = '375e32b2-804a-49f2-b282-85d1d5a5b9e1'
+ src_vref['name'] = 'volume-%s' % src_vref['id']
+ volume_file = 'volume-%s' % src_vref['id']
+ volume_path = '%s/%s/%s' % (self.TEST_MNT_POINT_BASE,
+ drv._get_hash_str(self.TEST_EXPORT1),
+ volume_file)
+ src_info_path = '%s.info' % volume_path
+ volume_ref = {'id': volume['id'],
+ 'name': volume['name'] + '-clone',
+ 'status': volume['status'],
+ 'provider_location': volume['provider_location'],
+ 'size': volume['size']}
+
+ snap_ref = {'volume_name': src_vref['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}
+
+ drv.create_snapshot(snap_ref)
+
+ snap_info = {'active': volume_file,
+ snap_ref['id']: volume_path + '-clone'}
+
+ drv._read_info_file(src_info_path).AndReturn(snap_info)
+
+ drv._copy_volume_from_snapshot(snap_ref, volume_ref, volume['size'])
+
+ drv.delete_snapshot(mox_lib.IgnoreArg())
+
+ mox.ReplayAll()
+
+ drv.create_cloned_volume(volume, src_vref)
+
def test_delete_volume(self):
"""delete_volume simple test case."""
mox = self._mox
snap_file_2 = '%s.%s' % (volume_filename, self.SNAP_UUID_2)
info_path = '%s%s' % (volume_path, '.info')
+ qemu_img_info_output = """image: volume-%s.%s
+ file format: qcow2
+ virtual size: 1.0G (1073741824 bytes)
+ disk size: 173K
+ backing file: %s
+ """ % (self.VOLUME_UUID, self.SNAP_UUID, volume_filename)
+
mox.StubOutWithMock(drv, '_execute')
- mox.StubOutWithMock(os.path, 'exists')
mox.StubOutWithMock(drv, '_read_file')
mox.StubOutWithMock(drv, '_read_info_file')
mox.StubOutWithMock(drv, '_get_backing_chain_for_path')
mox.StubOutWithMock(drv, '_get_matching_backing_file')
mox.StubOutWithMock(drv, '_write_info_file')
+ mox.StubOutWithMock(image_utils, 'qemu_img_info')
- os.path.exists(snap_path_2).AndReturn(True)
-
- info_file_json = """
- {
- %(SNAP_UUID)s: "volume-%(VOLUME_UUID)s.%(SNAP_UUID)s",
- %(SNAP_UUID_2)s": "volume-%(VOLUME_UUID)s.%(SNAP_UUID_2)s",
- "active": "volume-%(VOLUME_UUID)s.%(SNAP_UUID_2)s"
- }
- """ % {'SNAP_UUID': self.SNAP_UUID,
- 'SNAP_UUID_2': self.SNAP_UUID_2,
- 'VOLUME_UUID': self.VOLUME_UUID}
+ img_info = image_utils.QemuImgInfo(qemu_img_info_output)
+ image_utils.qemu_img_info(snap_path_2).AndReturn(img_info)
info_file_dict = {'active': snap_file_2,
self.SNAP_UUID_2: snap_file_2,
'volume': self._simple_volume(),
'id': self.SNAP_UUID_2}
- qemu_img_info_output = """image: volume-%s.%s
- file format: qcow2
- virtual size: 1.0G (1073741824 bytes)
- disk size: 173K
- backing file: %s
- """ % (self.VOLUME_UUID, self.SNAP_UUID, volume_filename)
-
- qemu_img_info_output_2 = """image: volume-%s
- file format: qcow2
- virtual size: 1.0G (1073741824 bytes)
- disk size: 173K
- """ % self.VOLUME_UUID
-
- drv._execute('qemu-img', 'info', snap_path_2,
- run_as_root=True).\
- AndReturn((qemu_img_info_output, ''))
-
snap_path_2_chain = [{self.SNAP_UUID_2: snap_file_2},
{self.SNAP_UUID: snap_file},
{'active': snap_file_2}]
snap_path_2 = '%s.%s' % (volume_path, self.SNAP_UUID_2)
snap_file_2 = 'volume-%s.%s' % (self.VOLUME_UUID, self.SNAP_UUID_2)
- mox.StubOutWithMock(drv, '_execute')
- mox.StubOutWithMock(os.path, 'exists')
- mox.StubOutWithMock(drv, '_read_info_file')
- mox.StubOutWithMock(drv, '_write_info_file')
- mox.StubOutWithMock(drv, '_get_backing_chain_for_path')
- mox.StubOutWithMock(drv, 'get_active_image_from_info')
-
- info_file_dict = {self.SNAP_UUID_2: 'volume-%s.%s' %
- (self.VOLUME_UUID, self.SNAP_UUID_2),
- self.SNAP_UUID: 'volume-%s.%s' %
- (self.VOLUME_UUID, self.SNAP_UUID)}
-
- info_path = drv._local_path_volume(volume) + '.info'
- drv._read_info_file(info_path).AndReturn(info_file_dict)
-
- os.path.exists(snap_path).AndReturn(True)
-
- snap_ref = {'name': 'test snap',
- 'volume_id': self.VOLUME_UUID,
- 'volume': volume,
- 'id': self.SNAP_UUID}
-
qemu_img_info_output_snap_2 = """image: volume-%s.%s
file format: qcow2
virtual size: 1.0G (1073741824 bytes)
disk size: 175K
""" % self.VOLUME_UUID
+ mox.StubOutWithMock(drv, '_execute')
+ mox.StubOutWithMock(drv, '_read_info_file')
+ mox.StubOutWithMock(drv, '_write_info_file')
+ mox.StubOutWithMock(drv, '_get_backing_chain_for_path')
+ mox.StubOutWithMock(drv, 'get_active_image_from_info')
+ mox.StubOutWithMock(image_utils, 'qemu_img_info')
+
+ info_file_dict = {self.SNAP_UUID_2: 'volume-%s.%s' %
+ (self.VOLUME_UUID, self.SNAP_UUID_2),
+ self.SNAP_UUID: 'volume-%s.%s' %
+ (self.VOLUME_UUID, self.SNAP_UUID)}
+
+ info_path = drv._local_path_volume(volume) + '.info'
+ drv._read_info_file(info_path).AndReturn(info_file_dict)
+
+ img_info = image_utils.QemuImgInfo(qemu_img_info_output_snap_1)
+ image_utils.qemu_img_info(snap_path).AndReturn(img_info)
+
+ snap_ref = {'name': 'test snap',
+ 'volume_id': self.VOLUME_UUID,
+ 'volume': volume,
+ 'id': self.SNAP_UUID}
+
snap_path_chain = [{'filename': snap_file_2,
'backing-filename': snap_file},
{'filename': snap_file,
mox.VerifyAll()
- def test_get_backing_file(self, path='', actual_path=''):
- (mox, drv) = self._mox, self._driver
-
- qemu_img_info_output = """image: volume-%s
- file format: qcow2
- virtual size: 1.0G (1073741824 bytes)
- disk size: 152K
- backing file: %svolume-%s.%s%s
- """ % (self.VOLUME_UUID,
- path, self.VOLUME_UUID, self.SNAP_UUID, actual_path)
-
- mox.ReplayAll()
-
- expected_file = 'volume-%s.%s' % (self.VOLUME_UUID, self.SNAP_UUID)
- self.assertEqual(drv._get_backing_file(qemu_img_info_output),
- expected_file)
-
- mox.VerifyAll()
-
- def test_get_backing_file_with_path(self):
- self.test_get_backing_file(path='/mnt/asdf/')
-
- def test_get_backing_file_other_cwd(self):
- ap = ' (actual path: /mnt/asdf/volume-%s.%s)' % \
- (self.VOLUME_UUID, self.SNAP_UUID)
- self.test_get_backing_file(actual_path=ap)
-
- def test_get_backing_file_none(self):
- (mox, drv) = self._mox, self._driver
-
- qemu_img_info_output = """image: volume-%s
- file format: raw
- virtual size: 1.0G (1073741824 bytes)
- disk size: 152K
- """ % self.VOLUME_UUID
-
- mox.ReplayAll()
-
- self.assertIsNone(drv._get_backing_file(qemu_img_info_output))
-
- mox.VerifyAll()
-
- def test_get_file_format(self):
- (mox, drv) = self._mox, self._driver
-
- qemu_img_info_output = """image: volume-%s
- file format: qcow2
- virtual size: 1.0G (1073741824 bytes)
- disk size: 152K
- """ % self.VOLUME_UUID
-
- mox.ReplayAll()
-
- self.assertEqual(drv._get_file_format(qemu_img_info_output), 'qcow2')
-
- mox.VerifyAll()
-
def test_read_info_file(self):
(mox, drv) = self._mox, self._driver
volume = self._simple_volume()
- mox.StubOutWithMock(drv, '_execute')
- mox.StubOutWithMock(drv, 'get_active_image_from_info')
-
- drv.get_active_image_from_info(volume).AndReturn(volume['name'])
+ volume_path = '%s/%s/volume-%s' % (self.TEST_MNT_POINT_BASE,
+ drv._get_hash_str(
+ self.TEST_EXPORT1),
+ self.VOLUME_UUID)
qemu_img_info_output = """image: volume-%s
file format: qcow2
disk size: 473K
""" % self.VOLUME_UUID
- volume_path = '%s/%s/volume-%s' % (self.TEST_MNT_POINT_BASE,
- drv._get_hash_str(
- self.TEST_EXPORT1),
- self.VOLUME_UUID)
- drv._execute('qemu-img', 'info', volume_path).\
- AndReturn((qemu_img_info_output, ''))
+ img_info = image_utils.QemuImgInfo(qemu_img_info_output)
- drv._execute('qemu-img', 'resize', volume_path, '3G', run_as_root=True)
+ mox.StubOutWithMock(drv, '_execute')
+ mox.StubOutWithMock(drv, 'get_active_image_from_info')
+ mox.StubOutWithMock(image_utils, 'qemu_img_info')
+ mox.StubOutWithMock(image_utils, 'resize_image')
+
+ drv.get_active_image_from_info(volume).AndReturn(volume['name'])
+
+ image_utils.qemu_img_info(volume_path).AndReturn(img_info)
+
+ image_utils.resize_image(volume_path, 3)
mox.ReplayAll()
mox.StubOutWithMock(drv, '_read_info_file')
mox.StubOutWithMock(drv, '_write_info_file')
mox.StubOutWithMock(os.path, 'exists')
- mox.StubOutWithMock(drv, '_get_backing_file_for_path')
mox.StubOutWithMock(db, 'snapshot_get')
+ mox.StubOutWithMock(image_utils, 'qemu_img_info')
snap_info = {'active': snap_file,
self.SNAP_UUID: snap_file}
os.path.exists(snap_path).AndReturn(True)
- drv._read_info_file(info_path, empty_if_missing=True).\
- AndReturn(snap_info)
-
- asdfqemu_img_info_output = """image: %s
+ qemu_img_info_output = """image: %s
file format: qcow2
virtual size: 1.0G (1073741824 bytes)
disk size: 173K
backing file: %s
""" % (snap_file, volume_file)
+ img_info = image_utils.QemuImgInfo(qemu_img_info_output)
+ image_utils.qemu_img_info(snap_path).AndReturn(img_info)
+
+ drv._read_info_file(info_path, empty_if_missing=True).\
+ AndReturn(snap_info)
delete_info = {
'type': 'qcow2',
drv._nova.delete_volume_snapshot(ctxt, self.SNAP_UUID, delete_info)
- drv._get_backing_file_for_path(snap_path).AndReturn(volume_file)
-
drv._read_info_file(info_path).AndReturn(snap_info)
drv._read_info_file(info_path).AndReturn(snap_info)
mox.StubOutWithMock(drv, '_read_info_file')
mox.StubOutWithMock(drv, '_write_info_file')
mox.StubOutWithMock(os.path, 'exists')
- mox.StubOutWithMock(drv, '_get_backing_file_for_path')
mox.StubOutWithMock(db, 'snapshot_get')
+ mox.StubOutWithMock(image_utils, 'qemu_img_info')
snap_info = {'active': snap_file_2,
self.SNAP_UUID: snap_file,
os.path.exists(snap_path).AndReturn(True)
+ qemu_img_info_output = """image: %s
+ file format: qcow2
+ virtual size: 1.0G (1073741824 bytes)
+ disk size: 173K
+ backing file: %s
+ """ % (snap_file, volume_file)
+ img_info = image_utils.QemuImgInfo(qemu_img_info_output)
+
+ image_utils.qemu_img_info(snap_path).AndReturn(img_info)
+
drv._read_info_file(info_path, empty_if_missing=True).\
AndReturn(snap_info)
- drv._get_backing_file_for_path(snap_path).AndReturn(volume_file)
-
delete_info = {'type': 'qcow2',
'merge_target_file': volume_file,
'file_to_merge': snap_file,
mox.StubOutWithMock(drv, '_read_info_file')
mox.StubOutWithMock(drv, '_write_info_file')
mox.StubOutWithMock(os.path, 'exists')
- mox.StubOutWithMock(drv, '_get_backing_file_for_path')
mox.StubOutWithMock(db, 'snapshot_get')
+ mox.StubOutWithMock(image_utils, 'qemu_img_info')
snap_info = {'active': snap_file,
self.SNAP_UUID: snap_file}
os.path.exists(snap_path).AndReturn(True)
- drv._read_info_file(info_path, empty_if_missing=True).\
- AndReturn(snap_info)
-
- asdfqemu_img_info_output = """image: %s
+ qemu_img_info_output = """image: %s
file format: qcow2
virtual size: 1.0G (1073741824 bytes)
disk size: 173K
backing file: %s
""" % (snap_file, volume_file)
+ img_info = image_utils.QemuImgInfo(qemu_img_info_output)
+
+ image_utils.qemu_img_info(snap_path).AndReturn(img_info)
+
+ drv._read_info_file(info_path, empty_if_missing=True).\
+ AndReturn(snap_info)
delete_info = {
'type': 'qcow2',
drv._nova.delete_volume_snapshot(ctxt, self.SNAP_UUID, delete_info)
- drv._get_backing_file_for_path(snap_path).AndReturn(volume_file)
-
drv._read_info_file(info_path).AndReturn(snap_info)
drv._read_info_file(info_path).AndReturn(snap_info)
mox.StubOutWithMock(drv, '_execute')
mox.StubOutWithMock(drv, '_local_volume_dir')
+ mox.StubOutWithMock(image_utils, 'qemu_img_info')
- qemu_img_output_base = """image: %s
+ qemu_img_output_base = """image: %(image_name)s
file format: qcow2
virtual size: 1.0G (1073741824 bytes)
disk size: 173K
"""
- qemu_img_output = qemu_img_output_base + 'backing file: %s\n'
+ qemu_img_output = """image: %(image_name)s
+ file format: qcow2
+ virtual size: 1.0G (1073741824 bytes)
+ disk size: 173K
+ backing file: %(backing_file)s
+ """
+
+ qemu_img_output_1 = qemu_img_output_base % {'image_name': vol_filename}
+ qemu_img_output_2 = qemu_img_output % {'image_name': vol_filename_2,
+ 'backing_file': vol_filename}
+ qemu_img_output_3 = qemu_img_output % {'image_name': vol_filename_3,
+ 'backing_file': vol_filename_2}
- qemu_img_output_1 = qemu_img_output % (vol_filename, vol_filename_2)
- qemu_img_output_2 = qemu_img_output % (vol_filename_2, vol_filename_3)
- qemu_img_output_3 = qemu_img_output_base % (vol_filename_3)
+ info_1 = image_utils.QemuImgInfo(qemu_img_output_1)
+ info_2 = image_utils.QemuImgInfo(qemu_img_output_2)
+ info_3 = image_utils.QemuImgInfo(qemu_img_output_3)
drv._local_volume_dir(volume).AndReturn(vol_dir)
- drv._execute('qemu-img', 'info', vol_path).\
- AndReturn((qemu_img_output_1, None))
+ image_utils.qemu_img_info(vol_path_3).\
+ AndReturn(info_3)
drv._local_volume_dir(volume).AndReturn(vol_dir)
- drv._execute('qemu-img', 'info', vol_path_2).\
- AndReturn((qemu_img_output_2, None))
+ image_utils.qemu_img_info(vol_path_2).\
+ AndReturn(info_2)
drv._local_volume_dir(volume).AndReturn(vol_dir)
- drv._execute('qemu-img', 'info', vol_path_3).\
- AndReturn((qemu_img_output_3, None))
+ image_utils.qemu_img_info(vol_path).\
+ AndReturn(info_1)
mox.ReplayAll()
- drv._get_backing_chain_for_path(volume, vol_path)
+ chain = drv._get_backing_chain_for_path(volume, vol_path_3)
+
+ # Verify chain contains all expected data
+ item_1 = drv._get_matching_backing_file(chain, vol_filename)
+ self.assertEqual(item_1['filename'], vol_filename_2)
+ chain.remove(item_1)
+ item_2 = drv._get_matching_backing_file(chain, vol_filename_2)
+ self.assertEqual(item_2['filename'], vol_filename_3)
+ chain.remove(item_2)
+ self.assertEqual(len(chain), 1)
+ self.assertEqual(chain[0]['filename'], vol_filename)
+
+ def test_create_volume_from_snapshot(self):
+ (mox, drv) = self._mox, self._driver
+
+ volume = self._simple_volume('c1073000-0000-0000-0000-0000000c1073')
+ src_volume = self._simple_volume()
+
+ mox.StubOutWithMock(drv, 'create_snapshot')
+ mox.StubOutWithMock(drv, '_copy_volume_from_snapshot')
+ mox.StubOutWithMock(drv, 'delete_snapshot')
+
+ 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}
+
+ volume_ref = {'id': volume['id'],
+ 'size': volume['size'],
+ 'status': volume['status'],
+ 'provider_location': volume['provider_location'],
+ 'name': 'volume-' + volume['id'] + '-clone'}
+
+ drv.create_snapshot(snap_ref)
+ drv._copy_volume_from_snapshot(snap_ref,
+ volume_ref,
+ src_volume['size'])
+ drv.delete_snapshot(snap_ref)
+
+ mox.ReplayAll()
+
+ drv.create_cloned_volume(volume, src_volume)
+
+ def test_initialize_connection(self):
+ (mox, drv) = self._mox, self._driver
+
+ volume = self._simple_volume()
+ vol_dir = os.path.join(self.TEST_MNT_POINT_BASE,
+ drv._get_hash_str(self.TEST_EXPORT1))
+ vol_path = os.path.join(vol_dir, volume['name'])
+
+ qemu_img_output = """image: %s
+ file format: raw
+ virtual size: 1.0G (1073741824 bytes)
+ disk size: 173K
+ """ % volume['name']
+ img_info = image_utils.QemuImgInfo(qemu_img_output)
+
+ mox.StubOutWithMock(drv, 'get_active_image_from_info')
+ mox.StubOutWithMock(image_utils, 'qemu_img_info')
+
+ drv.get_active_image_from_info(volume).AndReturn(volume['name'])
+ image_utils.qemu_img_info(vol_path).AndReturn(img_info)
+
+ mox.ReplayAll()
+
+ conn_info = drv.initialize_connection(volume, None)
+
+ self.assertEqual(conn_info['data']['format'], 'raw')
+ self.assertEqual(conn_info['driver_volume_type'], 'glusterfs')
+ self.assertEqual(conn_info['data']['name'], volume['name'])
def _local_path_volume_info(self, volume):
return '%s%s' % (self._local_path_volume(volume), '.info')
+ def _qemu_img_info(self, path):
+ """Sanitize image_utils' qemu_img_info.
+
+ This code expects to deal only with relative filenames.
+ """
+
+ info = image_utils.qemu_img_info(path)
+ if info.image:
+ info.image = os.path.basename(info.image)
+ if info.backing_file:
+ info.backing_file = os.path.basename(info.backing_file)
+
+ return info
+
def get_active_image_from_info(self, volume):
"""Returns filename of the active image from the info file."""
else:
out_format = 'raw'
- command = ['qemu-img', 'convert',
- '-O', out_format,
- path_to_disk,
- path_to_new_vol]
-
- self._execute(*command, run_as_root=True)
+ image_utils.convert_image(path_to_disk, path_to_new_vol, out_format)
def delete_volume(self, volume):
"""Deletes a logical volume."""
'backing_file=%s' % backing_path_full_path, new_snap_path]
self._execute(*command, run_as_root=True)
- command = ['qemu-img', 'info', backing_path_full_path]
- (out, err) = self._execute(*command, run_as_root=True)
- backing_fmt = self._get_file_format(out)
+ info = self._qemu_img_info(backing_path_full_path)
+ backing_fmt = info.file_format
command = ['qemu-img', 'rebase', '-u',
'-b', backing_filename,
snapshot_path = '%s/%s' % (self._local_volume_dir(snapshot['volume']),
snapshot_file)
- if not os.path.exists(snapshot_path):
- msg = _('Snapshot file at %s does not exist.') % snapshot_path
- raise exception.InvalidSnapshot(msg)
+ snapshot_path_img_info = self._qemu_img_info(snapshot_path)
vol_path = self._local_volume_dir(snapshot['volume'])
# Online delete
context = snapshot['context']
- base_file = self._get_backing_file_for_path(snapshot_path)
+ base_file = snapshot_path_img_info.backing_file
if base_file is None:
# There should always be at least the original volume
# file as base.
# (guaranteed to| (being deleted) |
# exist) | |
- base_file = self._get_backing_file_for_path(snapshot_path)
- snapshot_file_path = '%s/%s' % (vol_path, snapshot_file)
+ base_file = snapshot_path_img_info.backing_file
- self._qemu_img_commit(snapshot_file_path)
- self._execute('rm', '-f', snapshot_file_path, run_as_root=True)
+ self._qemu_img_commit(snapshot_path)
+ self._execute('rm', '-f', snapshot_path, run_as_root=True)
# Remove snapshot_file from info
info_path = self._local_path_volume(snapshot['volume']) + '.info'
self._qemu_img_commit(higher_file_path)
if highest_file is not None:
highest_file_path = '%s/%s' % (vol_path, highest_file)
- snapshot_file_fmt = self._get_file_format_for_path(
- '%s/%s' % (vol_path, snapshot_file))
+ info = self._qemu_img_info(snapshot_path)
+ snapshot_file_fmt = info.file_format
backing_fmt = ('-F', snapshot_file_fmt)
self._execute('qemu-img', 'rebase', '-u',
self._local_volume_dir(snapshot['volume']), file_to_delete)
self._execute('rm', '-f', path_to_delete, run_as_root=True)
- def _get_backing_file(self, output):
- for line in output.split('\n'):
- backing_file = None
-
- m = re.search(r'(?<=backing\ file: )(.*)', line)
- if m:
- backing_file = m.group(0)
-
- if backing_file is None:
- continue
-
- # Remove "(actual path: /mnt/asdf/a.img)" suffix added when
- # running from a different directory
- backing_file = re.sub(r' \(actual path: .*$', '',
- backing_file, count=1)
-
- return os.path.basename(backing_file)
-
- def _get_backing_file_for_path(self, path):
- (out, err) = self._execute('qemu-img', 'info', path,
- run_as_root=True)
- return self._get_backing_file(out)
-
- def _get_file_format_for_path(self, path):
- (out, err) = self._execute('qemu-img', 'info', path,
- run_as_root=True)
- return self._get_file_format(out)
-
def _get_backing_chain_for_path(self, volume, path):
"""Returns list of dicts containing backing-chain information.
output = []
- (out, _err) = self._execute('qemu-img', 'info', path)
+ info = self._qemu_img_info(path)
new_info = {}
new_info['filename'] = os.path.basename(path)
- new_info['backing-filename'] = self._get_backing_file(out)
+ new_info['backing-filename'] = info.backing_file
output.append(new_info)
- while True:
+ while new_info['backing-filename']:
filename = new_info['backing-filename']
path = os.path.join(self._local_volume_dir(volume), filename)
- (out, _err) = self._execute('qemu-img', 'info', path)
- backing_filename = self._get_backing_file(out)
- if backing_filename is None:
- break
+ info = self._qemu_img_info(path)
+ backing_filename = info.backing_file
new_info = {}
new_info['filename'] = filename
new_info['backing-filename'] = backing_filename
return output
- def _get_file_format(self, output):
- for line in output.split('\n'):
- m = re.search(r'(?<=file\ format: )(.*)', line)
- if m:
- return m.group(0)
-
- def _get_backing_file_format(self, output):
- for line in output.split('\n'):
- m = re.search(r'(?<=backing\ file\ format: )(.*)', line)
- if m:
- return m.group(0)
-
def _qemu_img_commit(self, path):
return self._execute('qemu-img', 'commit', path, run_as_root=True)
data['options'] = self.shares[volume['provider_location']]
# Test file for raw vs. qcow2 format
- (out, err) = self._execute('qemu-img', 'info', path,
- run_as_root=True)
- data['format'] = self._get_file_format(out)
+ info = self._qemu_img_info(path)
+ data['format'] = info.file_format
if data['format'] not in ['raw', 'qcow2']:
msg = _('%s must be a valid raw or qcow2 image.') % path
raise exception.InvalidVolume(msg)
active_file = self.get_active_image_from_info(volume)
active_file_path = '%s/%s' % (self._local_volume_dir(volume),
active_file)
- backing_file = self._get_backing_file_for_path(active_file_path)
- if backing_file is not None:
+ info = self._qemu_img_info(active_file_path)
+ backing_file = info.backing_file
+ if backing_file:
snapshots_exist = True
else:
snapshots_exist = False
- root_file_fmt = self._get_file_format_for_path(
- self._local_path_volume(volume))
+ root_file_fmt = info.file_format
temp_path = None
' driver when no snapshots exist.')
raise exception.InvalidVolume(msg)
- (out, err) = self._execute('qemu-img', 'info', volume_path)
- backing_fmt = self._get_file_format(out)
+ info = self._qemu_img_info(volume_path)
+ backing_fmt = info.file_format
if backing_fmt not in ['raw', 'qcow2']:
msg = _('Unrecognized backing format: %s')
raise exception.InvalidVolume(msg % backing_fmt)
# qemu-img can resize both raw and qcow2 files
- cmd = ['qemu-img', 'resize', volume_path, '%sG' % size_gb]
- self._execute(*cmd, run_as_root=True)
+ image_utils.resize_image(volume_path, size_gb)
def _do_create_volume(self, volume):
"""Create a volume on given glusterfs_share.