curtin-dev team mailing list archive
-
curtin-dev team
-
Mailing list archive
-
Message #01089
[Merge] ~mwhudson/curtin:pare-down-dasdview-parsing into curtin:master
Michael Hudson-Doyle has proposed merging ~mwhudson/curtin:pare-down-dasdview-parsing into curtin:master.
Commit message:
simplify dasdview parsing code
Now that the only thing we need dasdview output for is to determine the format type of the dasd (ldl vs cdl vs unformatted) we can make a few things simpler.
Requested reviews:
curtin developers (curtin-dev)
For more details, see:
https://code.launchpad.net/~mwhudson/curtin/+git/curtin/+merge/394207
--
Your team curtin developers is requested to review the proposed merge of ~mwhudson/curtin:pare-down-dasdview-parsing into curtin:master.
diff --git a/curtin/block/dasd.py b/curtin/block/dasd.py
index 7450300..8524d63 100644
--- a/curtin/block/dasd.py
+++ b/curtin/block/dasd.py
@@ -1,13 +1,12 @@
# This file is part of curtin. See LICENSE file for copyright and license info.
-import collections
+import glob
import os
+import re
import tempfile
from curtin import util
from curtin.log import LOG, logged_time
-Dasdvalue = collections.namedtuple('Dasdvalue', ['hex', 'dec', 'txt'])
-
class DasdPartition:
def __init__(self, table, device, start, end, length, id, system):
@@ -116,196 +115,43 @@ def dasdinfo(device_id):
return util.load_shell_content(out)
-def dasdview(devname):
- ''' Run dasdview on devname and return dictionary of data.
-
- dasdview --extended has 3 sections
- general (2:6), geometry (8:12), extended (14:)
-
- '''
+def dasd_format(devname):
+ """Return the format (ldl/cdl/not-formatted) of devname."""
if not os.path.exists(devname):
raise ValueError("Invalid dasd device name: '%s'" % devname)
out, err = util.subp(['dasdview', '--extended', devname], capture=True)
- return _parse_dasdview(out)
-
-
-def _parse_dasdview(view_output):
- """ Parse dasdview --extended output into a dictionary
-
- Input:
- --- general DASD information ---------------------------------------------
- device node : /dev/dasdd
- busid : 0.0.1518
- type : ECKD
- device type : hex 3390 dec 13200
-
- --- DASD geometry --------------------------------------------------------
- number of cylinders : hex 2721 dec 10017
- tracks per cylinder : hex f dec 15
- blocks per track : hex c dec 12
- blocksize : hex 1000 dec 4096
-
- --- extended DASD information --------------------------------------------
- real device number : hex 0 dec 0
- subchannel identifier : hex 178 dec 376
- CU type (SenseID) : hex 3990 dec 14736
- CU model (SenseID) : hex e9 dec 233
- device type (SenseID) : hex 3390 dec 13200
- device model (SenseID) : hex c dec 12
- open count : hex 1 dec 1
- req_queue_len : hex 0 dec 0
- chanq_len : hex 0 dec 0
- status : hex 5 dec 5
- label_block : hex 2 dec 2
- FBA_layout : hex 0 dec 0
- characteristics_size : hex 40 dec 64
- confdata_size : hex 100 dec 256
- format : hex 2 dec 2 CDL formatted
- features : hex 0 dec 0 default
-
- characteristics : 3990e933 900c5e0c 39f72032 2721000f
- e000e5a2 05940222 13090674 00000000
- 00000000 00000000 32321502 dfee0001
- 0677080f 007f4800 1f3c0000 00002721
-
- configuration_data : dc010100 f0f0f2f1 f0f7f9f0 f0c9c2d4
- f7f5f0f0 f0f0f0f0 f0c4e7d7 f7f10818
- d4020000 f0f0f2f1 f0f7f9f6 f1c9c2d4
- f7f5f0f0 f0f0f0f0 f0c4e7d7 f7f10800
- d0000000 f0f0f2f1 f0f7f9f6 f1c9c2d4
- f7f5f0f0 f0f0f0f0 f0c4e7d7 f7f00800
- f0000001 f0f0f2f1 f0f7f9f0 f0c9c2d4
- f7f5f0f0 f0f0f0f0 f0c4e7d7 f7f10800
- 00000000 00000000 00000000 00000000
- 00000000 00000000 00000000 00000000
- 00000000 00000000 00000000 00000000
- 00000000 00000000 00000000 00000000
- 00000000 00000000 00000000 00000000
- 00000000 00000000 00000000 00000000
- 81000003 2d001e00 15000247 000c0016
- 000cc018 935e41ee 00030000 0000a000
-
- Output:
-
- view = {
- 'extended': {
- 'chanq_len': Dasdvalue(hex='0x0', dec=0, txt=None),
- 'characteristics': ['3990e933', ...], # shortened for brevity
- 'characteristics_size': Dasdvalue(hex='0x40', dec=64, txt=None),
- 'confdata_size': Dasdvalue(hex='0x100', dec=256, txt=None),
- 'configuration_data': ['dc010100', ...], # shortened for brevity
- 'cu_model_senseid': Dasdvalue(hex='0xe9', dec=233, txt=None),
- 'cu_type__senseid': Dasdvalue(hex='0x3990', dec=14736, txt=None),
- 'device_model_senseid': Dasdvalue(hex='0xc', dec=12, txt=None),
- 'device_type__senseid': Dasdvalue(hex='0x3390', dec=13200, txt=None),
- 'fba_layout': Dasdvalue(hex='0x0', dec=0, txt=None),
- 'features': Dasdvalue(hex='0x0', dec=0, txt='default'),
- 'format': Dasdvalue(hex='0x2', dec=2, txt='cdl'),
- 'label_block': Dasdvalue(hex='0x2', dec=2, txt=None),
- 'open_count': Dasdvalue(hex='0x1', dec=1, txt=None),
- 'real_device_number': Dasdvalue(hex='0x0', dec=0, txt=None),
- 'req_queue_len': Dasdvalue(hex='0x0', dec=0, txt=None),
- 'status': Dasdvalue(hex='0x5', dec=5, txt=None),
- 'subchannel_identifier': Dasdvalue(hex='0x178', dec=376, txt=None)},
- 'general': {
- 'busid': ['0.0.1518'],
- 'device_node': ['/dev/dasdd'],
- 'device_type': Dasdvalue(hex='0x3390', dec=13200, txt=None),
- 'type': ['ECKD']},
- 'geometry': {
- 'blocks_per_track': Dasdvalue(hex='0xc', dec=12, txt=None),
- 'blocksize': Dasdvalue(hex='0x1000', dec=4096, txt=None),
- 'number_of_cylinders': Dasdvalue(hex='0x2721', dec=10017, txt=None),
- 'tracks_per_cylinder': Dasdvalue(hex='0xf', dec=15, txt=None)}
- }
- """
+ return _dasd_format(out)
- info_key_map = {
- 'CDL formatted': 'cdl',
- 'LDL formatted': 'ldl',
- 'NOT formatted': 'not-formatted',
- }
- def _mkdasdvalue(hex_str, dec_str, comment=None):
- v_hex = hex_str.replace('hex ', '0x')
- v_dec = int(dec_str.replace('dec ', ''))
- v_str = None
- if comment is not None:
- v_str = info_key_map.get(comment, comment)
-
- return Dasdvalue(v_hex, v_dec, v_str)
-
- def _map_strip(value):
- v_type = type(value)
- return v_type(map(lambda x: x.strip(), value))
-
- def _parse_output(output):
- parsed = {}
- key = prev_key = value = None
- for line in output:
- if not line:
- continue
- if ':' in line:
- key, value = map(lambda x: x.strip(),
- line.lstrip().split(':'))
- # normalize lvalue
- key = key.replace(' ', '_')
- key = key.replace(' ', '_')
- key = key.replace('(', '').replace(')', '')
- key = key.lower()
- prev_key = key
- if value and '\t' in value:
- value = _map_strip(value.split('\t'))
- # [hex X, dec Y]
- # [hex X, dec Y, string]
- value = _mkdasdvalue(*value)
- elif value and ' ' in value:
- # characteristics : XXXXXXX XXXXXXX XXXXXXXX XXXXXXX
- # YYYYYYY YYYYYYY YYYYYYYY YYYYYYY
- # convert to list of strings.
- value = value.lstrip().split()
- else:
- value = None
- else:
- key = prev_key
- # no colon line, parse value from line
- # YYYYYYY YYYYYYY YYYYYYYY YYYYYYY
- value = line.lstrip().split()
-
- # extend lists for existing keys
- if key in parsed and type(value) == list:
- parsed[key].extend(value)
- else:
- parsed.update({key: value})
-
- return parsed
-
- if not view_output or not isinstance(view_output, util.string_types):
- raise ValueError(
- 'Invalid value for input to parse: ' + str(view_output))
+DASD_FORMAT = r"^format\s+:.+\s+(?P<value>\w+\s\w+)$"
+
+
+def find_val(regex, content):
+ m = re.search(regex, content, re.MULTILINE)
+ if m is not None:
+ return m.group("value")
- # XXX: dasdview --extended has 52 lines for dasd devices
- if len(view_output.splitlines()) < 52:
- raise ValueError(
- 'dasdview output has fewer than 52 lines, cannot parse')
- lines = view_output.splitlines()
- gen_start, gen_end = (2, 6)
- geo_start, geo_end = (8, 12)
- ext_start, ext_end = (14, len(lines))
+def _dasd_format(dasdview_output):
+ """ Read and return specified device "disk_layout" value.
- general_output = lines[gen_start:gen_end]
- geometry_output = lines[geo_start:geo_end]
- extended_output = lines[ext_start:ext_end]
+ :returns: string: One of ['cdl', 'ldl', 'not-formatted'].
+ :raises: ValueError if dasdview result missing 'format' section.
- view = {
- 'general': _parse_output(general_output),
- 'geometry': _parse_output(geometry_output),
- 'extended': _parse_output(extended_output),
+ """
+ if not dasdview_output:
+ return
+
+ mapping = {
+ 'cdl formatted': 'cdl',
+ 'ldl formatted': 'ldl',
+ 'not formatted': 'not-formatted',
}
- return view
+ diskfmt = find_val(DASD_FORMAT, dasdview_output)
+ if diskfmt is not None:
+ return mapping.get(diskfmt.lower())
def _valid_device_id(device_id):
@@ -371,38 +217,9 @@ class CcwDevice(object):
class DasdDevice(CcwDevice):
- def __init__(self, device_id):
- super(DasdDevice, self).__init__(device_id)
- self._kname = None
-
- @property
- def kname(self):
- if not self._kname:
- self._kname = self._get_kname()
- return self._kname
-
- def _get_kname(self):
- """ Return the kernel name of the dasd device. """
- if not self.is_online():
- raise RuntimeError('Cannot determine dasd kname for offline '
- 'device: %s' % self.device_id)
-
- blockdir = self.ccw_device_attr_path('block')
- if not os.path.isdir(blockdir):
- raise RuntimeError('Unexpectedly not a directory: %s' % blockdir)
-
- try:
- knames = os.listdir(blockdir)
- [dasd_kname] = knames
- except ValueError:
- raise RuntimeError('Unexpected os.listdir result at sysfs path '
- '%s: "%s"' % (blockdir, knames))
-
- return dasd_kname
-
@property
def devname(self):
- return '/dev/%s' % self.kname
+ return '/dev/disk/by-path/ccw-%s' % self.device_id
def partition(self, partnumber, partsize, strict=True):
""" Add a partition to this DasdDevice specifying partnumber and size.
@@ -461,42 +278,31 @@ class DasdDevice(CcwDevice):
""" Returns a boolean indicating if the specified device_id is not yet
formatted.
- :param device_id: string of device ccw bus_id.
:returns: boolean: True if the device is not formatted.
"""
return self.ccw_device_attr('status') == "unformatted"
- def is_online(self):
- """ Returns a boolean indicating if specified device is online.
-
- :param device_id: string of device ccw bus_id.
- :returns: boolean: True if device is online.
- """
- return self.ccw_device_attr('online') == "1"
-
def blocksize(self):
""" Read and return device_id's 'blocksize' value.
:param: device_id: string of device ccw bus_id.
:returns: string: the device's current blocksize.
"""
- blkattr = 'block/%s/queue/hw_sector_size' % self.kname
- return self.ccw_device_attr(blkattr)
+ blkattr = 'block/*/queue/hw_sector_size'
+ [path] = glob.glob(self.ccw_device_attr_path(blkattr))
+ return util.load_file(path)
def disk_layout(self):
""" Read and return specified device "disk_layout" value.
:returns: string: One of ['cdl', 'ldl', 'not-formatted'].
:raises: ValueError if dasdview result missing 'format' section.
-
"""
- view = dasdview(self.devname)
- disk_format = view.get('extended', {}).get('format')
- if not disk_format:
+ format = dasd_format(self.devname)
+ if not format:
raise ValueError(
- 'dasdview on %s missing "format" section' % self.devname)
-
- return disk_format.txt
+ 'could not determine format of %s' % self.devname)
+ return format
def label(self):
"""Read and return specified device label (VOLSER) value.
@@ -546,7 +352,7 @@ class DasdDevice(CcwDevice):
@logged_time("DASD.FORMAT")
def format(self, blksize=4096, layout='cdl', force=False, set_label=None,
- keep_label=False, no_label=False, mode='quick', strict=True):
+ keep_label=False, no_label=False, mode='quick'):
""" Format DasdDevice with supplied parameters.
:param blksize: integer value to configure disk block size in bytes.
@@ -572,7 +378,7 @@ class DasdDevice(CcwDevice):
:param strict: boolean which enforces that dasd device exists before
issuing format command, defaults to True.
- :raises: RuntimeError if strict==True and devname does not exist.
+ :raises: RuntimeError if devname does not exist.
:raises: ValueError on invalid blocksize, disk_layout and mode.
:raises: ProcessExecutionError on errors running 'dasdfmt' command.
@@ -580,7 +386,7 @@ class DasdDevice(CcwDevice):
dasdformat -y --blocksize=4096 --disk_layout=cdl \
--mode=quick /dev/dasda
"""
- if strict and not os.path.exists(self.devname):
+ if not os.path.exists(self.devname):
raise RuntimeError("devname '%s' does not exist" % self.devname)
if no_label:
diff --git a/tests/unittests/test_block_dasd.py b/tests/unittests/test_block_dasd.py
index dfd62d3..fffa4a1 100644
--- a/tests/unittests/test_block_dasd.py
+++ b/tests/unittests/test_block_dasd.py
@@ -85,80 +85,18 @@ class TestDasdValidDeviceId(CiTestCase):
dasd.DasdDevice(invalid_dev)
-class TestDasdDeviceIdToKname(CiTestCase):
-
- def setUp(self):
- super(TestDasdDeviceIdToKname, self).setUp()
- self.add_patch('curtin.block.dasd.os.path.isdir', 'm_isdir')
- self.add_patch('curtin.block.dasd.os.listdir', 'm_listdir')
- self.add_patch('curtin.block.dasd.DasdDevice.is_online', 'm_online')
-
- self.dasd = dasd.DasdDevice(random_device_id())
- self.m_online.return_value = True
- self.m_isdir.return_value = True
- self.m_listdir.return_value = [self.random_string()]
-
- def test_device_id_to_kname_returns_kname(self):
- """returns a dasd kname if device_id is valid and online """
- result = self.dasd.kname
- self.assertIsNotNone(result)
- self.assertEqual(result, self.m_listdir.return_value[0])
-
- def test_devid_to_kname_raises_runtimeerror_no_online(self):
- """device_id_to_kname raises RuntimeError on offline devices."""
- self.m_online.return_value = False
- result = None
- with self.assertRaises(RuntimeError):
- result = self.dasd.kname
- self.assertEqual(result, None)
- self.assertEqual(1, self.m_online.call_count)
- self.assertEqual(0, self.m_isdir.call_count)
- self.assertEqual(0, self.m_listdir.call_count)
-
- def test_devid_to_kname_raises_runtimeerror_no_blockpath(self):
- """device_id_to_kname raises RuntimeError on invalid sysfs path."""
- self.m_isdir.return_value = False
- result = None
- with self.assertRaises(RuntimeError):
- result = self.dasd.kname
- self.assertEqual(result, None)
- self.assertEqual(1, self.m_online.call_count)
- self.assertEqual(1, self.m_isdir.call_count)
- self.m_isdir.assert_called_with(
- '/sys/bus/ccw/devices/%s/block' % self.dasd.device_id)
- self.assertEqual(0, self.m_listdir.call_count)
-
- def test_devid_to_kname_raises_runtimeerror_empty_blockdir(self):
- """device_id_to_kname raises RuntimeError on empty blockdir."""
- self.m_listdir.return_value = []
- result = None
- with self.assertRaises(RuntimeError):
- result = self.dasd.kname
- self.assertEqual(result, None)
- self.assertEqual(1, self.m_online.call_count)
- self.assertEqual(1, self.m_isdir.call_count)
- self.m_isdir.assert_called_with(
- '/sys/bus/ccw/devices/%s/block' % self.dasd.device_id)
- self.m_listdir.assert_called_with(
- '/sys/bus/ccw/devices/%s/block' % self.dasd.device_id)
- self.assertEqual(1, self.m_listdir.call_count)
-
-
class TestDasdCcwDeviceAttr(CiTestCase):
def setUp(self):
super(TestDasdCcwDeviceAttr, self).setUp()
self.add_patch('curtin.block.dasd.os.path.isfile', 'm_isfile')
self.add_patch('curtin.block.dasd.util.load_file', 'm_loadfile')
- dpath = 'curtin.block.dasd.DasdDevice'
- self.add_patch(dpath + '.kname', 'm_kname')
+ self.add_patch('curtin.block.dasd.glob.glob', 'm_glob')
# defaults
self.m_isfile.return_value = True
self.m_loadfile.return_value = self.random_string()
self.dasd = dasd.DasdDevice(random_device_id())
- self.kname = self.random_string()
- self.m_kname.return_value = self.kname
def _test_ccw_attr(self, my_attr=None, attr_val_in=None, attr_val=None):
if not my_attr:
@@ -200,60 +138,37 @@ class TestDasdCcwDeviceAttr(CiTestCase):
self.m_loadfile.return_value = self.random_string()
self.assertFalse(self.dasd.is_not_formatted())
- def test_is_online_returns_false_if_not_online(self):
- self.m_loadfile.return_value = self.random_string()
- self.assertFalse(self.dasd.is_online())
-
def test_blocksize(self):
blocksize_val = '%d' % random.choice([512, 1024, 2048, 4096])
+ path = self.random_string()
+ self.m_glob.return_value = [path]
self.m_loadfile.return_value = blocksize_val
self.assertEqual(blocksize_val, self.dasd.blocksize())
+ self.m_loadfile.assert_called_once_with(path)
class TestDiskLayout(CiTestCase):
- layouts = {
- 'not-formatted': dasd.Dasdvalue(0x0, 0, 'not-formatted'),
- 'ldl': dasd.Dasdvalue(0x1, 1, 'ldl'),
- 'cdl': dasd.Dasdvalue(0x2, 2, 'cdl'),
- }
-
def setUp(self):
super(TestDiskLayout, self).setUp()
- self.add_patch('curtin.block.dasd.os.path.exists', 'm_exists')
- self.add_patch('curtin.block.dasd.dasdview', 'm_dasdview')
+ self.add_patch('curtin.block.dasd.dasd_format', 'm_dasd_format')
dpath = 'curtin.block.dasd.DasdDevice'
self.add_patch(dpath + '.devname', 'm_devname')
- # defaults
- self.m_exists.return_value = True
- self.m_dasdview.return_value = self._mkview()
self.dasd = dasd.DasdDevice(random_device_id())
self.devname = self.random_string()
self.m_devname.return_value = self.devname
- @classmethod
- def _mkview(cls, layout=None):
- if not layout:
- layout = random.choice(list(cls.layouts.values()))
- return {'extended': {'format': layout}}
-
- # XXX: Parameterize me
- def test_disk_layout_returns_dasd_extended_format_value(self):
+ def test_disk_layout_returns_dasd_format_result(self):
"""disk_layout returns dasd disk_layout format as string"""
- for my_layout in self.layouts.values():
- self.m_dasdview.return_value = self._mkview(layout=my_layout)
- self.assertEqual(my_layout.txt, self.dasd.disk_layout())
+ expected = self.m_dasd_format.return_value = self.random_string()
+ self.assertEqual(expected, self.dasd.disk_layout())
- # XXX: Parameterize me
- def test_disk_layout_raises_valueerror_on_missing_format_section(self):
+ def test_disk_layout_raises_valueerror_on_missing_format(self):
"""disk_layout raises ValueError if view missing 'format' section."""
- for my_layout in self.layouts.values():
- view = self._mkview(layout=my_layout)
- view['extended']['format'] = None
- self.m_dasdview.return_value = view
- with self.assertRaises(ValueError):
- self.dasd.disk_layout()
+ self.m_dasd_format.return_value = None
+ with self.assertRaises(ValueError):
+ self.dasd.disk_layout()
class TestLabel(CiTestCase):
@@ -287,8 +202,6 @@ class TestLabel(CiTestCase):
class TestNeedsFormatting(CiTestCase):
- blocksizes = [512, 1024, 2048, 4096]
-
def setUp(self):
super(TestNeedsFormatting, self).setUp()
dpath = 'curtin.block.dasd.DasdDevice'
@@ -298,8 +211,10 @@ class TestNeedsFormatting(CiTestCase):
self.add_patch(dpath + '.label', 'm_label')
self.m_not_fmt.return_value = False
- self.m_blocksize.return_value = 4096
- self.m_disk_layout.return_value = TestDiskLayout.layouts['cdl'].txt
+ self.blocksize = 4096
+ self.m_blocksize.return_value = self.blocksize
+ self.disk_layout = self.random_string()
+ self.m_disk_layout.return_value = self.disk_layout
self.label = self.random_string()
self.m_label.return_value = self.label
@@ -308,26 +223,34 @@ class TestNeedsFormatting(CiTestCase):
def test_needs_formatting_label_mismatch(self):
my_label = self.random_string()
self.assertNotEqual(self.label, my_label)
- self.assertTrue(self.dasd.needs_formatting(4096, 'cdl', my_label))
+ self.assertTrue(
+ self.dasd.needs_formatting(
+ self.blocksize, self.disk_layout, my_label))
def test_needs_formatting_layout_mismatch(self):
- my_layout = TestDiskLayout.layouts['ldl'].txt
+ my_layout = self.random_string()
+ self.assertNotEqual(self.disk_layout, my_layout)
self.assertTrue(
- self.dasd.needs_formatting(4096, my_layout, self.label))
+ self.dasd.needs_formatting(
+ self.blocksize, my_layout, self.label))
def test_needs_formatting_blocksize_mismatch(self):
- my_blocksize = random.choice(self.blocksizes[0:3])
+ my_blocksize = random.randrange(self.blocksize)
+ self.assertNotEqual(self.blocksize, my_blocksize)
self.assertTrue(
- self.dasd.needs_formatting(my_blocksize, 'cdl', self.label))
+ self.dasd.needs_formatting(
+ my_blocksize, self.disk_layout, self.label))
def test_needs_formatting_unformatted_disk(self):
self.m_not_fmt.return_value = True
self.assertTrue(
- self.dasd.needs_formatting(4096, 'cdl', self.label))
+ self.dasd.needs_formatting(
+ self.blocksize, self.disk_layout, self.label))
def test_needs_formatting_ignores_label_mismatch(self):
self.assertFalse(
- self.dasd.needs_formatting(4096, 'cdl', None))
+ self.dasd.needs_formatting(
+ self.blocksize, self.disk_layout, None))
class TestFormat(CiTestCase):
@@ -346,10 +269,6 @@ class TestFormat(CiTestCase):
self.devname = self.random_string()
self.m_devname.return_value = self.devname
- def test_format_devname_ignores_path_missing_strict_false(self):
- self.m_exists.return_value = False
- self.dasd.format(strict=False)
-
def test_format_defaults_match_docstring(self):
self.dasd.format()
self.m_subp.assert_called_with(
@@ -454,9 +373,39 @@ class TestDasdInfo(CiTestCase):
dasd.dasdinfo(device_id)
-class TestDasdView(CiTestCase):
+class TestDasdFormat(CiTestCase):
+
+ def setUp(self):
+ super(TestDasdFormat, self).setUp()
+ self.add_patch('curtin.block.dasd.util.subp', 'm_subp')
+ self.add_patch('curtin.block.dasd.os.path.exists', 'm_exists')
+ self.add_patch('curtin.block.dasd._dasd_format', 'm_dasd_format')
+
+ # defaults
+ self.m_exists.return_value = True
+ self.m_subp.return_value = ('', '')
+
+ def test_dasd_format_raise_error_on_invalid_device(self):
+ """dasdview raises error on invalid device path."""
+ devname = self.random_string()
+ self.m_exists.return_value = False
+ with self.assertRaises(ValueError):
+ dasd.dasd_format(devname)
+
+ def test_dasd_foramt_calls__dasd_format(self):
+ """dasdview calls parser on output from dasdview command."""
+ devname = self.random_string()
+ view = self.random_string()
+ self.m_subp.return_value = (view, self.random_string())
+ dasd.dasd_format(devname)
+ self.m_subp.assert_called_with(
+ ['dasdview', '--extended', devname], capture=True)
+ self.m_dasd_format.assert_called_with(view)
+
+
+class Test_DasdFormat(CiTestCase):
- view = textwrap.dedent("""\
+ view_output_template = textwrap.dedent("""\
--- general DASD information ----------------------------------------------
device node : /dev/dasdd
@@ -485,7 +434,7 @@ class TestDasdView(CiTestCase):
FBA_layout : hex 0 dec 0
characteristics_size : hex 40 dec 64
confdata_size : hex 100 dec 256
- format : hex 2 dec 2 CDL formatted
+ format : hex 2 dec 2 {format}
features : hex 0 dec 0 default
characteristics : 3990e933 900c5e0c 39f72032 2721000f
@@ -510,59 +459,15 @@ class TestDasdView(CiTestCase):
81000003 2d001e00 15000247 000c0016
000cc018 935e41ee 00030000 0000a000""")
- view_nondasd = textwrap.dedent("""\
- Error: dasdview: Could not retrieve disk information!
-
- """)
-
- def setUp(self):
- super(TestDasdView, self).setUp()
- self.add_patch('curtin.block.dasd.util.subp', 'm_subp')
- self.add_patch('curtin.block.dasd.os.path.exists', 'm_exists')
- self.add_patch('curtin.block.dasd._parse_dasdview', 'm_parseview')
-
- # defaults
- self.m_exists.return_value = True
- self.m_subp.return_value = ('', '')
-
- def test_dasdview_raise_error_on_invalid_device(self):
- """dasdview raises error on invalid device path."""
- devname = self.random_string()
- self.m_exists.return_value = False
- with self.assertRaises(ValueError):
- dasd.dasdview(devname)
-
- def test_dasdview_calls_parse_dasdview(self):
- """dasdview calls parser on output from dasdview command."""
- devname = self.random_string()
- self.m_subp.return_value = (self.view, self.random_string())
- dasd.dasdview(devname)
- self.m_subp.assert_called_with(
- ['dasdview', '--extended', devname], capture=True)
- self.m_parseview.assert_called_with(self.view)
-
-
-class TestParseDasdView(CiTestCase):
-
- def test_parse_dasdview_no_input(self):
- """_parse_dasdview raises ValueError on invalid status input."""
- for view_output in [None, 123, {}, (), []]:
- with self.assertRaises(ValueError):
- dasd._parse_dasdview(view_output)
-
- def test_parse_dasdview_invalid_strings_short(self):
- """_parse_dasdview raises ValueError on invalid long input."""
- with self.assertRaises(ValueError):
- dasd._parse_dasdview("\n".join([self.random_string()] * 20))
-
- def test_parse_dasdview_returns_dictionary(self):
+ def test__dasd_format_returns_format(self):
"""_parse_dasdview returns dict w/ required keys parsing valid view."""
- result = dasd._parse_dasdview(TestDasdView.view)
- self.assertEqual(dict, type(result))
- self.assertNotEqual({}, result)
- self.assertEqual(3, len(result.keys()))
- for key in result.keys():
- self.assertEqual(dict, type(result[key]))
- self.assertNotEqual(0, len(list(result[key].keys())))
+ for (format, expected) in [
+ ('CDL formatted', 'cdl'),
+ ('LDL formatted', 'ldl'),
+ ('not formatted', 'not-formatted'),
+ ]:
+ result = dasd._dasd_format(
+ self.view_output_template.format(format=format))
+ self.assertEqual(result, expected)
# vi: ts=4 expandtab syntax=python
Follow ups
-
[Merge] ~mwhudson/curtin:pare-down-dasdview-parsing into curtin:master
From: Server Team CI bot, 2020-12-11
-
Re: [Merge] ~mwhudson/curtin:pare-down-dasdview-parsing into curtin:master
From: Server Team CI bot, 2020-12-11
-
[Merge] ~mwhudson/curtin:pare-down-dasdview-parsing into curtin:master
From: Paride Legovini, 2020-12-11
-
[Merge] ~mwhudson/curtin:pare-down-dasdview-parsing into curtin:master
From: Paride Legovini, 2020-12-11
-
[Merge] ~mwhudson/curtin:pare-down-dasdview-parsing into curtin:master
From: Server Team CI bot, 2020-12-11
-
Invalid Commit Message
From: Server Team CI bot, 2020-12-11
-
[Merge] ~mwhudson/curtin:pare-down-dasdview-parsing into curtin:master
From: Michael Hudson-Doyle, 2020-12-11
-
Re: [Merge] ~mwhudson/curtin:pare-down-dasdview-parsing into curtin:master
From: Paride Legovini, 2020-12-10
-
Re: [Merge] ~mwhudson/curtin:pare-down-dasdview-parsing into curtin:master
From: Server Team CI bot, 2020-12-02
-
Re: [Merge] ~mwhudson/curtin:pare-down-dasdview-parsing into curtin:master
From: Michael Hudson-Doyle, 2020-11-25
-
Re: [Merge] ~mwhudson/curtin:pare-down-dasdview-parsing into curtin:master
From: Server Team CI bot, 2020-11-24
-
Re: [Merge] ~mwhudson/curtin:pare-down-dasdview-parsing into curtin:master
From: Paride Legovini, 2020-11-24
-
Re: [Merge] ~mwhudson/curtin:pare-down-dasdview-parsing into curtin:master
From: Dimitri John Ledkov, 2020-11-23
-
Re: [Merge] ~mwhudson/curtin:pare-down-dasdview-parsing into curtin:master
From: Server Team CI bot, 2020-11-23
-
Re: [Merge] ~mwhudson/curtin:pare-down-dasdview-parsing into curtin:master
From: Ryan Harper, 2020-11-22
-
Re: [Merge] ~mwhudson/curtin:pare-down-dasdview-parsing into curtin:master
From: Paride Legovini, 2020-11-20
-
Re: [Merge] ~mwhudson/curtin:pare-down-dasdview-parsing into curtin:master
From: Server Team CI bot, 2020-11-19