Merge pull request #28265 from jfindlay/blockdev

fix blockdev execution and state modules
This commit is contained in:
Mike Place 2015-10-26 06:27:36 -06:00
commit 62485e567f
4 changed files with 195 additions and 46 deletions

View file

@ -12,17 +12,28 @@ import subprocess
# Import salt libs
import salt.utils
import salt.utils.decorators as decorators
log = logging.getLogger(__name__)
__func_alias__ = {
'format_': 'format'
}
__virtualname__ = 'blockdev'
def __virtual__():
'''
Only work on POSIX-like systems
Only load this module if the blockdev utility is available
'''
if salt.utils.is_windows():
return False
return True
return (False, ('The {0} execution module '
'is not supported on windows'.format(__virtualname__)))
elif not salt.utils.which('blockdev'):
return (False, ('Cannot load the {0} execution module: '
'blockdev utility not found'.format(__virtualname__)))
return __virtualname__
def tune(device, **kwargs):
@ -33,7 +44,7 @@ def tune(device, **kwargs):
.. code-block:: bash
salt '*' blockdev.tune /dev/sda1 read-ahead=1024 read-write=True
salt '*' blockdev.tune /dev/sdX1 read-ahead=1024 read-write=True
Valid options are: ``read-ahead``, ``filesystem-read-ahead``,
``read-only``, ``read-write``.
@ -64,6 +75,7 @@ def tune(device, **kwargs):
return dump(device, args)
@decorators.which('wipefs')
def wipe(device):
'''
Remove the filesystem information
@ -72,7 +84,7 @@ def wipe(device):
.. code-block:: bash
salt '*' blockdev.wipe /dev/sda1
salt '*' blockdev.wipe /dev/sdX1
'''
cmd = 'wipefs {0}'.format(device)
@ -88,21 +100,38 @@ def dump(device, args=None):
'''
Return all contents of dumpe2fs for a specified device
args
a list containing only the desired arguments to return
CLI Example:
.. code-block:: bash
salt '*' extfs.dump /dev/sda1
salt '*' blockdev.dump /dev/sdX1
'''
cmd = 'blockdev --getro --getsz --getss --getpbsz --getiomin --getioopt --getalignoff --getmaxsect --getsize --getsize64 --getra --getfra {0}'.format(device)
cmd = ['blockdev',
'--getro',
'--getsz',
'--getss',
'--getpbsz',
'--getiomin',
'--getioopt',
'--getalignoff',
'--getmaxsect',
'--getsize',
'--getsize64',
'--getra',
'--getfra',
str(device)]
ret = {}
opts = [c[2:] for c in cmd.split() if c.startswith('--')]
opts = [c[2:] for c in cmd if c.startswith('--')]
out = __salt__['cmd.run_all'](cmd, python_shell=False)
if out['retcode'] == 0:
lines = [line for line in out['stdout'].splitlines() if line]
count = 0
for line in lines:
ret[opts[count]] = line
count = count+1
count += 1
if args:
temp_ret = {}
for arg in args:
@ -114,6 +143,94 @@ def dump(device, args=None):
return False
@decorators.which('sync')
@decorators.which('mkfs')
def format_(device, fs_type='ext4', inode_size=None, lazy_itable_init=None):
'''
Format a filesystem onto a block device
.. versionadded:: 2015.8.2
device
The block device in which to create the new filesystem
fs_type
The type of filesystem to create
inode_size
Size of the inodes
This option is only enabled for ext and xfs filesystems
lazy_itable_init
If enabled and the uninit_bg feature is enabled, the inode table will
not be fully initialized by mke2fs. This speeds up filesystem
initialization noticeably, but it requires the kernel to finish
initializing the filesystem in the background when the filesystem
is first mounted. If the option value is omitted, it defaults to 1 to
enable lazy inode table zeroing.
This option is only enabled for ext filesystems
CLI Example:
.. code-block:: bash
salt '*' blockdev.format /dev/sdX1
'''
cmd = ['mkfs', '-t', str(fs_type)]
if inode_size is not None:
if fs_type[:3] == 'ext':
cmd.extend(['-i', str(inode_size)])
elif fs_type == 'xfs':
cmd.extend(['-i', 'size={0}'.format(inode_size)])
if lazy_itable_init is not None:
if fs_type[:3] == 'ext':
cmd.extend(['-E', 'lazy_itable_init={0}'.format(lazy_itable_init)])
cmd.append(str(device))
mkfs_success = __salt__['cmd.retcode'](cmd, ignore_retcode=True) == 0
sync_success = __salt__['cmd.retcode']('sync', ignore_retcode=True) == 0
return all([mkfs_success, sync_success])
@decorators.which_bin(['lsblk', 'df'])
def fstype(device):
'''
Return the filesystem name of a block device
.. versionadded:: 2015.8.2
device
The name of the block device
CLI Example:
.. code-block:: bash
salt '*' blockdev.fstype /dev/sdX1
'''
if salt.utils.which('lsblk'):
lsblk_out = __salt__['cmd.run']('lsblk -o fstype {0}'.format(device)).splitlines()
if len(lsblk_out) > 1:
fs_type = lsblk_out[1].strip()
if fs_type:
return fs_type
if salt.utils.which('df'):
# the fstype was not set on the block device, so inspect the filesystem
# itself for its type
df_out = __salt__['cmd.run']('df -T {0}'.format(device)).splitlines()
if len(df_out) > 1:
fs_type = df_out[1].split()[1]
if fs_type:
return fs_type
return ''
@decorators.which('resize2fs')
def resize2fs(device):
'''
Resizes the filesystem.
@ -121,7 +238,7 @@ def resize2fs(device):
CLI Example:
.. code-block:: bash
salt '*' blockdev.resize2fs /dev/sda1
salt '*' blockdev.resize2fs /dev/sdX1
'''
ret = {}
cmd = 'resize2fs {0}'.format(device)

