1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-22 17:35:59 +03:00
lvm2/test/api/python_lvm_unit.py
Tony Asleson 370520a310 python_lvm_unit.py: Clean-up method names & scope
Changed naming of methods from camel case to all lower case with
underscores per guidelines.  Changed any methods that can be
static methods to static.

Signed-off-by: Tony Asleson <tasleson@redhat.com>
2013-11-19 14:40:45 -06:00

813 lines
20 KiB
Python
Executable File

#!/usr/bin/env python
# Copyright (C) 2012-2013 Red Hat, Inc. All rights reserved.
#
# This file is part of LVM2.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import unittest
import random
import string
import lvm
import os
# Set of basic unit tests for the python bindings.
#
# *** WARNING ***
#
# This test tries to only modify configuration for the list of allowed
# PVs, but an error in it could potentially cause data loss if run on a
# production system. Therefore it is strongly advised that this unit test
# not be run on a system that contains data of value.
fh = None
def l(txt):
if os.environ.get('PY_UNIT_LOG') is not None:
global fh
if fh is None:
fh = open('/tmp/lvm_py_unit_test_' + rs(10), "a")
fh.write(txt + "\n")
fh.flush()
def rs(rand_len=10):
"""
Generate a random string
"""
return ''.join(random.choice(string.ascii_uppercase)
for x in range(rand_len))
def _get_allowed_devices():
rc = os.environ.get('PY_UNIT_PVS')
if rc is not None:
rc = rc.split(' ')
rc.sort()
return rc
def compare_pv(right, left):
r_name = right.getName()
l_name = left.getName()
if r_name > l_name:
return 1
elif r_name == l_name:
return 0
else:
return -1
class AllowedPVS(object):
"""
We are only allowed to muck with certain PV, filter to only
the ones we can use.
"""
def __init__(self):
self.handle = None
self.pvs_all = None
def __enter__(self):
rc = []
allowed_dev = _get_allowed_devices()
if allowed_dev:
self.handle = lvm.listPvs()
self.pvs_all = self.handle.open()
for p in self.pvs_all:
if p.getName() in allowed_dev:
rc.append(p)
#Sort them consistently
rc.sort(compare_pv)
return rc
def __exit__(self, t_type, value, traceback):
if self.handle:
self.pvs_all = None
self.handle.close()
class TestLvm(unittest.TestCase):
VG_P = 'py_unit_test_'
@staticmethod
def _get_pv_device_names():
rc = []
with AllowedPVS() as pvs:
for p in pvs:
rc.append(p.getName())
return rc
@staticmethod
def _create_thick_lv(device_list, name):
vg = lvm.vgCreate(TestLvm.VG_P + "_" + name)
for d in device_list:
vg.extend(d)
vg.createLvLinear(name, vg.getSize() / 2)
vg.close()
vg = None
@staticmethod
def _create_thin_pool(device_list, pool_name):
vg = lvm.vgCreate(TestLvm.VG_P + "_" + pool_name)
for d in device_list:
vg.extend(d)
vg.createLvThinpool(pool_name, vg.getSize()/2, 0, 0,
lvm.THIN_DISCARDS_PASSDOWN, 1)
return vg
@staticmethod
def _create_thin_lv(pv_devices, name):
thin_pool_name = 'thin_vg_pool_' + rs(4)
vg = TestLvm._create_thin_pool(pv_devices, thin_pool_name)
vg.createLvThin(thin_pool_name, name, vg.getSize()/8)
vg.close()
vg = None
@staticmethod
def _vg_names():
rc = []
vg_names = lvm.listVgNames()
for i in vg_names:
if i[0:len(TestLvm.VG_P)] == TestLvm.VG_P:
rc.append(i)
return rc
@staticmethod
def _get_lv(lv_vol_type=None, lv_name=None):
vg_name_list = TestLvm._vg_names()
for vg_name in vg_name_list:
vg = lvm.vgOpen(vg_name, "w")
lvs = vg.listLVs()
for lv in lvs:
attr = lv.getAttr()
if lv_vol_type or lv_name:
if lv_vol_type is not None and attr[0] == lv_vol_type:
return lv, vg
elif lv_name is not None and lv_name == lv.getName():
return lv, vg
else:
return lv, vg
vg.close()
return None, None
@staticmethod
def _remove_vg(vg_name):
vg = lvm.vgOpen(vg_name, 'w')
pvs = vg.listPVs()
pe_devices = []
#Remove old snapshots first, then lv
for lv in vg.listLVs():
attr = lv.getAttr()
if attr[0] == 's':
lv.remove()
lvs = vg.listLVs()
#Now remove any thin lVs
for lv in vg.listLVs():
attr = lv.getAttr()
if attr[0] == 'V':
lv.remove()
#now remove the rest
for lv in vg.listLVs():
name = lv.getName()
#Don't remove the hidden ones
if '_tmeta' not in name and '_tdata' not in name:
lv.remove()
for p in pvs:
pe_devices.append(p.getName())
for pv in pe_devices[:-1]:
vg.reduce(pv)
vg.remove()
vg.close()
@staticmethod
def _clean_up():
#Clear out the testing PVs, but only if they contain stuff
#this unit test created
for vg_n in TestLvm._vg_names():
TestLvm._remove_vg(vg_n)
for d in TestLvm._get_pv_device_names():
lvm.pvRemove(d)
lvm.pvCreate(d)
def setUp(self):
device_list = TestLvm._get_pv_device_names()
#Make sure we have an adequate number of PVs to use
self.assertTrue(len(device_list) >= 4)
TestLvm._clean_up()
def tearDown(self):
TestLvm._clean_up()
def test_pv_resize(self):
with AllowedPVS() as pvs:
pv = pvs[0]
curr_size = pv.getSize()
dev_size = pv.getDevSize()
self.assertTrue(curr_size == dev_size)
pv.resize(curr_size/2)
with AllowedPVS() as pvs:
pv = pvs[0]
resized_size = pv.getSize()
self.assertTrue(resized_size != curr_size)
pv.resize(dev_size)
def test_pv_life_cycle(self):
"""
Test removing and re-creating a PV
"""
target_name = None
with AllowedPVS() as pvs:
pv = pvs[0]
target_name = pv.getName()
lvm.pvRemove(target_name)
with AllowedPVS() as pvs:
for p in pvs:
self.assertTrue(p.getName() != target_name)
lvm.pvCreate(target_name, 0)
with AllowedPVS() as pvs:
found = False
for p in pvs:
if p.getName() == target_name:
found = True
self.assertTrue(found)
@staticmethod
def test_pv_methods():
with AllowedPVS() as pvs:
for p in pvs:
p.getName()
p.getUuid()
p.getMdaCount()
p.getSize()
p.getDevSize()
p.getFree()
p = None
def test_version(self):
version = lvm.getVersion()
self.assertNotEquals(version, None)
self.assertEquals(type(version), str)
self.assertTrue(len(version) > 0)
def test_pv_getters(self):
with AllowedPVS() as pvs:
pv = pvs[0]
self.assertEqual(type(pv.getName()), str)
self.assertTrue(len(pv.getName()) > 0)
self.assertEqual(type(pv.getUuid()), str)
self.assertTrue(len(pv.getUuid()) > 0)
self.assertTrue(type(pv.getMdaCount()) == int or
type(pv.getMdaCount()) == long)
self.assertTrue(type(pv.getSize()) == int or
type(pv.getSize()) == long)
self.assertTrue(type(pv.getDevSize()) == int or
type(pv.getSize()) == long)
self.assertTrue(type(pv.getFree()) == int or
type(pv.getFree()) == long)
def _test_prop(self, prop_obj, prop, var_type, settable):
result = prop_obj.getProperty(prop)
self.assertEqual(type(result[0]), var_type)
self.assertEqual(type(result[1]), bool)
self.assertTrue(result[1] == settable)
def test_pv_segs(self):
with AllowedPVS() as pvs:
pv = pvs[0]
pv_segs = pv.listPVsegs()
#LVsegs returns a tuple, (value, bool settable)
#TODO: Test other properties of pv_seg
for i in pv_segs:
self._test_prop(i, 'pvseg_start', long, False)
def test_pv_property(self):
with AllowedPVS() as pvs:
pv = pvs[0]
self._test_prop(pv, 'pv_mda_count', long, False)
def test_lv_property(self):
lv_name = 'lv_test'
TestLvm._create_thin_lv(TestLvm._get_pv_device_names(), lv_name)
lv, vg = TestLvm._get_lv(None, lv_name)
self._test_prop(lv, 'seg_count', long, False)
vg.close()
def test_lv_tags(self):
lv_name = 'lv_test'
TestLvm._create_thin_lv(TestLvm._get_pv_device_names(), lv_name)
lv, vg = TestLvm._get_lv(None, lv_name)
self._test_tags(lv)
vg.close()
def test_lv_active_inactive(self):
lv_name = 'lv_test'
TestLvm._create_thin_lv(TestLvm._get_pv_device_names(), lv_name)
lv, vg = TestLvm._get_lv(None, lv_name)
lv.deactivate()
self.assertTrue(lv.isActive() is False)
lv.activate()
self.assertTrue(lv.isActive() is True)
vg.close()
def test_lv_rename(self):
lv_name = 'lv_test'
TestLvm._create_thin_lv(TestLvm._get_pv_device_names(), lv_name)
lv, vg = TestLvm._get_lv(None, lv_name)
current_name = lv.getName()
new_name = rs()
lv.rename(new_name)
self.assertEqual(lv.getName(), new_name)
lv.rename(current_name)
vg.close()
def test_lv_snapshot(self):
thin_lv = 'thin_lv'
thick_lv = 'thick_lv'
device_names = TestLvm._get_pv_device_names()
TestLvm._create_thin_lv(device_names[0:2], thin_lv)
TestLvm._create_thick_lv(device_names[2:4], thick_lv)
lv, vg = TestLvm._get_lv(None, thick_lv)
lv.snapshot('thick_snap_shot', 1024*1024)
vg.close()
thick_ss, vg = TestLvm._get_lv(None, 'thick_snap_shot')
self.assertTrue(thick_ss is not None)
vg.close()
thin_lv, vg = TestLvm._get_lv(None, thin_lv)
thin_lv.snapshot('thin_snap_shot')
vg.close()
thin_ss, vg = TestLvm._get_lv(None, 'thin_snap_shot')
self.assertTrue(thin_ss is not None)
origin = thin_ss.getOrigin()
self.assertTrue(thin_lv, origin)
vg.close()
def test_lv_suspend(self):
lv_name = 'lv_test'
TestLvm._create_thin_lv(TestLvm._get_pv_device_names(), lv_name)
lv, vg = TestLvm._get_lv(None, lv_name)
result = lv.isSuspended()
self.assertTrue(type(result) == bool)
vg.close()
def test_lv_size(self):
lv_name = 'lv_test'
TestLvm._create_thin_lv(TestLvm._get_pv_device_names(), lv_name)
lv, vg = TestLvm._get_lv(None, lv_name)
result = lv.getSize()
self.assertTrue(type(result) == int or type(result) == long)
vg.close()
def test_lv_resize(self):
lv_name = 'lv_test'
TestLvm._create_thin_lv(TestLvm._get_pv_device_names(), lv_name)
lv, vg = TestLvm._get_lv(None, lv_name)
curr_size = lv.getSize()
lv.resize(curr_size+(1024*1024))
latest = lv.getSize()
self.assertTrue(curr_size != latest)
def test_lv_seg(self):
lv_name = 'lv_test'
TestLvm._create_thin_lv(TestLvm._get_pv_device_names(), lv_name)
lv, vg = TestLvm._get_lv(None, lv_name)
lv_segs = lv.listLVsegs()
#LVsegs returns a tuple, (value, bool settable)
#TODO: Test other properties of lv_seg
for i in lv_segs:
self._test_prop(i, 'seg_start_pe', long, False)
vg.close()
def test_get_set_extend_size(self):
thick_lv = 'get_set_prop'
device_names = TestLvm._get_pv_device_names()
TestLvm._create_thick_lv(device_names[0:2], thick_lv)
lv, vg = TestLvm._get_lv(None, thick_lv)
new_extent = 1024 * 1024 * 4
self.assertFalse(vg.getExtentSize() != new_extent,
"Cannot determine if it works if they are the same")
vg.setExtentSize(new_extent)
self.assertEqual(vg.getExtentSize(), new_extent)
vg.close()
def test_vg_get_set_prop(self):
thick_lv = 'get_set_prop'
device_names = TestLvm._get_pv_device_names()
TestLvm._create_thick_lv(device_names[0:2], thick_lv)
lv, vg = TestLvm._get_lv(None, thick_lv)
self.assertTrue(vg is not None)
if vg:
vg_mda_copies = vg.getProperty('vg_mda_copies')
vg.setProperty('vg_mda_copies', vg_mda_copies[0])
vg.close()
def test_vg_remove_restore(self):
#Store off the list of physical devices
pv_devices = []
thick_lv = 'get_set_prop'
device_names = TestLvm._get_pv_device_names()
TestLvm._create_thick_lv(device_names[0:2], thick_lv)
lv, vg = TestLvm._get_lv(None, thick_lv)
vg_name = vg.getName()
pvs = vg.listPVs()
for p in pvs:
pv_devices.append(p.getName())
vg.close()
TestLvm._remove_vg(vg_name)
self._create_thick_lv(pv_devices, thick_lv)
def test_vg_names(self):
vg = lvm.listVgNames()
self.assertTrue(isinstance(vg, tuple))
def test_dupe_lv_create(self):
"""
Try to create a lv with the same name expecting a failure
Note: This was causing a seg. fault previously
"""
thick_lv = 'dupe_name'
device_names = TestLvm._get_pv_device_names()
TestLvm._create_thick_lv(device_names[0:2], thick_lv)
lv, vg = TestLvm._get_lv(None, thick_lv)
self.assertTrue(vg is not None)
if vg:
lvs = vg.listLVs()
if len(lvs):
lv = lvs[0]
lv_name = lv.getName()
self.assertRaises(lvm.LibLVMError, vg.createLvLinear, lv_name,
lv.getSize())
vg.close()
def test_vg_uuids(self):
device_names = TestLvm._get_pv_device_names()
TestLvm._create_thin_lv(device_names[0:2], 'thin')
TestLvm._create_thick_lv(device_names[2:4], 'thick')
vgs_uuids = lvm.listVgUuids()
self.assertTrue(len(vgs_uuids) > 0)
self.assertTrue(isinstance(vgs_uuids, tuple))
vgs_uuids = list(vgs_uuids)
vgs_names = lvm.listVgNames()
for vg_name in vgs_names:
vg = lvm.vgOpen(vg_name, "r")
#TODO Write/fix BUG, vg uuid don't match between
#lvm.listVgUuids and vg.getUuid()
vg_uuid_search = vg.getUuid().replace('-', '')
self.assertTrue(vg_uuid_search in vgs_uuids)
vgs_uuids.remove(vg_uuid_search)
vg.close()
self.assertTrue(len(vgs_uuids) == 0)
def test_pv_lookup_from_vg(self):
device_names = TestLvm._get_pv_device_names()
TestLvm._create_thin_lv(device_names[0:2], 'thin')
TestLvm._create_thick_lv(device_names[2:4], 'thick')
vg_names = TestLvm._vg_names()
self.assertTrue(len(vg_names) > 0)
for vg_name in vg_names:
vg = lvm.vgOpen(vg_name, 'w')
pvs = vg.listPVs()
for p in pvs:
name = p.getName()
uuid = p.getUuid()
pv_name_lookup = vg.pvFromName(name)
pv_uuid_lookup = vg.pvFromUuid(uuid)
self.assertTrue(pv_name_lookup.getName() ==
pv_uuid_lookup.getName())
self.assertTrue(pv_name_lookup.getUuid() ==
pv_uuid_lookup.getUuid())
self.assertTrue(name == pv_name_lookup.getName())
self.assertTrue(uuid == pv_uuid_lookup.getUuid())
pv_name_lookup = None
pv_uuid_lookup = None
p = None
pvs = None
vg.close()
def test_percent_to_float(self):
self.assertEqual(lvm.percentToFloat(0), 0.0)
self.assertEqual(lvm.percentToFloat(1000000), 1.0)
self.assertEqual(lvm.percentToFloat(1000000 / 2), 0.5)
def test_scan(self):
self.assertEqual(lvm.scan(), None)
def test_config_reload(self):
self.assertEqual(lvm.configReload(), None)
def test_config_override(self):
self.assertEquals(lvm.configOverride("global.test = 1"), None)
def test_config_find_bool(self):
either_or = lvm.configFindBool("global/fallback_to_local_locking")
self.assertTrue(type(either_or) == bool)
self.assertTrue(lvm.configFindBool("global/locking_type"))
def test_vg_from_pv_lookups(self):
device_names = TestLvm._get_pv_device_names()
TestLvm._create_thin_lv(device_names[0:2], 'thin')
TestLvm._create_thick_lv(device_names[2:4], 'thick')
vgname_list = TestLvm._vg_names()
self.assertTrue(len(vgname_list) > 0)
for vg_name in vgname_list:
vg = lvm.vgOpen(vg_name, 'r')
vg_name = vg.getName()
pv_list = vg.listPVs()
for pv in pv_list:
vg_name_from_pv = lvm.vgNameFromPvid(pv.getUuid())
self.assertEquals(vg_name, vg_name_from_pv)
self.assertEqual(vg_name, lvm.vgNameFromDevice(pv.getName()))
vg.close()
def test_vg_get_name(self):
device_names = TestLvm._get_pv_device_names()
TestLvm._create_thin_lv(device_names[0:2], 'thin')
TestLvm._create_thick_lv(device_names[2:4], 'thick')
vgname_list = TestLvm._vg_names()
self.assertTrue(len(vgname_list) > 0)
for vg_name in vgname_list:
vg = lvm.vgOpen(vg_name, 'r')
self.assertEqual(vg.getName(), vg_name)
vg.close()
def test_vg_get_uuid(self):
device_names = TestLvm._get_pv_device_names()
TestLvm._create_thin_lv(device_names[0:2], 'thin')
TestLvm._create_thick_lv(device_names[2:4], 'thick')
vgname_list = TestLvm._vg_names()
self.assertTrue(len(vgname_list) > 0)
for vg_name in vgname_list:
vg = lvm.vgOpen(vg_name, 'r')
uuid = vg.getUuid()
self.assertNotEqual(uuid, None)
self.assertTrue(len(uuid) > 0)
vg.close()
RETURN_NUMERIC = ["getSeqno", "getSize", "getFreeSize", "getFreeSize",
"getExtentSize", "getExtentCount", "getFreeExtentCount",
"getPvCount", "getMaxPv", "getMaxLv"]
def test_vg_getters(self):
device_names = TestLvm._get_pv_device_names()
TestLvm._create_thin_lv(device_names[0:2], 'thin')
TestLvm._create_thick_lv(device_names[2:4], 'thick')
vg_name_list = TestLvm._vg_names()
self.assertTrue(len(vg_name_list) > 0)
for vg_name in vg_name_list:
vg = lvm.vgOpen(vg_name, 'r')
self.assertTrue(type(vg.isClustered()) == bool)
self.assertTrue(type(vg.isExported()) == bool)
self.assertTrue(type(vg.isPartial()) == bool)
#Loop through the list invoking the method
for method_name in TestLvm.RETURN_NUMERIC:
method = getattr(vg, method_name)
result = method()
self.assertTrue(type(result) == int or type(result) == long)
vg.close()
def _test_tags(self, tag_obj):
existing_tags = tag_obj.getTags()
self.assertTrue(type(existing_tags) == tuple)
num_tags = random.randint(2, 40)
created_tags = []
for i in range(num_tags):
tag_name = rs(random.randint(1, 128))
tag_obj.addTag(tag_name)
created_tags.append(tag_name)
tags = tag_obj.getTags()
self.assertTrue(len(existing_tags) + len(created_tags) == len(tags))
num_remove = len(created_tags)
for i in range(num_remove):
tag_to_remove = created_tags[
random.randint(0, len(created_tags) - 1)]
created_tags.remove(tag_to_remove)
tag_obj.removeTag(tag_to_remove)
current_tags = tag_obj.getTags()
self.assertFalse(tag_to_remove in current_tags)
current_tags = tag_obj.getTags()
self.assertTrue(len(current_tags) == len(existing_tags))
for e in existing_tags:
self.assertTrue(e in current_tags)
def test_vg_tags(self):
device_names = TestLvm._get_pv_device_names()
i = 0
for d in device_names:
if i % 2 == 0:
TestLvm._create_thin_lv([d], "thin_lv%d" % i)
else:
TestLvm._create_thick_lv([d], "thick_lv%d" % i)
i += 1
for vg_name in TestLvm._vg_names():
vg = lvm.vgOpen(vg_name, 'w')
self._test_tags(vg)
vg.close()
@staticmethod
def test_listing():
env = os.environ
for k, v in env.items():
l("%s:%s" % (k, v))
with lvm.listPvs() as pvs:
for p in pvs:
l('pv= %s' % p.getName())
l('Checking for VG')
for v in lvm.listVgNames():
l('vg= %s' % v)
def test_pv_empty_listing(self):
#We had a bug where we would seg. fault if we had no PVs.
l('testPVemptylisting entry')
device_names = TestLvm._get_pv_device_names()
for d in device_names:
l("Removing %s" % d)
lvm.pvRemove(d)
count = 0
with lvm.listPvs() as pvs:
for p in pvs:
count += 1
l('pv= %s' % p.getName())
self.assertTrue(count == 0)
for d in device_names:
lvm.pvCreate(d)
def test_pv_create(self):
size = [0, 1024*1024*4]
pvmeta_copies = [0, 1, 2]
pvmeta_size = [0, 255, 512, 1024]
data_alignment = [0, 2048, 4096]
data_alignment_offset = [1, 1, 1]
zero = [0, 1]
device_names = TestLvm._get_pv_device_names()
for d in device_names:
lvm.pvRemove(d)
d = device_names[0]
#Test some error cases
self.assertRaises(TypeError, lvm.pvCreate, None)
self.assertRaises(lvm.LibLVMError, lvm.pvCreate, '')
self.assertRaises(lvm.LibLVMError, lvm.pvCreate, d, 4)
self.assertRaises(lvm.LibLVMError, lvm.pvCreate, d, 0, 4)
self.assertRaises(lvm.LibLVMError, lvm.pvCreate, d, 0, 0, 0, 2**34)
self.assertRaises(lvm.LibLVMError, lvm.pvCreate, d, 0, 0, 0, 4096,
2**34)
#Try a number of combinations and permutations
for s in size:
lvm.pvCreate(d, s)
lvm.pvRemove(d)
for copies in pvmeta_copies:
lvm.pvCreate(d, s, copies)
lvm.pvRemove(d)
for pv_size in pvmeta_size:
lvm.pvCreate(d, s, copies, pv_size)
lvm.pvRemove(d)
for align in data_alignment:
lvm.pvCreate(d, s, copies, pv_size, align)
lvm.pvRemove(d)
for align_offset in data_alignment_offset:
lvm.pvCreate(d, s, copies, pv_size, align,
align * align_offset)
lvm.pvRemove(d)
for z in zero:
lvm.pvCreate(d, s, copies, pv_size, align,
align * align_offset, z)
lvm.pvRemove(d)
#Restore
for d in device_names:
lvm.pvCreate(d)
if __name__ == "__main__":
unittest.main()