Move udev rules blacklisting to utils layer
Also add udevadm_settle() to utils Change-Id: I9bce65fa545c93b3f9b556171c9030baa3795b3e Closes-Bug: #1477537
This commit is contained in:
parent
355c08a049
commit
dee9f2eb7e
@ -127,37 +127,11 @@ class Manager(object):
|
||||
lu.vgremove_all()
|
||||
lu.pvremove_all()
|
||||
|
||||
# Here is udev's rules blacklisting to be done:
|
||||
# by adding symlinks to /dev/null in /etc/udev/rules.d for already
|
||||
# existent rules in /lib/.
|
||||
# 'parted' generates too many udev events in short period of time
|
||||
# so we should increase processing speed for those events,
|
||||
# otherwise partitioning is doomed.
|
||||
empty_rule_path = os.path.join(CONF.udev_rules_dir,
|
||||
os.path.basename(CONF.udev_empty_rule))
|
||||
with open(empty_rule_path, 'w') as f:
|
||||
f.write('#\n')
|
||||
LOG.debug("Enabling udev's rules blacklisting")
|
||||
for rule in os.listdir(CONF.udev_rules_lib_dir):
|
||||
dst = os.path.join(CONF.udev_rules_dir, rule)
|
||||
if os.path.isdir(dst):
|
||||
continue
|
||||
if dst.endswith('.rules'):
|
||||
# for successful blacklisting already existent file with name
|
||||
# from /etc which overlaps with /lib should be renamed prior
|
||||
# symlink creation.
|
||||
try:
|
||||
if os.path.exists(dst):
|
||||
os.rename(dst, dst[:-len('.rules')] +
|
||||
CONF.udev_rename_substr)
|
||||
utils.execute('udevadm', 'settle', '--quiet')
|
||||
except OSError:
|
||||
LOG.debug("Skipping udev rule %s blacklising" % dst)
|
||||
else:
|
||||
os.symlink(empty_rule_path, dst)
|
||||
utils.execute('udevadm', 'settle', '--quiet')
|
||||
utils.execute('udevadm', 'control', '--reload-rules',
|
||||
check_exit_code=[0])
|
||||
utils.blacklist_udev_rules(udev_rules_dir=CONF.udev_rules_dir,
|
||||
udev_rules_lib_dir=CONF.udev_rules_lib_dir,
|
||||
udev_rename_substr=CONF.udev_rename_substr,
|
||||
udev_empty_rule=CONF.udev_empty_rule)
|
||||
|
||||
for parted in self.driver.partition_scheme.parteds:
|
||||
for prt in parted.partitions:
|
||||
@ -191,36 +165,10 @@ class Manager(object):
|
||||
raise errors.PartitionNotFoundError(
|
||||
'Partition %s not found after creation' % prt.name)
|
||||
|
||||
# disable udev's rules blacklisting
|
||||
LOG.debug("Disabling udev's rules blacklisting")
|
||||
for rule in os.listdir(CONF.udev_rules_dir):
|
||||
src = os.path.join(CONF.udev_rules_dir, rule)
|
||||
if os.path.isdir(src):
|
||||
continue
|
||||
if src.endswith('.rules'):
|
||||
if os.path.islink(src):
|
||||
try:
|
||||
os.remove(src)
|
||||
utils.execute('udevadm', 'settle', '--quiet')
|
||||
except OSError:
|
||||
LOG.debug(
|
||||
"Skipping udev rule %s de-blacklisting" % src)
|
||||
elif src.endswith(CONF.udev_rename_substr):
|
||||
try:
|
||||
if os.path.exists(src):
|
||||
os.rename(src, src[:-len(CONF.udev_rename_substr)] +
|
||||
'.rules')
|
||||
utils.execute('udevadm', 'settle', '--quiet')
|
||||
except OSError:
|
||||
LOG.debug("Skipping udev rule %s de-blacklisting" % src)
|
||||
utils.execute('udevadm', 'control', '--reload-rules',
|
||||
check_exit_code=[0])
|
||||
# NOTE(agordeev): re-create all the links which were skipped by udev
|
||||
# while blacklisted
|
||||
# NOTE(agordeev): do subsystem match, otherwise it will stuck
|
||||
utils.execute('udevadm', 'trigger', '--subsystem-match=block',
|
||||
check_exit_code=[0])
|
||||
utils.execute('udevadm', 'settle', '--quiet', check_exit_code=[0])
|
||||
utils.unblacklist_udev_rules(
|
||||
udev_rules_dir=CONF.udev_rules_dir,
|
||||
udev_rename_substr=CONF.udev_rename_substr)
|
||||
|
||||
# If one creates partitions with the same boundaries as last time,
|
||||
# there might be md and lvm metadata on those partitions. To prevent
|
||||
|
@ -268,12 +268,10 @@ class TestManager(unittest2.TestCase):
|
||||
mock.call('swap', '', '', '/dev/mapper/os-swap')]
|
||||
self.assertEqual(mock_fu_mf_expected_calls, mock_fu_mf.call_args_list)
|
||||
|
||||
@mock.patch('six.moves.builtins.open')
|
||||
@mock.patch.object(os, 'symlink')
|
||||
@mock.patch.object(os, 'remove')
|
||||
@mock.patch.object(os, 'path')
|
||||
@mock.patch.object(os, 'listdir')
|
||||
@mock.patch.object(utils, 'execute')
|
||||
@mock.patch.object(manager.os.path, 'exists')
|
||||
@mock.patch.object(manager.utils, 'blacklist_udev_rules')
|
||||
@mock.patch.object(manager.utils, 'unblacklist_udev_rules')
|
||||
@mock.patch.object(manager.utils, 'execute')
|
||||
@mock.patch.object(mu, 'mdclean_all')
|
||||
@mock.patch.object(lu, 'lvremove_all')
|
||||
@mock.patch.object(lu, 'vgremove_all')
|
||||
@ -292,11 +290,9 @@ class TestManager(unittest2.TestCase):
|
||||
mock_pu_spf, mock_pu_sgt, mock_mu_m, mock_lu_p,
|
||||
mock_lu_v, mock_lu_l, mock_fu_mf, mock_pvr,
|
||||
mock_vgr, mock_lvr, mock_mdr, mock_exec,
|
||||
mock_os_ld, mock_os_p, mock_os_r, mock_os_s,
|
||||
mock_open):
|
||||
mock_os_ld.return_value = ['not_a_rule', 'fake.rules']
|
||||
mock_os_p.exists.return_value = True
|
||||
mock_unbl, mock_bl, mock_os_path):
|
||||
mock_hu_lbd.return_value = test_nailgun.LIST_BLOCK_DEVICES_SAMPLE
|
||||
mock_os_path.return_value = True
|
||||
self.mgr.driver.partition_scheme.mds = [
|
||||
objects.MD('fake_md1', 'mirror', devices=['/dev/sda1',
|
||||
'/dev/sdb1']),
|
||||
@ -310,12 +306,10 @@ class TestManager(unittest2.TestCase):
|
||||
['/dev/sdb3', '/dev/sdc1'])],
|
||||
mock_mu_m.call_args_list)
|
||||
|
||||
@mock.patch('six.moves.builtins.open')
|
||||
@mock.patch.object(os, 'symlink')
|
||||
@mock.patch.object(os, 'remove')
|
||||
@mock.patch.object(os, 'path')
|
||||
@mock.patch.object(os, 'listdir')
|
||||
@mock.patch.object(utils, 'execute')
|
||||
@mock.patch.object(manager.os.path, 'exists')
|
||||
@mock.patch.object(manager.utils, 'blacklist_udev_rules')
|
||||
@mock.patch.object(manager.utils, 'unblacklist_udev_rules')
|
||||
@mock.patch.object(manager.utils, 'execute')
|
||||
@mock.patch.object(mu, 'mdclean_all')
|
||||
@mock.patch.object(lu, 'lvremove_all')
|
||||
@mock.patch.object(lu, 'vgremove_all')
|
||||
@ -334,12 +328,16 @@ class TestManager(unittest2.TestCase):
|
||||
mock_pu_spf, mock_pu_sgt, mock_mu_m, mock_lu_p,
|
||||
mock_lu_v, mock_lu_l, mock_fu_mf, mock_pvr,
|
||||
mock_vgr, mock_lvr, mock_mdr, mock_exec,
|
||||
mock_os_ld, mock_os_p, mock_os_r, mock_os_s,
|
||||
mock_open):
|
||||
mock_os_ld.return_value = ['not_a_rule', 'fake.rules']
|
||||
mock_os_p.exists.return_value = True
|
||||
mock_unbl, mock_bl, mock_os_path):
|
||||
mock_os_path.return_value = True
|
||||
mock_hu_lbd.return_value = test_nailgun.LIST_BLOCK_DEVICES_SAMPLE
|
||||
self.mgr.do_partitioning()
|
||||
mock_unbl.assert_called_once_with(udev_rules_dir='/etc/udev/rules.d',
|
||||
udev_rename_substr='.renamedrule')
|
||||
mock_bl.assert_called_once_with(udev_rules_dir='/etc/udev/rules.d',
|
||||
udev_rules_lib_dir='/lib/udev/rules.d',
|
||||
udev_empty_rule='empty_rule',
|
||||
udev_rename_substr='.renamedrule')
|
||||
mock_pu_ml_expected_calls = [mock.call('/dev/sda', 'gpt'),
|
||||
mock.call('/dev/sdb', 'gpt'),
|
||||
mock.call('/dev/sdc', 'gpt')]
|
||||
|
@ -247,19 +247,20 @@ localhost.localdomain)
|
||||
mock_mddisplay.return_value = [{'name': '/dev/md11'}]
|
||||
self.assertRaises(errors.MDRemovingError, mu.mdclean_all)
|
||||
|
||||
@mock.patch.object(utils, 'udevadm_settle')
|
||||
@mock.patch.object(utils, 'execute')
|
||||
@mock.patch.object(mu, 'get_mdnames')
|
||||
def test_mdremove_ok(self, mock_get_mdn, mock_exec):
|
||||
def test_mdremove_ok(self, mock_get_mdn, mock_exec, mock_udev):
|
||||
# should check if md exists
|
||||
# should run mdadm command to remove md device
|
||||
mock_get_mdn.return_value = ['/dev/md0']
|
||||
expected_calls = [
|
||||
mock.call('udevadm', 'settle', '--quiet', check_exit_code=[0]),
|
||||
mock.call('mdadm', '--stop', '/dev/md0', check_exit_code=[0]),
|
||||
mock.call('mdadm', '--remove', '/dev/md0', check_exit_code=[0, 1])
|
||||
]
|
||||
mu.mdremove('/dev/md0')
|
||||
self.assertEqual(mock_exec.call_args_list, expected_calls)
|
||||
mock_udev.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(mu, 'get_mdnames')
|
||||
def test_mdremove_notfound(self, mock_get_mdn):
|
||||
|
@ -31,9 +31,10 @@ class TestPartitionUtils(unittest2.TestCase):
|
||||
pu.wipe('/dev/fake')
|
||||
mock_label.assert_called_once_with('/dev/fake')
|
||||
|
||||
@mock.patch.object(utils, 'udevadm_settle')
|
||||
@mock.patch.object(pu, 'reread_partitions')
|
||||
@mock.patch.object(utils, 'execute')
|
||||
def test_make_label(self, mock_exec, mock_rerd):
|
||||
def test_make_label(self, mock_exec, mock_rerd, mock_udev):
|
||||
# should run parted OS command
|
||||
# in order to create label on a device
|
||||
mock_exec.return_value = ('out', '')
|
||||
@ -41,21 +42,22 @@ class TestPartitionUtils(unittest2.TestCase):
|
||||
# gpt by default
|
||||
pu.make_label('/dev/fake')
|
||||
mock_exec_expected_calls = [
|
||||
mock.call('udevadm', 'settle', '--quiet', check_exit_code=[0]),
|
||||
mock.call('parted', '-s', '/dev/fake', 'mklabel', 'gpt',
|
||||
check_exit_code=[0, 1])]
|
||||
self.assertEqual(mock_exec_expected_calls, mock_exec.call_args_list)
|
||||
mock_rerd.assert_called_once_with('/dev/fake', out='out')
|
||||
mock_udev.assert_called_once_with()
|
||||
mock_exec.reset_mock()
|
||||
mock_rerd.reset_mock()
|
||||
mock_udev.reset_mock()
|
||||
|
||||
# label is set explicitly
|
||||
pu.make_label('/dev/fake', label='msdos')
|
||||
mock_exec_expected_calls = [
|
||||
mock.call('udevadm', 'settle', '--quiet', check_exit_code=[0]),
|
||||
mock.call('parted', '-s', '/dev/fake', 'mklabel', 'msdos',
|
||||
check_exit_code=[0, 1])]
|
||||
self.assertEqual(mock_exec_expected_calls, mock_exec.call_args_list)
|
||||
mock_udev.assert_called_once_with()
|
||||
mock_rerd.assert_called_once_with('/dev/fake', out='out')
|
||||
|
||||
def test_make_label_wrong_label(self):
|
||||
@ -64,9 +66,10 @@ class TestPartitionUtils(unittest2.TestCase):
|
||||
self.assertRaises(errors.WrongPartitionLabelError,
|
||||
pu.make_label, '/dev/fake', 'wrong')
|
||||
|
||||
@mock.patch.object(utils, 'udevadm_settle')
|
||||
@mock.patch.object(pu, 'reread_partitions')
|
||||
@mock.patch.object(utils, 'execute')
|
||||
def test_set_partition_flag(self, mock_exec, mock_rerd):
|
||||
def test_set_partition_flag(self, mock_exec, mock_rerd, mock_udev):
|
||||
# should run parted OS command
|
||||
# in order to set flag on a partition
|
||||
mock_exec.return_value = ('out', '')
|
||||
@ -74,20 +77,21 @@ class TestPartitionUtils(unittest2.TestCase):
|
||||
# default state is 'on'
|
||||
pu.set_partition_flag('/dev/fake', 1, 'boot')
|
||||
mock_exec_expected_calls = [
|
||||
mock.call('udevadm', 'settle', '--quiet', check_exit_code=[0]),
|
||||
mock.call('parted', '-s', '/dev/fake', 'set', '1', 'boot', 'on',
|
||||
check_exit_code=[0, 1])]
|
||||
mock_udev.assert_called_once_with()
|
||||
self.assertEqual(mock_exec_expected_calls, mock_exec.call_args_list)
|
||||
mock_rerd.assert_called_once_with('/dev/fake', out='out')
|
||||
mock_exec.reset_mock()
|
||||
mock_rerd.reset_mock()
|
||||
mock_udev.reset_mock()
|
||||
|
||||
# if state argument is given use it
|
||||
pu.set_partition_flag('/dev/fake', 1, 'boot', state='off')
|
||||
mock_exec_expected_calls = [
|
||||
mock.call('udevadm', 'settle', '--quiet', check_exit_code=[0]),
|
||||
mock.call('parted', '-s', '/dev/fake', 'set', '1', 'boot', 'off',
|
||||
check_exit_code=[0, 1])]
|
||||
mock_udev.assert_called_once_with()
|
||||
self.assertEqual(mock_exec_expected_calls, mock_exec.call_args_list)
|
||||
mock_rerd.assert_called_once_with('/dev/fake', out='out')
|
||||
|
||||
@ -107,10 +111,11 @@ class TestPartitionUtils(unittest2.TestCase):
|
||||
pu.set_partition_flag,
|
||||
'/dev/fake', 1, 'boot', state='wrong')
|
||||
|
||||
@mock.patch.object(utils, 'udevadm_settle')
|
||||
@mock.patch.object(pu, 'reread_partitions')
|
||||
@mock.patch.object(pu, 'info')
|
||||
@mock.patch.object(utils, 'execute')
|
||||
def test_make_partition(self, mock_exec, mock_info, mock_rerd):
|
||||
def test_make_partition(self, mock_exec, mock_info, mock_rerd, mock_udev):
|
||||
# should run parted OS command
|
||||
# in order to create new partition
|
||||
mock_exec.return_value = ('out', '')
|
||||
@ -122,10 +127,10 @@ class TestPartitionUtils(unittest2.TestCase):
|
||||
}
|
||||
pu.make_partition('/dev/fake', 100, 200, 'primary')
|
||||
mock_exec_expected_calls = [
|
||||
mock.call('udevadm', 'settle', '--quiet', check_exit_code=[0]),
|
||||
mock.call('parted', '-a', 'optimal', '-s', '/dev/fake', 'unit',
|
||||
'MiB', 'mkpart', 'primary', '100', '200',
|
||||
check_exit_code=[0, 1])]
|
||||
mock_udev.assert_called_once_with()
|
||||
self.assertEqual(mock_exec_expected_calls, mock_exec.call_args_list)
|
||||
mock_rerd.assert_called_once_with('/dev/fake', out='out')
|
||||
|
||||
@ -165,10 +170,12 @@ class TestPartitionUtils(unittest2.TestCase):
|
||||
self.assertEqual(mock_info.call_args_list,
|
||||
[mock.call('/dev/fake')] * 3)
|
||||
|
||||
@mock.patch.object(utils, 'udevadm_settle')
|
||||
@mock.patch.object(pu, 'reread_partitions')
|
||||
@mock.patch.object(pu, 'info')
|
||||
@mock.patch.object(utils, 'execute')
|
||||
def test_remove_partition(self, mock_exec, mock_info, mock_rerd):
|
||||
def test_remove_partition(self, mock_exec, mock_info, mock_rerd,
|
||||
mock_udev):
|
||||
# should run parted OS command
|
||||
# in order to remove partition
|
||||
mock_exec.return_value = ('out', '')
|
||||
@ -192,9 +199,9 @@ class TestPartitionUtils(unittest2.TestCase):
|
||||
}
|
||||
pu.remove_partition('/dev/fake', 1)
|
||||
mock_exec_expected_calls = [
|
||||
mock.call('udevadm', 'settle', '--quiet', check_exit_code=[0]),
|
||||
mock.call('parted', '-s', '/dev/fake', 'rm', '1',
|
||||
check_exit_code=[0, 1])]
|
||||
mock_udev.assert_called_once_with()
|
||||
self.assertEqual(mock_exec_expected_calls, mock_exec.call_args_list)
|
||||
mock_rerd.assert_called_once_with('/dev/fake', out='out')
|
||||
|
||||
@ -224,17 +231,19 @@ class TestPartitionUtils(unittest2.TestCase):
|
||||
self.assertRaises(errors.PartitionNotFoundError, pu.remove_partition,
|
||||
'/dev/fake', 3)
|
||||
|
||||
@mock.patch.object(utils, 'udevadm_settle')
|
||||
@mock.patch.object(utils, 'execute')
|
||||
def test_set_gpt_type(self, mock_exec):
|
||||
def test_set_gpt_type(self, mock_exec, mock_udev):
|
||||
pu.set_gpt_type('dev', 'num', 'type')
|
||||
mock_exec_expected_calls = [
|
||||
mock.call('udevadm', 'settle', '--quiet', check_exit_code=[0]),
|
||||
mock.call('sgdisk', '--typecode=%s:%s' % ('num', 'type'), 'dev',
|
||||
check_exit_code=[0])]
|
||||
self.assertEqual(mock_exec_expected_calls, mock_exec.call_args_list)
|
||||
mock_udev.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(utils, 'udevadm_settle')
|
||||
@mock.patch.object(utils, 'execute')
|
||||
def test_info(self, mock_exec):
|
||||
def test_info(self, mock_exec, mock_udev):
|
||||
mock_exec.return_value = [
|
||||
'BYT;\n'
|
||||
'/dev/fake:476940MiB:scsi:512:4096:msdos:ATA 1BD14;\n'
|
||||
@ -261,27 +270,29 @@ class TestPartitionUtils(unittest2.TestCase):
|
||||
actual = pu.info('/dev/fake')
|
||||
self.assertEqual(expected, actual)
|
||||
mock_exec_expected_calls = [
|
||||
mock.call('udevadm', 'settle', '--quiet', check_exit_code=[0]),
|
||||
mock.call('parted', '-s', '/dev/fake', '-m', 'unit', 'MiB',
|
||||
'print', 'free', check_exit_code=[0])]
|
||||
self.assertEqual(mock_exec_expected_calls, mock_exec.call_args_list)
|
||||
mock_udev.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(utils, 'execute')
|
||||
def test_reread_partitions_ok(self, mock_exec):
|
||||
pu.reread_partitions('/dev/fake', out='')
|
||||
self.assertEqual(mock_exec.call_args_list, [])
|
||||
|
||||
@mock.patch.object(utils, 'udevadm_settle')
|
||||
@mock.patch.object(time, 'sleep')
|
||||
@mock.patch.object(utils, 'execute')
|
||||
def test_reread_partitions_device_busy(self, mock_exec, mock_sleep):
|
||||
def test_reread_partitions_device_busy(self, mock_exec, mock_sleep,
|
||||
mock_udev):
|
||||
mock_exec.return_value = ('', '')
|
||||
pu.reread_partitions('/dev/fake', out='_Device or resource busy_')
|
||||
mock_exec_expected = [
|
||||
mock.call('partprobe', '/dev/fake', check_exit_code=[0, 1]),
|
||||
mock.call('udevadm', 'settle', '--quiet', check_exit_code=[0]),
|
||||
]
|
||||
self.assertEqual(mock_exec.call_args_list, mock_exec_expected)
|
||||
mock_sleep.assert_called_once_with(2)
|
||||
mock_udev.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(utils, 'execute')
|
||||
def test_reread_partitions_timeout(self, mock_exec):
|
||||
|
@ -212,3 +212,178 @@ class ExecuteTestCase(unittest2.TestCase):
|
||||
# by default files are sorted in backward direction
|
||||
self.assertEqual(filename, 'file1')
|
||||
mock_oslistdir.assert_called_once_with('/some/path')
|
||||
|
||||
@mock.patch.object(utils, 'execute')
|
||||
def test_udevadm_settle(self, mock_exec):
|
||||
utils.udevadm_settle()
|
||||
mock_exec.assert_called_once_with('udevadm', 'settle', '--quiet',
|
||||
check_exit_code=[0])
|
||||
|
||||
|
||||
@mock.patch.object(utils, 'open', create=True, new_callable=mock.mock_open)
|
||||
@mock.patch.object(utils, 'os', autospec=True)
|
||||
@mock.patch.object(utils, 'execute')
|
||||
@mock.patch.object(utils, 'udevadm_settle')
|
||||
class TestUdevRulesBlacklisting(unittest2.TestCase):
|
||||
@staticmethod
|
||||
def _fake_join(path1, path2):
|
||||
return '{0}/{1}'.format(path1, path2)
|
||||
|
||||
def test_blacklist_udev_rules_rule_exists(self, mock_udev, mock_execute,
|
||||
mock_os, mock_open):
|
||||
mock_os.path.join.side_effect = self._fake_join
|
||||
mock_os.path.basename.return_value = 'fake_basename'
|
||||
mock_os.listdir.return_value = ['fake.rules', 'fake_err.rules']
|
||||
mock_os.path.isdir.return_value = False
|
||||
mock_os.path.exists.return_value = True
|
||||
mock_os.rename.side_effect = [None, OSError]
|
||||
utils.blacklist_udev_rules('/etc/udev/rules.d', '/lib/udev/rules.d',
|
||||
'.renamedrule', 'empty_rule')
|
||||
self.assertEqual([mock.call('/etc/udev/rules.d/fake.rules'),
|
||||
mock.call('/etc/udev/rules.d/fake_err.rules')],
|
||||
mock_os.path.exists.call_args_list)
|
||||
self.assertEqual([mock.call('/etc/udev/rules.d/fake.rules',
|
||||
'/etc/udev/rules.d/fake.renamedrule'),
|
||||
mock.call('/etc/udev/rules.d/fake_err.rules',
|
||||
'/etc/udev/rules.d/fake_err.renamedrule')],
|
||||
mock_os.rename.call_args_list)
|
||||
self.assertEqual([mock.call('/etc/udev/rules.d', 'fake_basename'),
|
||||
mock.call('/etc/udev/rules.d', 'fake.rules'),
|
||||
mock.call('/etc/udev/rules.d', 'fake_err.rules')],
|
||||
mock_os.path.join.call_args_list)
|
||||
mock_os.symlink.assert_called_once_with(
|
||||
'/etc/udev/rules.d/fake_basename',
|
||||
'/etc/udev/rules.d/fake.rules')
|
||||
self.assertEqual(2 * [mock.call()], mock_udev.call_args_list)
|
||||
|
||||
def test_blacklist_udev_rules_rule_doesnot_exist(self, mock_udev,
|
||||
mock_execute, mock_os,
|
||||
mock_open):
|
||||
mock_os.path.join.side_effect = self._fake_join
|
||||
mock_os.path.basename.return_value = 'fake_basename'
|
||||
mock_os.listdir.return_value = ['fake.rules']
|
||||
mock_os.path.isdir.return_value = False
|
||||
mock_os.path.exists.return_value = False
|
||||
utils.blacklist_udev_rules('/etc/udev/rules.d', '/lib/udev/rules.d',
|
||||
'.renamedrule', 'empty_rule')
|
||||
self.assertFalse(mock_os.rename.called)
|
||||
mock_os.path.isdir.assert_called_once_with(
|
||||
'/etc/udev/rules.d/fake.rules')
|
||||
mock_os.path.exists.assert_called_once_with(
|
||||
'/etc/udev/rules.d/fake.rules')
|
||||
self.assertEqual([mock.call('/etc/udev/rules.d', 'fake_basename'),
|
||||
mock.call('/etc/udev/rules.d', 'fake.rules')],
|
||||
mock_os.path.join.call_args_list)
|
||||
mock_os.symlink.assert_called_once_with(
|
||||
'/etc/udev/rules.d/fake_basename',
|
||||
'/etc/udev/rules.d/fake.rules')
|
||||
mock_udev.assert_called_once_with()
|
||||
|
||||
def test_blacklist_udev_rules_not_a_rule(self, mock_udev, mock_execute,
|
||||
mock_os, mock_open):
|
||||
mock_os.path.join.side_effect = self._fake_join
|
||||
mock_os.path.basename.return_value = 'fake_basename'
|
||||
mock_os.listdir.return_value = ['not_a_rule', 'dir']
|
||||
mock_os.path.isdir.side_effect = [False, True]
|
||||
utils.blacklist_udev_rules('/etc/udev/rules.d', '/lib/udev/rules.d',
|
||||
'.renamedrule', 'empty_rule')
|
||||
self.assertFalse(mock_udev.called)
|
||||
self.assertFalse(mock_os.symlink.called)
|
||||
self.assertFalse(mock_os.rename.called)
|
||||
self.assertFalse(mock_os.path.exists.called)
|
||||
mock_os.listdir.assert_called_once_with('/lib/udev/rules.d')
|
||||
self.assertEqual([mock.call('/etc/udev/rules.d/not_a_rule'),
|
||||
mock.call('/etc/udev/rules.d/dir')],
|
||||
mock_os.path.isdir.call_args_list)
|
||||
self.assertEqual([mock.call('/etc/udev/rules.d', 'fake_basename'),
|
||||
mock.call('/etc/udev/rules.d', 'not_a_rule'),
|
||||
mock.call('/etc/udev/rules.d', 'dir')],
|
||||
mock_os.path.join.call_args_list)
|
||||
|
||||
def test_blacklist_udev_rules_create_empty_rule(self, mock_udev,
|
||||
mock_execute, mock_os,
|
||||
mock_open):
|
||||
mock_os.path.join.side_effect = self._fake_join
|
||||
mock_os.path.basename.return_value = 'fake_basename'
|
||||
utils.blacklist_udev_rules('/etc/udev/rules.d', '/lib/udev/rules.d',
|
||||
'.renamedrule', 'empty_rule')
|
||||
mock_open.assert_called_once_with('/etc/udev/rules.d/fake_basename',
|
||||
'w')
|
||||
file_handler = mock_open.return_value.__enter__.return_value
|
||||
file_handler.write.assert_called_once_with('#\n')
|
||||
mock_os.path.basename.assert_called_once_with('empty_rule')
|
||||
|
||||
def test_blacklist_udev_rules_execute(self, mock_udev, mock_execute,
|
||||
mock_os, mock_open):
|
||||
utils.blacklist_udev_rules('/etc/udev/rules.d', '/lib/udev/rules.d',
|
||||
'.renamedrule', 'empty_rule')
|
||||
mock_execute.assert_called_once_with(
|
||||
'udevadm', 'control', '--reload-rules', check_exit_code=[0])
|
||||
|
||||
def test_unblacklist_udev_rules_remove(self, mock_udev, mock_execute,
|
||||
mock_os, mock_open):
|
||||
mock_os.path.join.side_effect = self._fake_join
|
||||
mock_os.listdir.return_value = ['fake.rules', 'fake_err.rules']
|
||||
mock_os.remove.side_effect = [None, OSError]
|
||||
mock_os.path.isdir.side_effect = 2 * [False]
|
||||
mock_os.path.islink.return_value = True
|
||||
utils.unblacklist_udev_rules('/etc/udev/rules.d', '.renamedrule')
|
||||
self.assertFalse(mock_os.path.exists.called)
|
||||
self.assertFalse(mock_os.rename.called)
|
||||
mock_os.listdir.assert_called_once_with('/etc/udev/rules.d')
|
||||
expected_rules_calls = [mock.call('/etc/udev/rules.d/fake.rules'),
|
||||
mock.call('/etc/udev/rules.d/fake_err.rules')]
|
||||
self.assertEqual(expected_rules_calls,
|
||||
mock_os.path.islink.call_args_list)
|
||||
self.assertEqual(expected_rules_calls,
|
||||
mock_os.remove.call_args_list)
|
||||
self.assertEqual(2 * [mock.call()], mock_udev.call_args_list)
|
||||
|
||||
def test_unblacklist_udev_rules_executes(self, mock_udev, mock_execute,
|
||||
mock_os, mock_open):
|
||||
utils.unblacklist_udev_rules('/etc/udev/rules.d', '.renamedrule')
|
||||
self.assertEqual([mock.call('udevadm', 'control', '--reload-rules',
|
||||
check_exit_code=[0]),
|
||||
mock.call('udevadm', 'trigger',
|
||||
'--subsystem-match=block',
|
||||
check_exit_code=[0])],
|
||||
mock_execute.call_args_list)
|
||||
|
||||
def test_unblacklist_udev_rules_rename(self, mock_udev, mock_execute,
|
||||
mock_os, mock_open):
|
||||
mock_os.path.join.side_effect = self._fake_join
|
||||
mock_os.listdir.return_value = ['fake.renamedrule',
|
||||
'fake_err.renamedrule']
|
||||
mock_os.rename.side_effect = [None, OSError]
|
||||
mock_os.path.isdir.side_effect = 2 * [False]
|
||||
utils.unblacklist_udev_rules('/etc/udev/rules.d', '.renamedrule')
|
||||
self.assertFalse(mock_os.path.islink.called)
|
||||
self.assertFalse(mock_os.remove.called)
|
||||
mock_os.listdir.assert_called_once_with('/etc/udev/rules.d')
|
||||
self.assertEqual([mock.call('/etc/udev/rules.d/fake.renamedrule'),
|
||||
mock.call('/etc/udev/rules.d/fake_err.renamedrule')],
|
||||
mock_os.path.exists.call_args_list)
|
||||
self.assertEqual([mock.call('/etc/udev/rules.d/fake.renamedrule',
|
||||
'/etc/udev/rules.d/fake.rules'),
|
||||
mock.call('/etc/udev/rules.d/fake_err.renamedrule',
|
||||
'/etc/udev/rules.d/fake_err.rules')],
|
||||
mock_os.rename.call_args_list)
|
||||
self.assertEqual(2 * [mock.call()], mock_udev.call_args_list)
|
||||
|
||||
def test_unblacklist_udev_rules_not_a_rule(self, mock_udev, mock_execute,
|
||||
mock_os, mock_open):
|
||||
mock_os.path.join.side_effect = self._fake_join
|
||||
mock_os.listdir.return_value = ['not_a_rule', 'dir']
|
||||
mock_os.path.isdir.side_effect = [False, True]
|
||||
utils.unblacklist_udev_rules('/etc/udev/rules.d', '.renamedrule')
|
||||
mock_os.listdir.assert_called_once_with('/etc/udev/rules.d')
|
||||
self.assertEqual([mock.call('/etc/udev/rules.d', 'not_a_rule'),
|
||||
mock.call('/etc/udev/rules.d', 'dir')],
|
||||
mock_os.path.join.call_args_list)
|
||||
self.assertEqual([mock.call('/etc/udev/rules.d/not_a_rule'),
|
||||
mock.call('/etc/udev/rules.d/dir')],
|
||||
mock_os.path.isdir.call_args_list)
|
||||
self.assertFalse(mock_os.path.exists.called)
|
||||
self.assertFalse(mock_os.remove.called)
|
||||
self.assertFalse(mock_os.rename.called)
|
||||
mock_udev.assert_called_once_with()
|
||||
|
@ -142,7 +142,7 @@ def mdremove(mdname):
|
||||
# too busy with events when we start to modifiy md devices hard.
|
||||
# Thus `udevadm settle` is helping to avoid the later failure and
|
||||
# to prevent strange behaviour of md device.
|
||||
utils.execute('udevadm', 'settle', '--quiet', check_exit_code=[0])
|
||||
utils.udevadm_settle()
|
||||
utils.execute('mdadm', '--stop', mdname, check_exit_code=[0])
|
||||
utils.execute('mdadm', '--remove', mdname, check_exit_code=[0, 1])
|
||||
|
||||
|
@ -49,7 +49,7 @@ def parse_partition_info(output):
|
||||
|
||||
|
||||
def info(dev):
|
||||
utils.execute('udevadm', 'settle', '--quiet', check_exit_code=[0])
|
||||
utils.udevadm_settle()
|
||||
output = utils.execute('parted', '-s', dev, '-m',
|
||||
'unit', 'MiB',
|
||||
'print', 'free',
|
||||
@ -80,7 +80,7 @@ def make_label(dev, label='gpt'):
|
||||
if label not in ('gpt', 'msdos'):
|
||||
raise errors.WrongPartitionLabelError(
|
||||
'Wrong partition label type: %s' % label)
|
||||
utils.execute('udevadm', 'settle', '--quiet', check_exit_code=[0])
|
||||
utils.udevadm_settle()
|
||||
out, err = utils.execute('parted', '-s', dev, 'mklabel', label,
|
||||
check_exit_code=[0, 1])
|
||||
LOG.debug('Parted output: \n%s' % out)
|
||||
@ -109,7 +109,7 @@ def set_partition_flag(dev, num, flag, state='on'):
|
||||
if state not in ('on', 'off'):
|
||||
raise errors.WrongPartitionSchemeError(
|
||||
'Wrong partition flag state: %s' % state)
|
||||
utils.execute('udevadm', 'settle', '--quiet', check_exit_code=[0])
|
||||
utils.udevadm_settle()
|
||||
out, err = utils.execute('parted', '-s', dev, 'set', str(num),
|
||||
flag, state, check_exit_code=[0, 1])
|
||||
LOG.debug('Parted output: \n%s' % out)
|
||||
@ -130,7 +130,7 @@ def set_gpt_type(dev, num, type_guid):
|
||||
# TODO(kozhukalov): check whether type_guid is valid
|
||||
LOG.debug('Setting partition GUID: dev=%s num=%s guid=%s' %
|
||||
(dev, num, type_guid))
|
||||
utils.execute('udevadm', 'settle', '--quiet', check_exit_code=[0])
|
||||
utils.udevadm_settle()
|
||||
utils.execute('sgdisk', '--typecode=%s:%s' % (num, type_guid),
|
||||
dev, check_exit_code=[0])
|
||||
|
||||
@ -154,7 +154,7 @@ def make_partition(dev, begin, end, ptype):
|
||||
'Invalid boundaries: begin and end '
|
||||
'are not inside available free space')
|
||||
|
||||
utils.execute('udevadm', 'settle', '--quiet', check_exit_code=[0])
|
||||
utils.udevadm_settle()
|
||||
out, err = utils.execute(
|
||||
'parted', '-a', 'optimal', '-s', dev, 'unit', 'MiB',
|
||||
'mkpart', ptype, str(begin), str(end), check_exit_code=[0, 1])
|
||||
@ -167,7 +167,7 @@ def remove_partition(dev, num):
|
||||
if not any(x['fstype'] != 'free' and x['num'] == num
|
||||
for x in info(dev)['parts']):
|
||||
raise errors.PartitionNotFoundError('Partition %s not found' % num)
|
||||
utils.execute('udevadm', 'settle', '--quiet', check_exit_code=[0])
|
||||
utils.udevadm_settle()
|
||||
out, err = utils.execute('parted', '-s', dev, 'rm',
|
||||
str(num), check_exit_code=[0, 1])
|
||||
reread_partitions(dev, out=out)
|
||||
@ -191,4 +191,4 @@ def reread_partitions(dev, out='Device or resource busy', timeout=60):
|
||||
time.sleep(2)
|
||||
out, err = utils.execute('partprobe', dev, check_exit_code=[0, 1])
|
||||
LOG.debug('Partprobe output: \n%s' % out)
|
||||
utils.execute('udevadm', 'settle', '--quiet', check_exit_code=[0])
|
||||
utils.udevadm_settle()
|
||||
|
@ -265,3 +265,72 @@ def guess_filename(path, regexp, sort=True, reverse=True):
|
||||
if re.search(regexp, filename):
|
||||
return filename
|
||||
return None
|
||||
|
||||
|
||||
def blacklist_udev_rules(udev_rules_dir, udev_rules_lib_dir,
|
||||
udev_rename_substr, udev_empty_rule):
|
||||
"""Blacklist udev rules
|
||||
|
||||
Here is udev's rules blacklisting to be done:
|
||||
by adding symlinks to /dev/null in /etc/udev/rules.d for already
|
||||
existent rules in /lib/.
|
||||
'parted' generates too many udev events in short period of time
|
||||
so we should increase processing speed for those events,
|
||||
otherwise partitioning is doomed.
|
||||
"""
|
||||
empty_rule_path = os.path.join(udev_rules_dir,
|
||||
os.path.basename(udev_empty_rule))
|
||||
with open(empty_rule_path, 'w') as f:
|
||||
f.write('#\n')
|
||||
for rule in os.listdir(udev_rules_lib_dir):
|
||||
dst = os.path.join(udev_rules_dir, rule)
|
||||
if os.path.isdir(dst):
|
||||
continue
|
||||
if dst.endswith('.rules'):
|
||||
# for successful blacklisting already existent file with name
|
||||
# from /etc which overlaps with /lib should be renamed prior
|
||||
# symlink creation.
|
||||
try:
|
||||
if os.path.exists(dst):
|
||||
os.rename(dst, dst[:-len('.rules')] + udev_rename_substr)
|
||||
udevadm_settle()
|
||||
except OSError:
|
||||
LOG.debug("Skipping udev rule %s blacklising" % dst)
|
||||
else:
|
||||
os.symlink(empty_rule_path, dst)
|
||||
udevadm_settle()
|
||||
execute('udevadm', 'control', '--reload-rules', check_exit_code=[0])
|
||||
|
||||
|
||||
def unblacklist_udev_rules(udev_rules_dir, udev_rename_substr):
|
||||
"""disable udev's rules blacklisting"""
|
||||
for rule in os.listdir(udev_rules_dir):
|
||||
src = os.path.join(udev_rules_dir, rule)
|
||||
if os.path.isdir(src):
|
||||
continue
|
||||
if src.endswith('.rules'):
|
||||
if os.path.islink(src):
|
||||
try:
|
||||
os.remove(src)
|
||||
udevadm_settle()
|
||||
except OSError:
|
||||
LOG.debug(
|
||||
"Skipping udev rule %s de-blacklisting" % src)
|
||||
elif src.endswith(udev_rename_substr):
|
||||
try:
|
||||
if os.path.exists(src):
|
||||
os.rename(src, src[:-len(udev_rename_substr)] + '.rules')
|
||||
udevadm_settle()
|
||||
except OSError:
|
||||
LOG.debug("Skipping udev rule %s de-blacklisting" % src)
|
||||
execute('udevadm', 'control', '--reload-rules', check_exit_code=[0])
|
||||
# NOTE(agordeev): re-create all the links which were skipped by udev
|
||||
# while blacklisted
|
||||
# NOTE(agordeev): do subsystem match, otherwise it will stuck
|
||||
execute('udevadm', 'trigger', '--subsystem-match=block',
|
||||
check_exit_code=[0])
|
||||
udevadm_settle()
|
||||
|
||||
|
||||
def udevadm_settle():
|
||||
execute('udevadm', 'settle', '--quiet', check_exit_code=[0])
|
||||
|
Loading…
Reference in New Issue
Block a user