View file

@ -29,14 +29,17 @@ import os.path
# Import salt libs
import salt.utils
__virtualname__ = 'blockdev'
def __virtual__():
'''
Only work on POSIX-like systems
Only load this module if the blockdev execution module is available
'''
if salt.utils.is_windows():
return False
return True
if 'blockdev.tune' in __salt__:
return __virtualname__
return (False, ('Cannot load the {0} state module: '
'blockdev execution module not found'.format(__virtualname__)))
def tuned(name, **kwargs):
@ -146,25 +149,8 @@ def formatted(name, fs_type='ext4', **kwargs):
ret['result'] = None
return ret
cmd = 'mkfs -t {0} '.format(fs_type)
if 'inode_size' in kwargs:
if fs_type[:3] == 'ext':
cmd += '-i {0} '.format(kwargs['inode_size'])
elif fs_type == 'xfs':
cmd += '-i size={0} '.format(kwargs['inode_size'])
if 'lazy_itable_init' in kwargs:
if fs_type[:3] == 'ext':
cmd += '-E lazy_itable_init={0} '.format(kwargs['lazy_itable_init'])
cmd += name
__salt__['cmd.run'](cmd).splitlines()
__salt__['cmd.run']('sync').splitlines()
blk = __salt__['cmd.run']('lsblk -o fstype {0}'.format(name)).splitlines()
if len(blk) == 1:
current_fs = ''
else:
current_fs = blk[1]
__salt__['blockdev.format'](name, fs_type, **kwargs)
current_fs = __salt__['blockdev.fstype'](name)
if current_fs == fs_type:
ret['comment'] = ('{0} has been formatted '

View file

@ -21,37 +21,79 @@ blockdev.__salt__ = {
@skipIf(NO_MOCK, NO_MOCK_REASON)
class TestBlockdevModule(TestCase):
def test_dump(self):
device = '/dev/sdX'
cmd = ['blockdev',
'--getro',
'--getsz',
'--getss',
'--getpbsz',
'--getiomin',
'--getioopt',
'--getalignoff',
'--getmaxsect',
'--getsize',
'--getsize64',
'--getra',
'--getfra',
device]
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(blockdev.__salt__, {'cmd.run_all': mock}):
blockdev.dump('/dev/sda')
mock.assert_called_once_with(
'blockdev --getro --getsz --getss --getpbsz --getiomin '
'--getioopt --getalignoff --getmaxsect --getsize '
'--getsize64 --getra --getfra /dev/sda',
python_shell=False
)
blockdev.dump(device)
mock.assert_called_once_with(cmd, python_shell=False)
def test_wipe(self):
device = '/dev/sdX'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(blockdev.__salt__, {'cmd.run_all': mock}):
blockdev.wipe('/dev/sda')
blockdev.wipe(device)
mock.assert_called_once_with(
'wipefs /dev/sda',
'wipefs {0}'.format(device),
python_shell=False
)
def test_tune(self):
device = '/dev/sdX'
mock = MagicMock(return_value='712971264\n512\n512\n512\n0\n0\n88\n712971264\n365041287168\n512\n512')
with patch.dict(blockdev.__salt__, {'cmd.run': mock}):
mock_dump = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch('salt.modules.blockdev.dump', mock_dump):
kwargs = {'read-ahead': 512, 'filesystem-read-ahead': 512}
blockdev.tune('/dev/sda', **kwargs)
blockdev.tune(device, **kwargs)
mock.assert_called_once_with(
'blockdev --setra 512 --setfra 512 /dev/sda',
'blockdev --setra 512 --setfra 512 {0}'.format(device),
python_shell=False
)
def test_format(self):
'''
unit tests for blockdev.format
'''
device = '/dev/sdX1'
fs_type = 'ext4'
mock = MagicMock(return_value=0)
with patch.dict(blockdev.__salt__, {'cmd.retcode': mock}):
self.assertEqual(blockdev.format_(device), True)
def test_fstype(self):
'''
unit tests for blockdev.fstype
'''
device = '/dev/sdX1'
fs_type = 'ext4'
mock = MagicMock(return_value='FSTYPE\n{0}'.format(fs_type))
with patch.dict(blockdev.__salt__, {'cmd.run': mock}):
self.assertEqual(blockdev.fstype(device), fs_type)
def test_resize2fs(self):
'''
unit tests for blockdev.resize2fs
'''
device = '/dev/sdX1'
mock = MagicMock()
with patch.dict(blockdev.__salt__, {'cmd.run_all': mock}):
blockdev.resize2fs(device)
mock.assert_called_once_with('resize2fs {0}'.format(device), python_shell=False)
if __name__ == '__main__':
from integration import run_tests

View file

@ -76,8 +76,12 @@ class BlockdevTestCase(TestCase):
ret.update({'comment': comt})
self.assertDictEqual(blockdev.formatted(name), ret)
mock = MagicMock(return_value='ext4')
with patch.dict(blockdev.__salt__, {'cmd.run': mock}):
mock_ext4 = MagicMock(return_value='ext4')
mock_t = MagicMock(return_value=True)
mock_e = MagicMock(return_value='')
with patch.dict(blockdev.__salt__, {'cmd.run': mock_ext4,
'blockdev.format': mock_t,
'blockdev.fstype': mock_e}):
comt = ('{0} already formatted with '.format(name))
ret.update({'comment': comt, 'result': True})
self.assertDictEqual(blockdev.formatted(name, fs_type=''), ret)