Merge ~raharper/curtin:ubuntu/eoan-sru-20200130 into curtin:ubuntu/eoan

Proposed by Ryan Harper
Status: Merged
Merged at revision: 1c2b677876854b6639ae0ff8bdb6eebdf01f35e9
Proposed branch: ~raharper/curtin:ubuntu/eoan-sru-20200130
Merge into: curtin:ubuntu/eoan
Diff against target: 15603 lines (+12330/-488)
87 files modified
HACKING.rst (+3/-4)
curtin/__init__.py (+1/-1)
curtin/block/clear_holders.py (+88/-21)
curtin/block/multipath.py (+74/-2)
curtin/block/schemas.py (+7/-1)
curtin/block/zfs.py (+24/-0)
curtin/commands/block_meta.py (+99/-46)
curtin/commands/curthooks.py (+200/-53)
curtin/commands/install.py (+5/-1)
curtin/distro.py (+25/-2)
curtin/net/deps.py (+3/-3)
curtin/storage_config.py (+105/-20)
curtin/udev.py (+15/-7)
curtin/util.py (+12/-5)
debian/changelog (+63/-0)
debian/control (+1/-1)
doc/topics/config.rst (+6/-1)
doc/topics/storage.rst (+17/-2)
examples/tests/basic-dasd.yaml (+2/-2)
examples/tests/bcache-ceph-nvme-simple.yaml (+107/-0)
examples/tests/bcache-wipe-xfs.yaml (+4/-3)
examples/tests/bridging_network_v2.yaml (+38/-0)
examples/tests/dirty_disks_config.yaml (+9/-1)
examples/tests/network_mtu_networkd.yaml (+93/-0)
examples/tests/reuse-raid-member-partition.yaml (+73/-0)
examples/tests/reuse-raid-member-wipe.yaml (+71/-0)
helpers/common (+84/-13)
tests/data/probert_storage_multipath.json (+1059/-0)
tests/data/probert_storage_raid1_partitions.json (+951/-0)
tests/data/probert_storage_zlp6.json (+6980/-0)
tests/unittests/test_block.py (+26/-0)
tests/unittests/test_block_dasd.py (+1/-1)
tests/unittests/test_block_multipath.py (+87/-6)
tests/unittests/test_block_zfs.py (+26/-0)
tests/unittests/test_clear_holders.py (+131/-11)
tests/unittests/test_commands_block_meta.py (+377/-36)
tests/unittests/test_commands_collect_logs.py (+3/-1)
tests/unittests/test_curthooks.py (+311/-26)
tests/unittests/test_distro.py (+71/-0)
tests/unittests/test_storage_config.py (+114/-9)
tests/unittests/test_udev.py (+15/-14)
tests/unittests/test_util.py (+41/-1)
tests/vmtests/__init__.py (+231/-23)
tests/vmtests/helpers.py (+11/-6)
tests/vmtests/releases.py (+34/-0)
tests/vmtests/test_apt_config_cmd.py (+1/-4)
tests/vmtests/test_basic.py (+71/-81)
tests/vmtests/test_basic_dasd.py (+8/-10)
tests/vmtests/test_bcache_basic.py (+5/-0)
tests/vmtests/test_bcache_bug1718699.py (+5/-0)
tests/vmtests/test_bcache_ceph.py (+31/-0)
tests/vmtests/test_bcache_partitions.py (+5/-0)
tests/vmtests/test_fs_battery.py (+5/-0)
tests/vmtests/test_iscsi.py (+6/-0)
tests/vmtests/test_journald_reporter.py (+5/-4)
tests/vmtests/test_lvm.py (+15/-18)
tests/vmtests/test_lvm_iscsi.py (+5/-0)
tests/vmtests/test_lvm_raid.py (+4/-0)
tests/vmtests/test_lvm_root.py (+16/-1)
tests/vmtests/test_mdadm_bcache.py (+92/-12)
tests/vmtests/test_mdadm_iscsi.py (+5/-0)
tests/vmtests/test_multipath.py (+6/-0)
tests/vmtests/test_network.py (+4/-0)
tests/vmtests/test_network_alias.py (+5/-0)
tests/vmtests/test_network_bonding.py (+4/-0)
tests/vmtests/test_network_bridging.py (+23/-0)
tests/vmtests/test_network_ipv6_static.py (+4/-0)
tests/vmtests/test_network_ipv6_vlan.py (+8/-0)
tests/vmtests/test_network_mtu.py (+42/-10)
tests/vmtests/test_network_static.py (+4/-0)
tests/vmtests/test_network_static_routes.py (+5/-0)
tests/vmtests/test_network_vlan.py (+12/-0)
tests/vmtests/test_nvme.py (+5/-0)
tests/vmtests/test_old_apt_features.py (+3/-2)
tests/vmtests/test_pollinate_useragent.py (+5/-0)
tests/vmtests/test_preserve.py (+5/-0)
tests/vmtests/test_preserve_raid.py (+5/-0)
tests/vmtests/test_raid5_bcache.py (+5/-0)
tests/vmtests/test_reuse_raid_member.py (+63/-0)
tests/vmtests/test_simple.py (+16/-1)
tests/vmtests/test_uefi_basic.py (+11/-1)
tests/vmtests/test_zfsroot.py (+18/-2)
tools/block-discover-to-config (+3/-1)
tools/jenkins-runner (+50/-0)
tools/vmtest-filter (+12/-1)
tools/vmtest-sync-images (+15/-13)
tools/xkvm (+20/-4)
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Needs Fixing
Dan Watkins (community) Approve
Review via email: mp+378355@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Dan Watkins (oddbloke) wrote :

After manually adding the SRU bug number, the ~19.10.1 version suffix and removing all other bug references, I see the same locally. Thanks!

review: Approve
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/HACKING.rst b/HACKING.rst
2index d87552b..7c26a25 100644
3--- a/HACKING.rst
4+++ b/HACKING.rst
5@@ -15,12 +15,11 @@ Do these things once
6 be listed in the `contributor-agreement-canonical`_ group. Unfortunately
7 there is no easy way to check if an organization or company you are doing
8 work for has signed. If you are unsure or have questions, email
9- `Scott Moser <mailto:scott.moser@canonical.com>`_ and
10- `Ryan Harper <mailto:ryan.harper@canonical.com>`_ or ping smoser or rharper
11- in ``#curtin`` channel via Freenode IRC.
12+ `Josh Powers <mailto:josh.powers@canonical.com>` or ping powersj in
13+ ``#curtin`` channel via Freenode IRC.
14
15 When prompted for 'Project contact' or 'Canonical Project Manager' enter
16- 'David Britton'.
17+ 'Josh Powers'.
18
19 * Configure git with your email and name for commit messages.
20
21diff --git a/curtin/__init__.py b/curtin/__init__.py
22index 593231e..142d288 100644
23--- a/curtin/__init__.py
24+++ b/curtin/__init__.py
25@@ -32,6 +32,6 @@ FEATURES = [
26 'HAS_VERSION_MODULE',
27 ]
28
29-__version__ = "19.2"
30+__version__ = "19.3"
31
32 # vi: ts=4 expandtab syntax=python
33diff --git a/curtin/block/clear_holders.py b/curtin/block/clear_holders.py
34index 4a099cd..b691841 100644
35--- a/curtin/block/clear_holders.py
36+++ b/curtin/block/clear_holders.py
37@@ -166,14 +166,27 @@ def shutdown_mdadm(device):
38
39 blockdev = block.sysfs_to_devpath(device)
40
41- LOG.info('Wiping superblock on raid device: %s', device)
42- _wipe_superblock(blockdev, exclusive=False)
43-
44+ LOG.info('Discovering raid devices and spares for %s', device)
45 md_devs = (
46 mdadm.md_get_devices_list(blockdev) +
47 mdadm.md_get_spares_list(blockdev))
48 mdadm.set_sync_action(blockdev, action="idle")
49 mdadm.set_sync_action(blockdev, action="frozen")
50+
51+ LOG.info('Wiping superblock on raid device: %s', device)
52+ try:
53+ _wipe_superblock(blockdev, exclusive=False)
54+ except ValueError as e:
55+ # if the array is not functional, writes to the device may fail
56+ # and _wipe_superblock will raise ValueError for short writes
57+ # which happens on inactive raid volumes. In that case we
58+ # shouldn't give up yet as we still want to disassemble
59+ # array and wipe members. Other errors such as IOError or OSError
60+ # are unwelcome and will stop deployment.
61+ LOG.debug('Non-fatal error writing to array device %s, '
62+ 'proceeding with shutdown: %s', blockdev, e)
63+
64+ LOG.info('Removing raid array members: %s', md_devs)
65 for mddev in md_devs:
66 try:
67 mdadm.fail_device(blockdev, mddev)
68@@ -272,7 +285,26 @@ def wipe_superblock(device):
69 else:
70 bcache._stop_device(stop_path)
71
72- _wipe_superblock(blockdev)
73+ # the blockdev (e.g. /dev/sda2) may be a multipath partition which can
74+ # only be wiped via its device mapper device (e.g. /dev/dm-4)
75+ # check for this and determine the correct device mapper value to use.
76+ mp_dev = None
77+ mp_support = multipath.multipath_supported()
78+ if mp_support:
79+ parent, partnum = block.get_blockdev_for_partition(blockdev)
80+ parent_mpath_id = multipath.find_mpath_id_by_path(parent)
81+ if parent_mpath_id is not None:
82+ # construct multipath dmsetup id
83+ # <mpathid>-part%d -> /dev/dm-1
84+ mp_id, mp_dev = multipath.find_mpath_id_by_parent(parent_mpath_id,
85+ partnum=partnum)
86+ # if we don't find a mapping then the mp partition has already been
87+ # wiped/removed
88+ if mp_dev:
89+ LOG.debug('Found multipath device over %s, wiping holder %s',
90+ blockdev, mp_dev)
91+
92+ _wipe_superblock(mp_dev if mp_dev else blockdev)
93
94 # if we had partitions, make sure they've been removed
95 if partitions:
96@@ -295,16 +327,19 @@ def wipe_superblock(device):
97 device, attempt + 1, len(retries), wait)
98 time.sleep(wait)
99
100- # multipath partitions are separate block devices (disks)
101- if multipath.is_mpath_partition(blockdev):
102- multipath.remove_partition(blockdev)
103- # multipath devices must be hidden to utilize a single member (path)
104- elif multipath.is_mpath_device(blockdev):
105- mp_id = multipath.find_mpath_id(blockdev)
106- if mp_id:
107- multipath.remove_map(mp_id)
108- else:
109- raise RuntimeError('Failed to find multipath id for %s' % blockdev)
110+ if mp_support:
111+ # multipath partitions are separate block devices (disks)
112+ if mp_dev or multipath.is_mpath_partition(blockdev):
113+ multipath.remove_partition(mp_dev if mp_dev else blockdev)
114+ # multipath devices must be hidden to utilize a single member (path)
115+ elif multipath.is_mpath_device(blockdev):
116+ mp_id = multipath.find_mpath_id(blockdev)
117+ multipath.remove_partition(blockdev)
118+ if mp_id:
119+ multipath.remove_map(mp_id)
120+ else:
121+ raise RuntimeError(
122+ 'Failed to find multipath id for %s' % blockdev)
123
124
125 def _wipe_superblock(blockdev, exclusive=True, strict=True):
126@@ -456,25 +491,39 @@ def plan_shutdown_holder_trees(holders_trees):
127 if not isinstance(holders_trees, (list, tuple)):
128 holders_trees = [holders_trees]
129
130+ # sort the trees to ensure we generate a consistent plan
131+ holders_trees = sorted(holders_trees, key=lambda x: x['device'])
132+
133+ def htree_level(tree):
134+ if len(tree['holders']) == 0:
135+ return 0
136+ return 1 + sum(htree_level(holder) for holder in tree['holders'])
137+
138 def flatten_holders_tree(tree, level=0):
139 """
140 add entries from holders tree to registry with level key corresponding
141 to how many layers from raw disks the current device is at
142 """
143 device = tree['device']
144+ device_level = htree_level(tree)
145
146 # always go with highest level if current device has been
147 # encountered already. since the device and everything above it is
148 # re-added to the registry it ensures that any increase of level
149 # required here will propagate down the tree
150 # this handles a scenario like mdadm + bcache, where the backing
151- # device for bcache is a 3nd level item like mdadm, but the cache
152+ # device for bcache is a 3rd level item like mdadm, but the cache
153 # device is 1st level (disk) or second level (partition), ensuring
154 # that the bcache item is always considered higher level than
155 # anything else regardless of whether it was added to the tree via
156 # the cache device or backing device first
157 if device in reg:
158- level = max(reg[device]['level'], level)
159+ level = max(reg[device]['level'], level) + 1
160+
161+ else:
162+ # first time device to registry, assume the larger value of the
163+ # current level or the length of its dependencies.
164+ level = max(device_level, level)
165
166 reg[device] = {'level': level, 'device': device,
167 'dev_type': tree['dev_type']}
168@@ -487,10 +536,26 @@ def plan_shutdown_holder_trees(holders_trees):
169 for holders_tree in holders_trees:
170 flatten_holders_tree(holders_tree)
171
172- # return list of entry dicts with highest level first, then dev_type
173+ def devtype_order(dtype):
174+ """Return the order in which we want to clear device types, higher
175+ value should be cleared first.
176+
177+ :param: dtype: string. A device types name from the holders registry,
178+ see _define_handlers_registry()
179+ :returns: integer
180+ """
181+ dev_type_order = [
182+ 'disk', 'partition', 'bcache', 'lvm', 'raid', 'crypt']
183+ return 1 + dev_type_order.index(dtype)
184+
185+ # return list of entry dicts with greatest htree depth. The 'level' value
186+ # indicates the number of additional devices that are "below" this device.
187+ # Devices must be cleared in descending 'level' value. For devices which
188+ # have the same 'level' value, we sort within the 'level' by devtype order.
189 return [reg[k]
190- for k in sorted(reg, key=lambda x: (reg[x]['level'] * -1,
191- reg[x]['dev_type']))]
192+ for k in sorted(reg, reverse=True,
193+ key=lambda x: (reg[x]['level'],
194+ devtype_order(reg[x]['dev_type'])))]
195
196
197 def format_holders_tree(holders_tree):
198@@ -534,8 +599,10 @@ def assert_clear(base_paths):
199 valid = ('disk', 'partition')
200 if not isinstance(base_paths, (list, tuple)):
201 base_paths = [base_paths]
202- base_paths = [block.sys_block_path(path) for path in base_paths]
203- for holders_tree in [gen_holders_tree(p) for p in base_paths]:
204+ base_paths = [block.sys_block_path(path, strict=False)
205+ for path in base_paths]
206+ for holders_tree in [gen_holders_tree(p)
207+ for p in base_paths if os.path.exists(p)]:
208 if any(holder_type not in valid and path not in base_paths
209 for (holder_type, path) in get_holder_types(holders_tree)):
210 raise OSError('Storage not clear, remaining:\n{}'
211diff --git a/curtin/block/multipath.py b/curtin/block/multipath.py
212index d1e8441..8ce0509 100644
213--- a/curtin/block/multipath.py
214+++ b/curtin/block/multipath.py
215@@ -11,6 +11,7 @@ SHOW_MAPS_FMT = "name=%n multipath='%w' sysfs='%d' paths='%N'"
216
217
218 def _extract_mpath_data(cmd, show_verb):
219+ """ Parse output from specifed command output via load_shell_content."""
220 data, _err = util.subp(cmd, capture=True)
221 result = []
222 for line in data.splitlines():
223@@ -23,16 +24,34 @@ def _extract_mpath_data(cmd, show_verb):
224
225
226 def show_paths():
227+ """ Query multipathd for paths output and return a dict of the values."""
228 cmd = ['multipathd', 'show', 'paths', 'raw', 'format', SHOW_PATHS_FMT]
229 return _extract_mpath_data(cmd, 'paths')
230
231
232 def show_maps():
233+ """ Query multipathd for maps output and return a dict of the values."""
234 cmd = ['multipathd', 'show', 'maps', 'raw', 'format', SHOW_MAPS_FMT]
235 return _extract_mpath_data(cmd, 'maps')
236
237
238+def dmname_to_blkdev_mapping():
239+ """ Use dmsetup ls output to build a dict of DM_NAME, /dev/dm-x values."""
240+ data, _err = util.subp(['dmsetup', 'ls', '-o', 'blkdevname'], capture=True)
241+ mapping = {}
242+ if data and data.strip() != "No devices found":
243+ LOG.debug('multipath: dmsetup ls output:\n%s', data)
244+ for line in data.splitlines():
245+ if line:
246+ dm_name, blkdev = line.split('\t')
247+ # (dm-1) -> /dev/dm-1
248+ mapping[dm_name] = '/dev/' + blkdev.strip('()')
249+
250+ return mapping
251+
252+
253 def is_mpath_device(devpath):
254+ """ Check if devpath is a multipath device, returns boolean. """
255 info = udev.udevadm_info(devpath)
256 if info.get('DM_UUID', '').startswith('mpath-'):
257 return True
258@@ -41,6 +60,7 @@ def is_mpath_device(devpath):
259
260
261 def is_mpath_member(devpath):
262+ """ Check if a device is a multipath member (a path), returns boolean. """
263 try:
264 util.subp(['multipath', '-c', devpath], capture=True)
265 return True
266@@ -49,6 +69,7 @@ def is_mpath_member(devpath):
267
268
269 def is_mpath_partition(devpath):
270+ """ Check if a device is a multipath partition, returns boolean. """
271 if devpath.startswith('/dev/dm-'):
272 if 'DM_PART' in udev.udevadm_info(devpath):
273 LOG.debug("%s is multipath device partition", devpath)
274@@ -58,6 +79,7 @@ def is_mpath_partition(devpath):
275
276
277 def mpath_partition_to_mpath_id(devpath):
278+ """ Return the mpath id of a multipath partition. """
279 info = udev.udevadm_info(devpath)
280 if 'DM_MPATH' in info:
281 return info['DM_MPATH']
282@@ -66,9 +88,10 @@ def mpath_partition_to_mpath_id(devpath):
283
284
285 def remove_partition(devpath, retries=10):
286+ """ Remove a multipath partition mapping. """
287 LOG.debug('multipath: removing multipath partition: %s', devpath)
288 for _ in range(0, retries):
289- util.subp(['dmsetup', 'remove', devpath], rcs=[0, 1])
290+ util.subp(['dmsetup', 'remove', '--force', '--retry', devpath])
291 udev.udevadm_settle()
292 if not os.path.exists(devpath):
293 return
294@@ -77,10 +100,11 @@ def remove_partition(devpath, retries=10):
295
296
297 def remove_map(map_id, retries=10):
298+ """ Remove a multipath device mapping. """
299 LOG.debug('multipath: removing multipath map: %s', map_id)
300 devpath = '/dev/mapper/%s' % map_id
301 for _ in range(0, retries):
302- util.subp(['multipath', '-f', map_id], rcs=[0, 1])
303+ util.subp(['multipath', '-v3', '-R3', '-f', map_id], rcs=[0, 1])
304 udev.udevadm_settle()
305 if not os.path.exists(devpath):
306 return
307@@ -89,6 +113,7 @@ def remove_map(map_id, retries=10):
308
309
310 def find_mpath_members(multipath_id, paths=None):
311+ """ Return a list of device path for each member of aspecified mpath_id."""
312 if not paths:
313 paths = show_paths()
314
315@@ -98,6 +123,7 @@ def find_mpath_members(multipath_id, paths=None):
316
317
318 def find_mpath_id(devpath, maps=None):
319+ """ Return the mpath_id associated with a specified device path. """
320 if not maps:
321 maps = show_maps()
322
323@@ -109,3 +135,49 @@ def find_mpath_id(devpath, maps=None):
324 return mpmap['multipath']
325
326 return None
327+
328+
329+def find_mpath_id_by_path(devpath, paths=None):
330+ """ Return the mpath_id associated with a specified device path. """
331+ if not paths:
332+ paths = show_paths()
333+
334+ for path in paths:
335+ if devpath == '/dev/' + path['device']:
336+ return path['multipath']
337+
338+ return None
339+
340+
341+def find_mpath_id_by_parent(multipath_id, partnum=None):
342+ """ Return the mpath_id associated with a specified device path. """
343+ devmap = dmname_to_blkdev_mapping()
344+ LOG.debug('multipath: dm_name blk map: %s', devmap)
345+ dm_name = multipath_id
346+ if partnum:
347+ dm_name += "-part%d" % int(partnum)
348+
349+ return (dm_name, devmap.get(dm_name))
350+
351+
352+def multipath_supported():
353+ """Return a boolean indicating if multipath is supported."""
354+ try:
355+ multipath_assert_supported()
356+ return True
357+ except RuntimeError:
358+ return False
359+
360+
361+def multipath_assert_supported():
362+ """ Determine if the runtime system supports multipath.
363+ returns: True if system supports multipath
364+ raises: RuntimeError: if system does not support multipath
365+ """
366+ missing_progs = [p for p in ('multipath', 'multipathd')
367+ if not util.which(p)]
368+ if missing_progs:
369+ raise RuntimeError(
370+ "Missing multipath utils: %s" % ','.join(missing_progs))
371+
372+# vi: ts=4 expandtab syntax=python
373diff --git a/curtin/block/schemas.py b/curtin/block/schemas.py
374index f754ccc..fc7e522 100644
375--- a/curtin/block/schemas.py
376+++ b/curtin/block/schemas.py
377@@ -7,6 +7,8 @@ _path_nondev = r'(^/$|^(/[^/]+)+$)'
378 _fstypes = ['btrfs', 'ext2', 'ext3', 'ext4', 'fat', 'fat12', 'fat16', 'fat32',
379 'iso9660', 'vfat', 'jfs', 'ntfs', 'reiserfs', 'swap', 'xfs',
380 'zfsroot']
381+_ptables = ['dos', 'gpt', 'msdos', 'vtoc']
382+_ptable_unsupported = 'unsupported'
383
384 definitions = {
385 'id': {'type': 'string'},
386@@ -14,7 +16,7 @@ definitions = {
387 'devices': {'type': 'array', 'items': {'$ref': '#/definitions/ref_id'}},
388 'name': {'type': 'string'},
389 'preserve': {'type': 'boolean'},
390- 'ptable': {'type': 'string', 'enum': ['dos', 'gpt', 'msdos']},
391+ 'ptable': {'type': 'string', 'enum': _ptables + [_ptable_unsupported]},
392 'size': {'type': ['string', 'number'],
393 'minimum': 1,
394 'pattern': r'^([1-9]\d*(.\d+)?|\d+.\d+)(K|M|G|T)?B?'},
395@@ -119,6 +121,7 @@ DISK = {
396 'properties': {
397 'id': {'$ref': '#/definitions/id'},
398 'name': {'$ref': '#/definitions/name'},
399+ 'multipath': {'type': 'string'},
400 'preserve': {'$ref': '#/definitions/preserve'},
401 'wipe': {'$ref': '#/definitions/wipe'},
402 'type': {'const': 'disk'},
403@@ -265,6 +268,7 @@ PARTITION = {
404 'additionalProperties': False,
405 'properties': {
406 'id': {'$ref': '#/definitions/id'},
407+ 'multipath': {'type': 'string'},
408 'name': {'$ref': '#/definitions/name'},
409 'offset': {'$ref': '#/definitions/size'}, # XXX: This is not used
410 'preserve': {'$ref': '#/definitions/preserve'},
411@@ -296,6 +300,8 @@ RAID = {
412 'devices': {'$ref': '#/definitions/devices'},
413 'name': {'$ref': '#/definitions/name'},
414 'mdname': {'$ref': '#/definitions/name'}, # XXX: Docs need updating
415+ 'metadata': {'type': ['string', 'number']},
416+ 'preserve': {'$ref': '#/definitions/preserve'},
417 'ptable': {'$ref': '#/definitions/ptable'},
418 'spare_devices': {'$ref': '#/definitions/devices'},
419 'type': {'const': 'raid'},
420diff --git a/curtin/block/zfs.py b/curtin/block/zfs.py
421index dce15c3..25751d3 100644
422--- a/curtin/block/zfs.py
423+++ b/curtin/block/zfs.py
424@@ -281,4 +281,28 @@ def device_to_poolname(devname):
425 if vdev_type == 'zfs_member' and label:
426 return label
427
428+
429+def get_zpool_from_config(cfg):
430+ """Parse a curtin storage config and return a list
431+ of zpools that were created.
432+ """
433+ if not cfg:
434+ return []
435+
436+ if 'storage' not in cfg:
437+ return []
438+
439+ zpools = []
440+ sconfig = cfg['storage']['config']
441+ for item in sconfig:
442+ if item['type'] == 'zpool':
443+ zpools.append(item['pool'])
444+ elif item['type'] == 'format':
445+ if item['fstype'] == 'zfsroot':
446+ # curtin.commands.blockmeta sets pool='rpool' for zfsroot
447+ zpools.append('rpool')
448+
449+ return zpools
450+
451+
452 # vi: ts=4 expandtab syntax=python
453diff --git a/curtin/commands/block_meta.py b/curtin/commands/block_meta.py
454index a9110a9..f287bd4 100644
455--- a/curtin/commands/block_meta.py
456+++ b/curtin/commands/block_meta.py
457@@ -2,6 +2,7 @@
458
459 from collections import OrderedDict, namedtuple
460 from curtin import (block, config, paths, util)
461+from curtin.block import schemas
462 from curtin.block import (bcache, clear_holders, dasd, iscsi, lvm, mdadm, mkfs,
463 zfs)
464 from curtin import distro
465@@ -32,6 +33,7 @@ SIMPLE = 'simple'
466 SIMPLE_BOOT = 'simple-boot'
467 CUSTOM = 'custom'
468 BCACHE_REGISTRATION_RETRY = [0.2] * 60
469+PTABLE_UNSUPPORTED = schemas._ptable_unsupported
470
471 CMD_ARGUMENTS = (
472 ((('-D', '--devices'),
473@@ -58,7 +60,7 @@ CMD_ARGUMENTS = (
474 @logged_time("BLOCK_META")
475 def block_meta(args):
476 # main entry point for the block-meta command.
477- state = util.load_command_environment()
478+ state = util.load_command_environment(strict=True)
479 cfg = config.load_command_config(args, state)
480 dd_images = util.get_dd_images(cfg.get('sources', {}))
481
482@@ -67,7 +69,7 @@ def block_meta(args):
483 if devices is None:
484 devices = []
485 if 'storage' in cfg:
486- devices = get_disk_paths_from_storage_config(
487+ devices = get_device_paths_from_storage_config(
488 extract_storage_ordered_dict(cfg))
489 if len(devices) == 0:
490 devices = cfg.get('block-meta', {}).get('devices', [])
491@@ -258,7 +260,7 @@ def make_dname_byid(path, error_msg=None, info=None):
492
493
494 def make_dname(volume, storage_config):
495- state = util.load_command_environment()
496+ state = util.load_command_environment(strict=True)
497 rules_dir = os.path.join(state['scratch'], "rules.d")
498 vol = storage_config.get(volume)
499 path = get_path_to_storage_volume(volume, storage_config)
500@@ -404,9 +406,8 @@ def get_path_to_storage_volume(volume, storage_config):
501 try:
502 if not vol_value:
503 continue
504- if disk_key == 'serial':
505+ if disk_key in ['wwn', 'serial']:
506 volume_path = block.lookup_disk(vol_value)
507- break
508 elif disk_key == 'path':
509 if vol_value.startswith('iscsi:'):
510 i = iscsi.ensure_disk_connected(vol_value)
511@@ -416,21 +417,18 @@ def get_path_to_storage_volume(volume, storage_config):
512 # sys/class/block access is valid. ie, there are no
513 # udev generated values in sysfs
514 volume_path = os.path.realpath(vol_value)
515- break
516- elif disk_key == 'wwn':
517- by_wwn = '/dev/disk/by-id/wwn-%s' % vol.get('wwn')
518- volume_path = os.path.realpath(by_wwn)
519- break
520 elif disk_key == 'device_id':
521 dasd_device = dasd.DasdDevice(vol_value)
522 volume_path = dasd_device.devname
523- break
524 except ValueError:
525- pass
526+ continue
527+ # verify path exists otherwise try the next key
528+ if not os.path.exists(volume_path):
529+ volume_path = None
530
531- if not volume_path:
532- raise ValueError("serial, wwn or path to block dev must be \
533- specified to identify disk")
534+ if volume_path is None:
535+ raise ValueError("Failed to find storage volume id='%s' config: %s"
536+ % (vol['id'], vol))
537
538 elif vol.get('type') == "lvm_partition":
539 # For lvm partitions, a directory in /dev/ should be present with the
540@@ -536,7 +534,7 @@ def disk_handler(info, storage_config):
541
542 if config.value_as_boolean(info.get('preserve')):
543 # Handle preserve flag, verifying if ptable specified in config
544- if config.value_as_boolean(ptable):
545+ if config.value_as_boolean(ptable) and ptable != PTABLE_UNSUPPORTED:
546 current_ptable = block.get_part_table_type(disk)
547 if not ((ptable in _dos_names and current_ptable in _dos_names) or
548 (ptable == 'gpt' and current_ptable == 'gpt')):
549@@ -868,6 +866,47 @@ def mount_data(info, storage_config):
550 spec, path, fstype, ",".join(options), freq, passno, volume_path)
551
552
553+def _get_volume_type(device_path):
554+ lsblock = block._lsblock([device_path])
555+ kname = block.path_to_kname(device_path)
556+ return lsblock[kname]['TYPE']
557+
558+
559+def get_volume_spec(device_path):
560+ """
561+ Return the most reliable spec for a device per Ubuntu FSTAB wiki
562+
563+ https://wiki.ubuntu.com/FSTAB
564+ """
565+ info = udevadm_info(path=device_path)
566+ block_type = _get_volume_type(device_path)
567+
568+ devlinks = []
569+ if 'raid' in block_type:
570+ devlinks = [link for link in info['DEVLINKS']
571+ if os.path.basename(link).startswith('md-uuid-')]
572+ elif block_type in ['crypt', 'lvm', 'mpath']:
573+ devlinks = [link for link in info['DEVLINKS']
574+ if os.path.basename(link).startswith('dm-uuid-')]
575+ elif block_type in ['disk', 'part']:
576+ if device_path.startswith('/dev/bcache'):
577+ devlinks = [link for link in info['DEVLINKS']
578+ if link.startswith('/dev/bcache/by-uuid')]
579+ # on s390x prefer by-path links which are stable and unique.
580+ if platform.machine() == 's390x':
581+ devlinks = [link for link in info['DEVLINKS']
582+ if link.startswith('/dev/disk/by-path')]
583+ if len(devlinks) == 0:
584+ # use FS UUID if present
585+ devlinks = [link for link in info['DEVLINKS']
586+ if '/by-uuid' in link]
587+ if len(devlinks) == 0 and block_type == 'part':
588+ devlinks = [link for link in info['DEVLINKS']
589+ if '/by-partuuid' in link]
590+
591+ return devlinks[0] if len(devlinks) else device_path
592+
593+
594 def fstab_line_for_data(fdata):
595 """Return a string representing fdata in /etc/fstab format.
596
597@@ -883,8 +922,7 @@ def fstab_line_for_data(fdata):
598 if fdata.spec is None:
599 if not fdata.device:
600 raise ValueError("FstabData missing both spec and device.")
601- uuid = block.get_volume_uuid(fdata.device)
602- spec = ("UUID=%s" % uuid) if uuid else fdata.device
603+ spec = get_volume_spec(fdata.device)
604 else:
605 spec = fdata.spec
606
607@@ -896,8 +934,20 @@ def fstab_line_for_data(fdata):
608 else:
609 options = fdata.options
610
611- return ' '.join((spec, path, fdata.fstype, options,
612- fdata.freq, fdata.passno)) + "\n"
613+ if path != "none":
614+ # prefer provided spec over device
615+ device = fdata.spec if fdata.spec else None
616+ # if not provided a spec, derive device from calculated spec value
617+ if not device:
618+ device = fdata.device if fdata.device else spec
619+ comment = "# %s was on %s during curtin installation" % (path, device)
620+ else:
621+ comment = None
622+
623+ entry = ' '.join((spec, path, fdata.fstype, options,
624+ fdata.freq, fdata.passno)) + "\n"
625+ line = '\n'.join([comment, entry] if comment else [entry])
626+ return line
627
628
629 def mount_fstab_data(fdata, target=None):
630@@ -960,7 +1010,7 @@ def mount_handler(info, storage_config):
631 Mount specified device under target at 'path' and generate
632 fstab entry.
633 """
634- state = util.load_command_environment()
635+ state = util.load_command_environment(strict=True)
636 mount_apply(mount_data(info, storage_config),
637 target=state.get('target'), fstab=state.get('fstab'))
638
639@@ -1050,7 +1100,7 @@ def lvm_partition_handler(info, storage_config):
640
641
642 def dm_crypt_handler(info, storage_config):
643- state = util.load_command_environment()
644+ state = util.load_command_environment(strict=True)
645 volume = info.get('volume')
646 keysize = info.get('keysize')
647 cipher = info.get('cipher')
648@@ -1127,11 +1177,11 @@ def dm_crypt_handler(info, storage_config):
649 # A crypttab will be created in the same directory as the fstab in the
650 # configuration. This will then be copied onto the system later
651 if state['fstab']:
652- crypt_tab_location = os.path.join(os.path.split(state['fstab'])[0],
653- "crypttab")
654+ state_dir = os.path.dirname(state['fstab'])
655+ crypt_tab_location = os.path.join(state_dir, "crypttab")
656 uuid = block.get_volume_uuid(volume_path)
657- with open(crypt_tab_location, "a") as fp:
658- fp.write("%s UUID=%s none luks\n" % (dm_name, uuid))
659+ util.write_file(crypt_tab_location,
660+ "%s UUID=%s none luks\n" % (dm_name, uuid), omode="a")
661 else:
662 LOG.info("fstab configuration is not present in environment, so \
663 cannot locate an appropriate directory to write crypttab in \
664@@ -1139,7 +1189,7 @@ def dm_crypt_handler(info, storage_config):
665
666
667 def raid_handler(info, storage_config):
668- state = util.load_command_environment()
669+ state = util.load_command_environment(strict=True)
670 devices = info.get('devices')
671 raidlevel = info.get('raidlevel')
672 spare_devices = info.get('spare_devices')
673@@ -1196,11 +1246,10 @@ def raid_handler(info, storage_config):
674 # The file must also be written onto the running system to enable it to run
675 # mdadm --assemble and continue installation
676 if state['fstab']:
677- mdadm_location = os.path.join(os.path.split(state['fstab'])[0],
678- "mdadm.conf")
679+ state_dir = os.path.dirname(state['fstab'])
680+ mdadm_location = os.path.join(state_dir, "mdadm.conf")
681 mdadm_scan_data = mdadm.mdadm_detail_scan()
682- with open(mdadm_location, "w") as fp:
683- fp.write(mdadm_scan_data)
684+ util.write_file(mdadm_location, mdadm_scan_data)
685 else:
686 LOG.info("fstab configuration is not present in the environment, so \
687 cannot locate an appropriate directory to write mdadm.conf in, \
688@@ -1478,7 +1527,7 @@ def zpool_handler(info, storage_config):
689 """
690 zfs.zfs_assert_supported()
691
692- state = util.load_command_environment()
693+ state = util.load_command_environment(strict=True)
694
695 # extract /dev/disk/by-id paths for each volume used
696 vdevs = [get_path_to_storage_volume(v, storage_config)
697@@ -1517,7 +1566,7 @@ def zfs_handler(info, storage_config):
698 """
699 zfs.zfs_assert_supported()
700
701- state = util.load_command_environment()
702+ state = util.load_command_environment(strict=True)
703 poolname = get_poolname(info, storage_config)
704 volume = info.get('volume')
705 properties = info.get('properties', {})
706@@ -1535,20 +1584,24 @@ def zfs_handler(info, storage_config):
707 util.write_file(state['fstab'], fstab_entry, omode='a')
708
709
710-def get_disk_paths_from_storage_config(storage_config):
711- """Returns a list of disk paths in a storage config filtering out
712- preserved or disks which do not have wipe configuration.
713+def get_device_paths_from_storage_config(storage_config):
714+ """Returns a list of device paths in a storage config filtering out
715+ preserved or devices which do not have wipe configuration.
716
717 :param: storage_config: Ordered dict of storage configation
718 """
719- def get_path_if_present(disk, config):
720- return get_path_to_storage_volume(disk, config)
721-
722- return [get_path_if_present(k, storage_config)
723- for (k, v) in storage_config.items()
724- if v.get('type') == 'disk' and
725- config.value_as_boolean(v.get('wipe')) and
726- not config.value_as_boolean(v.get('preserve'))]
727+ dpaths = []
728+ for (k, v) in storage_config.items():
729+ if v.get('type') in ['disk', 'partition']:
730+ if config.value_as_boolean(v.get('wipe')):
731+ if config.value_as_boolean(v.get('preserve')):
732+ continue
733+ try:
734+ dpaths.append(
735+ get_path_to_storage_volume(k, storage_config))
736+ except Exception:
737+ pass
738+ return dpaths
739
740
741 def zfsroot_update_storage_config(storage_config):
742@@ -1685,7 +1738,7 @@ def meta_custom(args):
743 'zpool': zpool_handler,
744 }
745
746- state = util.load_command_environment()
747+ state = util.load_command_environment(strict=True)
748 cfg = config.load_command_config(args, state)
749
750 storage_config_dict = extract_storage_ordered_dict(cfg)
751@@ -1719,7 +1772,7 @@ def meta_simple(args):
752 """Creates a root partition. If args.mode == SIMPLE_BOOT, it will also
753 create a separate /boot partition.
754 """
755- state = util.load_command_environment()
756+ state = util.load_command_environment(strict=True)
757 cfg = config.load_command_config(args, state)
758 if args.target is not None:
759 state['target'] = args.target
760diff --git a/curtin/commands/curthooks.py b/curtin/commands/curthooks.py
761index 2869c6c..542557c 100644
762--- a/curtin/commands/curthooks.py
763+++ b/curtin/commands/curthooks.py
764@@ -104,6 +104,68 @@ def disable_overlayroot(cfg, target):
765 shutil.move(local_conf, local_conf + ".old")
766
767
768+def _update_initramfs_tools(machine=None):
769+ """ Return a list of binary names used to update an initramfs.
770+
771+ On some architectures there are helper binaries that are also
772+ used and will be included in the list.
773+ """
774+ tools = ['update-initramfs']
775+ if not machine:
776+ machine = platform.machine()
777+ if machine == 's390x':
778+ tools.append('zipl')
779+ elif machine == 'aarch64':
780+ tools.append('flash-kernel')
781+ return tools
782+
783+
784+def disable_update_initramfs(cfg, target, machine=None):
785+ """ Find update-initramfs tools in target and change their name. """
786+ with util.ChrootableTarget(target) as in_chroot:
787+ for tool in _update_initramfs_tools(machine=machine):
788+ found = util.which(tool, target=target)
789+ if found:
790+ LOG.debug('Diverting original %s in target.', tool)
791+ rename = found + '.curtin-disabled'
792+ divert = ['dpkg-divert', '--add', '--rename',
793+ '--divert', rename, found]
794+ in_chroot.subp(divert)
795+
796+ # create a dummy update-initramfs which just returns true;
797+ # this handles postinstall scripts which make invoke $tool
798+ # directly
799+ util.write_file(target + found,
800+ content="#!/bin/true\n# diverted by curtin",
801+ mode=0o755)
802+
803+
804+def update_initramfs_is_disabled(target):
805+ """ Return a bool indicating if initramfs tooling is disabled. """
806+ disabled = []
807+ with util.ChrootableTarget(target) as in_chroot:
808+ out, _err = in_chroot.subp(['dpkg-divert', '--list'], capture=True)
809+ disabled = [divert for divert in out.splitlines()
810+ if divert.endswith('.curtin-disabled')]
811+ return len(disabled) > 0
812+
813+
814+def enable_update_initramfs(cfg, target, machine=None):
815+ """ Enable initramfs update tools by restoring their original name. """
816+ if update_initramfs_is_disabled(target):
817+ with util.ChrootableTarget(target) as in_chroot:
818+ for tool in _update_initramfs_tools(machine=machine):
819+ LOG.info('Restoring %s in target for initrd updates.', tool)
820+ found = util.which(tool, target=target)
821+ if not found:
822+ continue
823+ # remove the diverted
824+ util.del_file(target + found)
825+ # un-divert and restore original file
826+ in_chroot.subp(
827+ ['dpkg-divert', '--rename', '--remove', found])
828+
829+
830 def setup_zipl(cfg, target):
831 if platform.machine() != 's390x':
832 return
833@@ -262,6 +324,11 @@ def get_flash_kernel_pkgs(arch=None, uefi=None):
834
835
836 def setup_kernel_img_conf(target):
837+ # kernel-img.conf only needed on release prior to 19.10
838+ lsb_info = distro.lsb_release(target=target)
839+ if tuple(map(int, lsb_info['release'].split('.'))) >= (19, 10):
840+ return
841+
842 kernel_img_conf_vars = {
843 'bootloader': 'no',
844 'inboot': 'yes',
845@@ -420,12 +487,25 @@ def setup_grub(cfg, target, osfamily=DISTROS.debian):
846
847 if storage_cfg_odict:
848 storage_grub_devices = []
849- for item_id, item in storage_cfg_odict.items():
850- if not item.get('grub_device'):
851- continue
852- LOG.debug("checking: %s", item)
853- storage_grub_devices.append(
854- get_path_to_storage_volume(item_id, storage_cfg_odict))
855+ if util.is_uefi_bootable():
856+ # Curtin only supports creating one EFI system partition. Thus the
857+ # grub_device can only be the default system partition mounted at
858+ # /boot/efi.
859+ for item_id, item in storage_cfg_odict.items():
860+ if item.get('path') == '/boot/efi':
861+ efi_dev_id = storage_cfg_odict[item['device']]['volume']
862+ LOG.debug("checking: %s", item)
863+ storage_grub_devices.append(get_path_to_storage_volume(
864+ efi_dev_id, storage_cfg_odict))
865+ break
866+ else:
867+ for item_id, item in storage_cfg_odict.items():
868+ if not item.get('grub_device'):
869+ continue
870+ LOG.debug("checking: %s", item)
871+ storage_grub_devices.append(
872+ get_path_to_storage_volume(item_id, storage_cfg_odict))
873+
874 if len(storage_grub_devices) > 0:
875 grubcfg['install_devices'] = storage_grub_devices
876
877@@ -509,10 +589,7 @@ def setup_grub(cfg, target, osfamily=DISTROS.debian):
878 LOG.debug("installing grub to %s [replace_default=%s]",
879 instdevs, replace_default)
880
881- # rhel lvm uses /run during grub configuration
882- chroot_mounts = (["/dev", "/proc", "/sys", "/run"]
883- if osfamily == DISTROS.redhat else None)
884- with util.ChrootableTarget(target, mounts=chroot_mounts):
885+ with util.ChrootableTarget(target):
886 args = ['install-grub']
887 if util.is_uefi_bootable():
888 args.append("--uefi")
889@@ -529,18 +606,66 @@ def setup_grub(cfg, target, osfamily=DISTROS.debian):
890 join_stdout_err = ['sh', '-c', 'exec "$0" "$@" 2>&1']
891 out, _err = util.subp(
892 join_stdout_err + args + instdevs, env=env, capture=True)
893- LOG.debug("%s\n%s\n", args, out)
894+ LOG.debug("%s\n%s\n", args + instdevs, out)
895
896 if util.is_uefi_bootable() and grubcfg.get('update_nvram', True):
897 uefi_reorder_loaders(grubcfg, target)
898
899
900 def update_initramfs(target=None, all_kernels=False):
901- cmd = ['update-initramfs', '-u']
902- if all_kernels:
903- cmd.extend(['-k', 'all'])
904- with util.ChrootableTarget(target) as in_chroot:
905- in_chroot.subp(cmd)
906+ """ Invoke update-initramfs in the target path.
907+
908+ Look up the installed kernel versions in the target
909+ to ensure that an initrd get created or updated as needed.
910+ This allows curtin to invoke update-initramfs exactly once
911+ at the end of the install instead of multiple calls.
912+ """
913+ if update_initramfs_is_disabled(target):
914+ return
915+
916+ # We keep the all_kernels flag for callers, the implementation
917+ # now will operate correctly on all kernels present in the image
918+ # which is almost always exactly one.
919+ #
920+ # Ideally curtin should be able to use update-initramfs -k all
921+ # however, update-initramfs expects to be able to find out which
922+ # versions of kernels are installed by using values from the
923+ # kernel package invoking update-initramfs -c <kernel version>.
924+ # With update-initramfs diverted, nothing captures the kernel
925+ # version strings in the place where update-initramfs expects
926+ # to find this information. Instead, curtin will examine
927+ # /boot to see what kernels and initramfs are installed and
928+ # either create or update as needed.
929+ #
930+ # This loop below will examine the contents of target's
931+ # /boot and pattern match for kernel files. On Ubuntu this
932+ # is in the form of /boot/vmlinu[xz]-<uname -r version>.
933+ #
934+ # For each kernel, we extract the version string and then
935+ # construct the name of of the initrd file that *would*
936+ # have been created when the kernel package was installed
937+ # if curtin had not diverted update-initramfs to prevent
938+ # duplicate initrd creation.
939+ #
940+ # if the initrd file exists, then we only need to invoke
941+ # update-initramfs's -u (update) method. If the file does
942+ # not exist, then we need to run the -c (create) method.
943+ boot = paths.target_path(target, 'boot')
944+ for kernel in sorted(glob.glob(boot + '/vmlinu*-*')):
945+ kfile = os.path.basename(kernel)
946+ # handle vmlinux or vmlinuz
947+ kprefix = kfile.split('-')[0]
948+ version = kfile.replace(kprefix + '-', '')
949+ initrd = kernel.replace(kprefix, 'initrd.img')
950+ # -u == update, -c == create
951+ mode = '-u' if os.path.exists(initrd) else '-c'
952+ cmd = ['update-initramfs', mode, '-k', version]
953+ with util.ChrootableTarget(target) as in_chroot:
954+ in_chroot.subp(cmd)
955+ if not os.path.exists(initrd):
956+ files = os.listdir(target + '/boot')
957+ LOG.debug('Failed to find initrd %s', initrd)
958+ LOG.debug('Files in target /boot: %s', files)
959
960
961 def copy_fstab(fstab, target):
962@@ -548,7 +673,10 @@ def copy_fstab(fstab, target):
963 LOG.warn("fstab variable not in state, not copying fstab")
964 return
965
966- shutil.copy(fstab, os.path.sep.join([target, 'etc/fstab']))
967+ content = util.load_file(fstab)
968+ header = distro.fstab_header()
969+ util.write_file(os.path.sep.join([target, 'etc/fstab']),
970+ content="%s\n%s" % (header, content))
971
972
973 def copy_crypttab(crypttab, target):
974@@ -884,12 +1012,21 @@ def install_missing_packages(cfg, target, osfamily=DISTROS.debian):
975 # UEFI requires grub-efi-{arch}. If a signed version of that package
976 # exists then it will be installed.
977 if util.is_uefi_bootable():
978- uefi_pkgs = []
979+ uefi_pkgs = ['efibootmgr']
980 if osfamily == DISTROS.redhat:
981 # centos/redhat doesn't support 32-bit?
982- uefi_pkgs.extend(['grub2-efi-x64-modules'])
983+ if 'grub2-efi-x64-modules' not in installed_packages:
984+ # Previously Curtin only supported unsigned GRUB due to an
985+ # upstream bug. By default lp:maas-image-builder and
986+ # packer-maas have grub preinstalled. If grub2-efi-x64-modules
987+ # is already in the image use unsigned grub so the install
988+ # doesn't require Internet access. If grub is missing use the
989+ # signed version.
990+ uefi_pkgs.extend(['grub2-efi-x64', 'shim-x64'])
991 elif osfamily == DISTROS.debian:
992 arch = util.get_architecture()
993+ if arch == 'i386':
994+ arch = 'ia32'
995 uefi_pkgs.append('grub-efi-%s' % arch)
996
997 # Architecture might support a signed UEFI loader
998@@ -1165,40 +1302,43 @@ def redhat_upgrade_cloud_init(netcfg, target=None, osfamily=DISTROS.redhat):
999 cloud_init_yum_repo = (
1000 paths.target_path(target,
1001 'etc/yum.repos.d/curtin-cloud-init.repo'))
1002+ rhel_ver = distro.rpm_get_dist_id(target)
1003 # Inject cloud-init daily yum repo
1004 util.write_file(cloud_init_yum_repo,
1005- content=cloud_init_repo(
1006- distro.rpm_get_dist_id(target)))
1007+ content=cloud_init_repo(rhel_ver))
1008
1009- # we separate the installation of repository packages (epel,
1010+ # ensure up-to-date ca-certificates to handle https mirror
1011+ # connections for epel and cloud-init-el.
1012+ packages = ['ca-certificates']
1013+
1014+ if int(rhel_ver) < 8:
1015+ # cloud-init in RHEL < 8 requires EPEL for dependencies.
1016+ packages += ['epel-release']
1017+ # RHEL8+ no longer ships bridge-utils. This does not effect
1018+ # bridge configuration. Only install on RHEL < 8 if not
1019+ # available, do not upgrade.
1020+ with util.ChrootableTarget(target) as in_chroot:
1021+ try:
1022+ in_chroot.subp(['rpm', '-q', 'bridge-utils'],
1023+ capture=False, rcs=[0])
1024+ except util.ProcessExecutionError:
1025+ LOG.debug(
1026+ 'Image missing bridge-utils package, installing')
1027+ packages += ['bridge-utils']
1028+
1029+ packages += ['cloud-init-el-release', 'cloud-init']
1030+
1031+ # We separate the installation of repository packages (epel,
1032 # cloud-init-el-release) as we need a new invocation of yum
1033 # to read the newly installed repo files.
1034-
1035- # ensure up-to-date ca-certificates to handle https mirror
1036- # connections
1037- distro.install_packages(['ca-certificates'], target=target,
1038- osfamily=osfamily)
1039- distro.install_packages(['epel-release'], target=target,
1040- osfamily=osfamily)
1041- distro.install_packages(['cloud-init-el-release'], target=target,
1042- osfamily=osfamily)
1043- distro.install_packages(['cloud-init'], target=target,
1044- osfamily=osfamily)
1045+ for package in packages:
1046+ distro.install_packages(
1047+ [package], target=target, osfamily=osfamily)
1048
1049 # remove cloud-init el-stable bootstrap repo config as the
1050 # cloud-init-el-release package points to the correct repo
1051 util.del_file(cloud_init_yum_repo)
1052
1053- # install bridge-utils if needed
1054- with util.ChrootableTarget(target) as in_chroot:
1055- try:
1056- in_chroot.subp(['rpm', '-q', 'bridge-utils'],
1057- capture=False, rcs=[0])
1058- except util.ProcessExecutionError:
1059- LOG.debug('Image missing bridge-utils package, installing')
1060- distro.install_packages(['bridge-utils'], target=target,
1061- osfamily=osfamily)
1062-
1063 LOG.info('Passing network configuration through to target')
1064 net.render_netconfig_passthrough(target, netconfig={'network': netcfg})
1065
1066@@ -1277,6 +1417,7 @@ def builtin_curthooks(cfg, target, state):
1067 LOG.info('Running curtin builtin curthooks')
1068 stack_prefix = state.get('report_stack_prefix', '')
1069 state_etcd = os.path.split(state['fstab'])[0]
1070+ machine = platform.machine()
1071
1072 distro_info = distro.get_distroinfo(target=target)
1073 if not distro_info:
1074@@ -1291,6 +1432,7 @@ def builtin_curthooks(cfg, target, state):
1075 description="configuring apt configuring apt"):
1076 do_apt_config(cfg, target)
1077 disable_overlayroot(cfg, target)
1078+ disable_update_initramfs(cfg, target, machine)
1079
1080 # LP: #1742560 prevent zfs-dkms from being installed (Xenial)
1081 if distro.lsb_release(target=target)['codename'] == 'xenial':
1082@@ -1383,12 +1525,6 @@ def builtin_curthooks(cfg, target, state):
1083 description="enabling selinux autorelabel mode"):
1084 redhat_apply_selinux_autorelabel(target)
1085
1086- with events.ReportEventStack(
1087- name=stack_prefix + '/updating-initramfs-configuration',
1088- reporting_enabled=True, level="INFO",
1089- description="updating initramfs configuration"):
1090- redhat_update_initramfs(target, cfg)
1091-
1092 with events.ReportEventStack(
1093 name=stack_prefix + '/pollinate-user-agent',
1094 reporting_enabled=True, level="INFO",
1095@@ -1424,17 +1560,28 @@ def builtin_curthooks(cfg, target, state):
1096 if os.path.isdir(udev_rules_d):
1097 copy_dname_rules(udev_rules_d, target)
1098
1099+ with events.ReportEventStack(
1100+ name=stack_prefix + '/updating-initramfs-configuration',
1101+ reporting_enabled=True, level="INFO",
1102+ description="updating initramfs configuration"):
1103+ if osfamily == DISTROS.debian:
1104+ # re-enable update_initramfs
1105+ enable_update_initramfs(cfg, target, machine)
1106+ update_initramfs(target, all_kernels=True)
1107+ elif osfamily == DISTROS.redhat:
1108+ redhat_update_initramfs(target, cfg)
1109+
1110 # As a rule, ARMv7 systems don't use grub. This may change some
1111 # day, but for now, assume no. They do require the initramfs
1112 # to be updated, and this also triggers boot loader setup via
1113 # flash-kernel.
1114- machine = platform.machine()
1115 if (machine.startswith('armv7') or
1116 machine.startswith('s390x') or
1117 machine.startswith('aarch64') and not util.is_uefi_bootable()):
1118- update_initramfs(target)
1119- else:
1120- setup_grub(cfg, target, osfamily=osfamily)
1121+ return
1122+
1123+ # all other paths lead to grub
1124+ setup_grub(cfg, target, osfamily=osfamily)
1125
1126
1127 def curthooks(args):
1128diff --git a/curtin/commands/install.py b/curtin/commands/install.py
1129index ad17508..a3471f6 100644
1130--- a/curtin/commands/install.py
1131+++ b/curtin/commands/install.py
1132@@ -11,7 +11,7 @@ import subprocess
1133 import sys
1134 import tempfile
1135
1136-from curtin.block import iscsi
1137+from curtin.block import iscsi, zfs
1138 from curtin import config
1139 from curtin import distro
1140 from curtin import util
1141@@ -505,6 +505,10 @@ def cmd_install(args):
1142 if iscsi.get_iscsi_disks_from_config(cfg):
1143 iscsi.restart_iscsi_service()
1144
1145+ for pool in zfs.get_zpool_from_config(cfg):
1146+ LOG.debug('Exporting ZFS zpool %s', pool)
1147+ zfs.zpool_export(pool)
1148+
1149 shutil.rmtree(workingd.top)
1150
1151 apply_power_state(cfg.get('power_state'))
1152diff --git a/curtin/distro.py b/curtin/distro.py
1153index 9714515..ed178bd 100644
1154--- a/curtin/distro.py
1155+++ b/curtin/distro.py
1156@@ -5,6 +5,7 @@ import os
1157 import re
1158 import shutil
1159 import tempfile
1160+import textwrap
1161
1162 from .paths import target_path
1163 from .util import (
1164@@ -284,7 +285,13 @@ def run_yum_command(mode, args=None, opts=None, env=None, target=None,
1165 if opts is None:
1166 opts = []
1167
1168- cmd = ['yum'] + defopts + opts + [mode] + args
1169+ # dnf is a drop in replacement for yum. On newer RH based systems yum
1170+ # is just a sym link to dnf.
1171+ if which('dnf', target=target):
1172+ cmd = ['dnf']
1173+ else:
1174+ cmd = ['yum']
1175+ cmd += defopts + opts + [mode] + args
1176 if not execute:
1177 return env, cmd
1178
1179@@ -311,8 +318,14 @@ def yum_install(mode, packages=None, opts=None, env=None, target=None,
1180 raise ValueError(
1181 'Unsupported mode "%s" for yum package install/upgrade' % mode)
1182
1183+ # dnf is a drop in replacement for yum. On newer RH based systems yum
1184+ # is just a sym link to dnf.
1185+ if which('dnf', target=target):
1186+ cmd = ['dnf']
1187+ else:
1188+ cmd = ['yum']
1189 # download first, then install/upgrade from cache
1190- cmd = ['yum'] + defopts + opts + [mode]
1191+ cmd += defopts + opts + [mode]
1192 dl_opts = ['--downloadonly', '--setopt=keepcache=1']
1193 inst_opts = ['--cacheonly']
1194
1195@@ -509,4 +522,14 @@ def get_package_version(pkg, target=None, semx=None):
1196 return None
1197
1198
1199+def fstab_header():
1200+ return textwrap.dedent("""\
1201+# /etc/fstab: static file system information.
1202+#
1203+# Use 'blkid' to print the universally unique identifier for a
1204+# device; this may be used with UUID= as a more robust way to name devices
1205+# that works even if disks are added and removed. See fstab(5).
1206+#
1207+# <file system> <mount point> <type> <options> <dump> <pass>""")
1208+
1209 # vi: ts=4 expandtab syntax=python
1210diff --git a/curtin/net/deps.py b/curtin/net/deps.py
1211index b98961d..cbebae9 100644
1212--- a/curtin/net/deps.py
1213+++ b/curtin/net/deps.py
1214@@ -47,11 +47,11 @@ def detect_required_packages_mapping(osfamily=DISTROS.debian):
1215 distro_mapping = {
1216 DISTROS.debian: {
1217 'bond': ['ifenslave'],
1218- 'bonds': [],
1219+ 'bonds': ['ifenslave'],
1220 'bridge': ['bridge-utils'],
1221- 'bridges': [],
1222+ 'bridges': ['bridge-utils'],
1223 'vlan': ['vlan'],
1224- 'vlans': []},
1225+ 'vlans': ['vlan']},
1226 DISTROS.redhat: {
1227 'bond': [],
1228 'bonds': [],
1229diff --git a/curtin/storage_config.py b/curtin/storage_config.py
1230index 841d868..4244b3e 100644
1231--- a/curtin/storage_config.py
1232+++ b/curtin/storage_config.py
1233@@ -304,7 +304,8 @@ def merge_config_trees_to_list(config_trees):
1234 max_level = level
1235 item_cfg = tree[top_item_id]
1236 if top_item_id in reg:
1237- raise ValueError('Duplicate id: %s' % top_item_id)
1238+ LOG.warning('Dropping Duplicate id: %s' % top_item_id)
1239+ continue
1240 reg[top_item_id] = {'level': level, 'config': item_cfg}
1241
1242 def sort_level(configs):
1243@@ -388,15 +389,15 @@ class ProbertParser(object):
1244 data = {}
1245 self.class_data = data
1246 else:
1247- raise ValueError('probe_data missing %s data' %
1248- self.probe_data_key)
1249+ LOG.warning('probe_data missing %s data', self.probe_data_key)
1250+ self.class_data = {}
1251
1252 # We keep a reference to the blockdev_data on the superclass
1253 # as each specific parser has common needs to reference
1254 # this data separate from the BlockdevParser class.
1255- self.blockdev_data = self.probe_data.get('blockdev')
1256+ self.blockdev_data = self.probe_data.get('blockdev', {})
1257 if not self.blockdev_data:
1258- raise ValueError('probe_data missing valid "blockdev" data')
1259+ LOG.warning('probe_data missing valid "blockdev" data')
1260
1261 def parse(self):
1262 raise NotImplementedError()
1263@@ -420,14 +421,76 @@ class ProbertParser(object):
1264
1265 return None
1266
1267+ def is_mpath(self, blockdev):
1268+ if blockdev.get('DM_MULTIPATH_DEVICE_PATH') == "1":
1269+ return True
1270+
1271+ return bool('mpath-' in blockdev.get('DM_UUID', ''))
1272+
1273+ def get_mpath_name(self, blockdev):
1274+ mpath_data = self.probe_data.get('multipath')
1275+ if not mpath_data:
1276+ return None
1277+
1278+ bd_name = blockdev['DEVNAME']
1279+ if blockdev['DEVTYPE'] == 'partition':
1280+ bd_name = self.partition_parent_devname(blockdev)
1281+ bd_name = os.path.basename(bd_name)
1282+ for path in mpath_data['paths']:
1283+ if bd_name == path['device']:
1284+ rv = path['multipath']
1285+ return rv
1286+
1287+ def find_mpath_member(self, blockdev):
1288+ if blockdev.get('DM_MULTIPATH_DEVICE_PATH') == "1":
1289+ # find all other DM_MULTIPATH_DEVICE_PATH devs with same serial
1290+ serial = blockdev.get('ID_SERIAL')
1291+ members = sorted([os.path.basename(dev['DEVNAME'])
1292+ for dev in self.blockdev_data.values()
1293+ if dev.get("ID_SERIAL", "") == serial and
1294+ dev['DEVTYPE'] == blockdev['DEVTYPE']])
1295+ # [/dev/sda, /dev/sdb]
1296+ # [/dev/sda1, /dev/sda2, /dev/sdb1, /dev/sdb2]
1297+
1298+ else:
1299+ dm_mpath = blockdev.get('DM_MPATH')
1300+ dm_uuid = blockdev.get('DM_UUID')
1301+ dm_part = blockdev.get('DM_PART')
1302+
1303+ if dm_mpath:
1304+ multipath = dm_mpath
1305+ else:
1306+ # part1-mpath-30000000000000064
1307+ # mpath-30000000000000064
1308+ # mpath-36005076306ffd6b60000000000002406
1309+ match = re.search(r'mpath\-([a-zA-Z]*|\d*)+$', dm_uuid)
1310+ if not match:
1311+ LOG.debug('Failed to extract multipath ID pattern from '
1312+ 'DM_UUID value: "%s"', dm_uuid)
1313+ return None
1314+ # remove leading 'mpath-'
1315+ multipath = match.group(0)[6:]
1316+ mpath_data = self.probe_data.get('multipath')
1317+ if not mpath_data:
1318+ return None
1319+ members = sorted([path['device'] for path in mpath_data['paths']
1320+ if path['multipath'] == multipath])
1321+
1322+ # append partition number if present
1323+ if dm_part:
1324+ members = [member + dm_part for member in members]
1325+
1326+ if len(members):
1327+ return members[0]
1328+
1329+ return None
1330+
1331 def blockdev_to_id(self, blockdev):
1332 """ Examine a blockdev dictionary and return a tuple of curtin
1333 storage type and name that can be used as a value for
1334 storage_config ids (opaque reference to other storage_config
1335 elements).
1336 """
1337- def is_mpath(blockdev):
1338- return bool(blockdev.get('DM_UUID', '').startswith('mpath-'))
1339
1340 def is_dmcrypt(blockdev):
1341 return bool(blockdev.get('DM_UUID', '').startswith('CRYPT-LUKS'))
1342@@ -441,8 +504,15 @@ class ProbertParser(object):
1343 if 'DM_LV_NAME' in blockdev:
1344 devtype = 'lvm-partition'
1345 name = blockdev['DM_LV_NAME']
1346- elif is_mpath(blockdev):
1347- name = blockdev['DM_UUID']
1348+ elif self.is_mpath(blockdev):
1349+ # extract a multipath member device
1350+ member = self.find_mpath_member(blockdev)
1351+ if member:
1352+ name = member
1353+ else:
1354+ name = blockdev['DM_UUID']
1355+ if 'DM_PART' in blockdev:
1356+ devtype = 'partition'
1357 elif is_dmcrypt(blockdev):
1358 devtype = 'dmcrypt'
1359 name = blockdev['DM_NAME']
1360@@ -505,7 +575,8 @@ class BcacheParser(ProbertParser):
1361 msg = ('Invalid "blockdev" value for cache device '
1362 'uuid=%s' % cset_uuid)
1363 if not cset_uuid:
1364- raise ValueError(msg)
1365+ LOG.warning(msg)
1366+ return None
1367
1368 for devuuid, config in cache_data.items():
1369 cache = _sb_get(config, 'cset.uuid')
1370@@ -518,6 +589,8 @@ class BcacheParser(ProbertParser):
1371 by_uuid = '/dev/bcache/by-uuid/' + uuid
1372 label = _sb_get(backing_data, 'dev.label')
1373 for devname, data in blockdev_data.items():
1374+ if not devname:
1375+ continue
1376 if devname.startswith('/dev/bcache'):
1377 # DEVLINKS is a space separated list
1378 devlinks = data.get('DEVLINKS', '').split()
1379@@ -525,7 +598,7 @@ class BcacheParser(ProbertParser):
1380 return devname
1381 if label:
1382 return label
1383- raise ValueError('Failed to find bcache %s ' % (by_uuid))
1384+ LOG.warning('Failed to find bcache %s ' % (by_uuid))
1385
1386 def _cache_mode(dev_data):
1387 # "1 [writeback]" -> "writeback"
1388@@ -535,12 +608,14 @@ class BcacheParser(ProbertParser):
1389
1390 return None
1391
1392+ if not self.blockdev_data:
1393+ return None
1394+
1395 backing_device = backing_data.get('blockdev')
1396 cache_device = _find_cache_device(backing_data, self.caching)
1397 cache_mode = _cache_mode(backing_data)
1398- bcache_name = os.path.basename(
1399- _find_bcache_devname(backing_uuid, backing_data,
1400- self.blockdev_data))
1401+ bcache_name = os.path.basename(_find_bcache_devname(backing_uuid,
1402+ backing_data, self.blockdev_data))
1403 bcache_entry = {'type': 'bcache', 'id': 'disk-%s' % bcache_name,
1404 'name': bcache_name}
1405
1406@@ -571,9 +646,10 @@ class BlockdevParser(ProbertParser):
1407 errors = []
1408
1409 for devname, data in self.blockdev_data.items():
1410- # skip composed devices here
1411+ # skip composed devices here, except partitions
1412 if data.get('DEVPATH', '').startswith('/devices/virtual'):
1413- continue
1414+ if data.get('DEVTYPE', '') != "partition":
1415+ continue
1416 entry = self.asdict(data)
1417 if entry:
1418 try:
1419@@ -660,6 +736,9 @@ class BlockdevParser(ProbertParser):
1420 'type': blockdev_data['DEVTYPE'],
1421 'id': self.blockdev_to_id(blockdev_data),
1422 }
1423+ if blockdev_data.get('DM_MULTIPATH_DEVICE_PATH') == "1":
1424+ mpath_name = self.get_mpath_name(blockdev_data)
1425+ entry['multipath'] = mpath_name
1426
1427 # default disks to gpt
1428 if entry['type'] == 'disk':
1429@@ -670,7 +749,11 @@ class BlockdevParser(ProbertParser):
1430 entry.update(uniq_ids)
1431
1432 if 'ID_PART_TABLE_TYPE' in blockdev_data:
1433- entry['ptable'] = blockdev_data['ID_PART_TABLE_TYPE']
1434+ ptype = blockdev_data['ID_PART_TABLE_TYPE']
1435+ if ptype in schemas._ptables:
1436+ entry['ptable'] = ptype
1437+ else:
1438+ entry['ptable'] = schemas._ptable_unsupported
1439 return entry
1440
1441 if entry['type'] == 'partition':
1442@@ -920,7 +1003,6 @@ class RaidParser(ProbertParser):
1443 Collects storage config type: raid for valid
1444 data and returns tuple of lists, configs, errors.
1445 """
1446-
1447 configs = []
1448 errors = []
1449 for devname, data in self.class_data.items():
1450@@ -1104,7 +1186,7 @@ class ZfsParser(ProbertParser):
1451 return (zpool_configs + zfs_configs, errors)
1452
1453
1454-def extract_storage_config(probe_data):
1455+def extract_storage_config(probe_data, strict=False):
1456 """ Examine a probert storage dictionary and extract a curtin
1457 storage configuration that would recreate all of the
1458 storage devices present in the provided data.
1459@@ -1156,7 +1238,10 @@ def extract_storage_config(probe_data):
1460 for e in errors:
1461 LOG.exception('Validation error: %s\n' % e)
1462 if len(errors) > 0:
1463- raise RuntimeError("Extract storage config does not validate.")
1464+ errmsg = "Extract storage config does not validate."
1465+ LOG.warning(errmsg)
1466+ if strict:
1467+ raise RuntimeError(errmsg)
1468
1469 # build and merge probed data into a valid storage config by
1470 # generating a config tree for each item in the probed data
1471diff --git a/curtin/udev.py b/curtin/udev.py
1472index 106a7e7..e2e3dd0 100644
1473--- a/curtin/udev.py
1474+++ b/curtin/udev.py
1475@@ -1,6 +1,8 @@
1476 # This file is part of curtin. See LICENSE file for copyright and license info.
1477
1478+import shlex
1479 import os
1480+
1481 from curtin import util
1482 from curtin.log import logged_call
1483
1484@@ -73,7 +75,7 @@ def udevadm_info(path=None):
1485 if not path:
1486 raise ValueError('Invalid path: "%s"' % path)
1487
1488- info_cmd = ['udevadm', 'info', '--query=property', path]
1489+ info_cmd = ['udevadm', 'info', '--query=property', '--export', path]
1490 output, _ = util.subp(info_cmd, capture=True)
1491
1492 # strip for trailing empty line
1493@@ -87,13 +89,19 @@ def udevadm_info(path=None):
1494 if not value:
1495 value = None
1496 if value:
1497- # devlinks is a list of paths separated by space
1498- # convert to a list for easy use
1499- if key == 'DEVLINKS':
1500- info[key] = value.split()
1501+ # preserve spaces in values to match udev database
1502+ parsed = shlex.split(value)
1503+ if ' ' not in value:
1504+ info[key] = parsed[0]
1505 else:
1506- # preserve spaces in values, to match udev database
1507- info[key] = value
1508+ # special case some known entries with spaces, e.g. ID_SERIAL
1509+ # and DEVLINKS, see tests/unittests/test_udev.py
1510+ if key == "DEVLINKS":
1511+ info[key] = shlex.split(parsed[0])
1512+ elif key == 'ID_SERIAL':
1513+ info[key] = parsed[0]
1514+ else:
1515+ info[key] = parsed
1516
1517 return info
1518
1519diff --git a/curtin/util.py b/curtin/util.py
1520index ebe219d..eb2228f 100644
1521--- a/curtin/util.py
1522+++ b/curtin/util.py
1523@@ -632,7 +632,7 @@ class ChrootableTarget(object):
1524 if mounts is not None:
1525 self.mounts = mounts
1526 else:
1527- self.mounts = ["/dev", "/proc", "/sys"]
1528+ self.mounts = ["/dev", "/proc", "/run", "/sys"]
1529 self.umounts = []
1530 self.disabled_daemons = False
1531 self.allow_daemons = allow_daemons
1532@@ -906,8 +906,9 @@ def sanitize_source(source):
1533 if type(source) is dict:
1534 # already sanitized?
1535 return source
1536- supported = ['tgz', 'dd-tgz', 'dd-tbz', 'dd-txz', 'dd-tar', 'dd-bz2',
1537- 'dd-gz', 'dd-xz', 'dd-raw', 'fsimage', 'fsimage-layered']
1538+ supported = ['tgz', 'dd-tgz', 'tbz', 'dd-tbz', 'txz', 'dd-txz', 'dd-tar',
1539+ 'dd-bz2', 'dd-gz', 'dd-xz', 'dd-raw', 'fsimage',
1540+ 'fsimage-layered']
1541 deftype = 'tgz'
1542 for i in supported:
1543 prefix = i + ":"
1544@@ -915,8 +916,14 @@ def sanitize_source(source):
1545 return {'type': i, 'uri': source[len(prefix):]}
1546
1547 # translate squashfs: to fsimage type.
1548- if source.startswith("squashfs:"):
1549- return {'type': 'fsimage', 'uri': source[len("squashfs:")]}
1550+ if source.startswith("squashfs://"):
1551+ return {'type': 'fsimage', 'uri': source[len("squashfs://"):]}
1552+
1553+ elif source.startswith("squashfs:"):
1554+ LOG.warning("The squashfs: prefix is deprecated and"
1555+ "will be removed in a future release."
1556+ "Please use squashfs:// instead.")
1557+ return {'type': 'fsimage', 'uri': source[len("squashfs:"):]}
1558
1559 if source.endswith("squashfs") or source.endswith("squash"):
1560 return {'type': 'fsimage', 'uri': source}
1561diff --git a/debian/changelog b/debian/changelog
1562index a5c5527..6d739ab 100644
1563--- a/debian/changelog
1564+++ b/debian/changelog
1565@@ -1,3 +1,66 @@
1566+curtin (19.3-17-g50ffca46-0ubuntu1~19.10.1) eoan; urgency=medium
1567+
1568+ * New upstream snapshot. (LP: #1861452)
1569+ - clear-holders: ensure we wipe device even if multipath enabled not not mp
1570+ - block_meta: use reliable fs_spec entries for block devices
1571+ - multipath: handle removal of multipath partitions correctly
1572+ - vmtests: skip Focal deploying Centos70 ScsiBasic
1573+ - vmtests: fix network mtu tests, separating ifupdown vs networkd
1574+ - doc: Fix kexec documentation bug. [Mike Pontillo]
1575+ - vmtests: Add Focal Fossa
1576+ - centos: Add centos/rhel 8 support, enable UEFI Secure Boot
1577+ [Lee Trager]
1578+ - Bump XFS /boot skip-by date out a while
1579+ - vmtest: Fix a missing unset of OUTPUT_FSTAB
1580+ - curthooks: handle s390x/aarch64 kernel install hooks
1581+ - clear-holders: handle arbitrary order of devices to clear
1582+ - curthooks: only run update-initramfs in target once
1583+ - test_network_mtu: bump fixby date for MTU tests
1584+ - block-discover: don't skip partitions on virtual devices
1585+ - block-discover: handle partial probe data
1586+ - Fix parsing of squashfs: uri prefix for installation sources
1587+ [Daniel Fox]
1588+ - Release 19.3
1589+ - Update HACKING.rst with Josh Powers contact info.
1590+ - t/jenkins-runner: replace $EPOCHSECONDS with 'date +%s' [Paride Legovini]
1591+ - curthooks: skip setup_kernel_img_conf on eoan and newer
1592+ - block_meta: use lookup for wwn, fix fallback from wwn, serial, path
1593+ - vmtest: Adjust TestScsiBasic to use dnames to find correct disk
1594+ - schema: Add ptable value 'unsupported'
1595+ - tools/xkvm: add -nographic to speed up devopt query
1596+ - test_block_dasd: fix random_device_id to only generate valid IDs
1597+ - vmtest: update skip_if_arch message
1598+ - Add skip_by_date to eoan ipv6 vlan test
1599+ - storage_config: interpret value, not presence, of
1600+ DM_MULTIPATH_DEVICE_PATH [Michael Hudson-Doyle]
1601+ - vmtest: Add skip_by_date for test_ip_output on eoan + vlans
1602+ - block-schema: update raid schema for preserve and metadata
1603+ - dasd: update partition table value to 'vtoc'
1604+ - clear-holders: increase the level for devices with holders by one
1605+ - tests: mock timestamp used in collect-log file creation
1606+ - ChrootableTarget: mount /run to resolve lvm/mdadm issues which
1607+ require it.
1608+ - block-discover: handle multipath disks
1609+ - Handle partial raid on partitions
1610+ - install: export zpools if present in the storage-config
1611+ - block-schema: allow 'mac' as partition table type
1612+ - jenkins-runner: disable the lockfile timeout by default [Paride Legovini]
1613+ - curthooks: use correct grub-efi package name on i386
1614+ - vmtest-sync-images: remove unused imports [Paride Legovini]
1615+ - vmtests: use file locking on the images [Paride Legovini]
1616+ - vmtest: enable arm64 [Paride Legovini]
1617+ - Make the vmtests/test_basic test suite run on ppc64el [Paride Legovini]
1618+ - vmtests: separate arch and target_arch in tests [Paride Legovini]
1619+ - vmtests: new decorator: skip_if_arch [Paride Legovini]
1620+ - vmtests: increase the VM memory for Bionic
1621+ - vmtests: Skip Eoan ZFS Root tests until bug fix is complete
1622+ - util: add support for 'tbz', 'txz' tar format types to sanitize_source
1623+ - net: ensure eni helper tools install if given netplan config
1624+ - d/control: update Depends for new probert package names
1625+ [Dimitri John Ledkov]
1626+
1627+ -- Ryan Harper <ryan.harper@canonical.com> Thu, 30 Jan 2020 13:46:56 -0600
1628+
1629 curtin (19.2-9-g38ce22b0-0ubuntu1) eoan; urgency=medium
1630
1631 * New upstream snapshot.
1632diff --git a/debian/control b/debian/control
1633index b5b857b..9fddcbd 100644
1634--- a/debian/control
1635+++ b/debian/control
1636@@ -26,7 +26,7 @@ Depends: bcache-tools,
1637 lvm2,
1638 mdadm,
1639 parted,
1640- probert,
1641+ probert-storage | probert,
1642 python3-curtin (= ${binary:Version}),
1643 udev,
1644 xfsprogs,
1645diff --git a/doc/topics/config.rst b/doc/topics/config.rst
1646index b7cca43..59e71f3 100644
1647--- a/doc/topics/config.rst
1648+++ b/doc/topics/config.rst
1649@@ -393,7 +393,8 @@ Enable rebooting with kexec.
1650
1651 **Example**::
1652
1653- kexec: on
1654+ kexec:
1655+ mode: "on"
1656
1657
1658 multipath
1659@@ -555,6 +556,7 @@ configures the method used to copy the image to the target system.
1660 - **dd-**: Use ``dd`` command to write image to target.
1661 - **cp://**: Use ``rsync`` command to copy source directory to target.
1662 - **file://**: Use ``tar`` command to extract source to target.
1663+- **squashfs://**: Mount squashfs image and copy contents to target.
1664 - **http[s]://**: Use ``wget | tar`` commands to extract source to target.
1665 - **fsimage://** mount filesystem image and copy contents to target.
1666 Local file or url are supported. Filesystem can be any filesystem type
1667@@ -649,6 +651,9 @@ This results in Curtin downloading the following URLs::
1668 sources:
1669 - cp:///
1670
1671+**Example squashfs from NFS mount**::
1672+ sources:
1673+ - squashfs:///media/filesystem.squashfs
1674
1675 **Example Copy from local tarball**::
1676
1677diff --git a/doc/topics/storage.rst b/doc/topics/storage.rst
1678index a1346e9..c85174d 100644
1679--- a/doc/topics/storage.rst
1680+++ b/doc/topics/storage.rst
1681@@ -110,7 +110,7 @@ These ``label`` values are reserved and cannot be used:
1682 **disk_layout**: *cdl, ldl*
1683
1684 The default ``disk_layout`` value is ``cdl``, the compaible disk layout which
1685-allows for up to 3 partitions and a MBR. The ``ldl``, Linux layout has only
1686+allows for up to 3 partitions and a VTOC. The ``ldl``, Linux layout has only
1687 one partition.
1688
1689
1690@@ -125,7 +125,7 @@ one partition.
1691 mode: full
1692 - id: disk0
1693 type: disk
1694- ptable: mbr
1695+ ptable: vtoc
1696 serial: 0X1520
1697 name: root_disk
1698 wipe: superblock
1699@@ -278,6 +278,14 @@ and determine which device to use as a boot disk. In cases where the boot
1700 device is on a special volume, such as a RAID array or a LVM Logical Volume,
1701 it may be necessary to specify the device that will hold the grub bootloader.
1702
1703+**multipath**: *<multipath name or serial>*
1704+
1705+If a disk is a path in a multipath device, it may be included in the
1706+configuration dictionary. Currently the value is informational only.
1707+Curtin already detects whether disks are part of a multipath and selects
1708+one member path to operate upon.
1709+
1710+
1711 **Config Example**::
1712
1713 - id: disk0
1714@@ -374,6 +382,13 @@ For partitions, the udev rule created relies upon disk contents, in this case
1715 the partition entry UUID. This will remain in effect unless the underlying disk
1716 on which the partition resides has the partition table modified or wiped.
1717
1718+**multipath**: *<multipath name or serial>*
1719+
1720+If a partition is found on a multipath device, it may be included in the
1721+configuration dictionary. Currently the value is informational only.
1722+Curtin already detects whether partitions are part of a multipath and selects
1723+one member path to operate upon.
1724+
1725
1726 **Config Example**::
1727
1728diff --git a/examples/tests/basic-dasd.yaml b/examples/tests/basic-dasd.yaml
1729index 62efbf0..3b0ba0d 100644
1730--- a/examples/tests/basic-dasd.yaml
1731+++ b/examples/tests/basic-dasd.yaml
1732@@ -11,14 +11,14 @@ storage:
1733 - id: sda
1734 type: disk
1735 wipe: superblock
1736- ptable: msdos
1737+ ptable: vtoc
1738 model: QEMU HARDDISK
1739 serial: disk-a
1740 grub_device: true
1741 - id: dasdb
1742 type: disk
1743 wipe: superblock
1744- ptable: msdos
1745+ ptable: vtoc
1746 serial: 0X1520
1747 wipe: superblock
1748 - id: sda-part1
1749diff --git a/examples/tests/bcache-ceph-nvme-simple.yaml b/examples/tests/bcache-ceph-nvme-simple.yaml
1750new file mode 100644
1751index 0000000..83cb04c
1752--- /dev/null
1753+++ b/examples/tests/bcache-ceph-nvme-simple.yaml
1754@@ -0,0 +1,107 @@
1755+storage:
1756+ config:
1757+ - grub_device: true
1758+ id: sda
1759+ model: MM1000GBKAL
1760+ name: sda
1761+ ptable: gpt
1762+ serial: disk-a
1763+ type: disk
1764+ wipe: superblock
1765+ - id: sdb
1766+ model: MM1000GBKAL
1767+ name: sdb
1768+ serial: disk-b
1769+ type: disk
1770+ wipe: superblock
1771+ - id: nvme0n1
1772+ model: INTEL SSDPEDME400G4
1773+ name: nvme0n1
1774+ serial: nvme-CVMD552400
1775+ type: disk
1776+ wipe: superblock
1777+ - backing_device: sdb
1778+ cache_device: nvme0n1
1779+ cache_mode: writeback
1780+ id: bcache1
1781+ name: bcache1
1782+ type: bcache
1783+ - device: sda
1784+ id: sda-part1
1785+ name: sda-part1
1786+ number: 1
1787+ offset: 4194304B
1788+ size: 5G
1789+ type: partition
1790+ uuid: 1e27e7af-26dc-4af4-9ef5-aea928204997
1791+ wipe: superblock
1792+ - device: sda
1793+ id: sda-part2
1794+ name: sda-part2
1795+ number: 2
1796+ size: 2G
1797+ type: partition
1798+ uuid: 0040d622-41f1-4596-842f-82d731ba9054
1799+ wipe: superblock
1800+ - device: sda
1801+ id: sda-part3
1802+ name: sda-part3
1803+ number: 3
1804+ size: 2G
1805+ type: partition
1806+ uuid: cb59d827-662c-4da6-b1ef-7967218bd0db
1807+ wipe: superblock
1808+ - backing_device: sda-part3
1809+ cache_device: nvme0n1
1810+ cache_mode: writeback
1811+ id: bcache0
1812+ name: bcache0
1813+ type: bcache
1814+ - fstype: fat32
1815+ id: sda-part1_format
1816+ label: efi
1817+ type: format
1818+ uuid: 27638478-d881-43e5-a93c-1cac7aa60daa
1819+ volume: sda-part1
1820+ - fstype: ext4
1821+ id: sda-part2_format
1822+ label: boot
1823+ type: format
1824+ uuid: cfd11d4f-d77f-4307-b372-b52e81c873f7
1825+ volume: sda-part2
1826+ - fstype: ext4
1827+ id: bcache0_format
1828+ label: root
1829+ type: format
1830+ uuid: 63247841-195c-4939-83e4-cb834d61f95f
1831+ volume: bcache0
1832+ - devices:
1833+ - bcache1
1834+ id: ceph-bcache-vg
1835+ name: ceph-bcache-vg
1836+ type: lvm_volgroup
1837+ - id: ceph-bcache-lv-0
1838+ name: ceph-bcache-lv-0
1839+ size: 3G
1840+ type: lvm_partition
1841+ volgroup: ceph-bcache-vg
1842+ - fstype: xfs
1843+ id: ceph-bcache-lv-0_format
1844+ volume: ceph-bcache-lv-0
1845+ type: format
1846+ - device: bcache0_format
1847+ id: bcache0_mount
1848+ options: ''
1849+ path: /
1850+ type: mount
1851+ - device: sda-part2_format
1852+ id: sda-part2_mount
1853+ options: ''
1854+ path: /boot
1855+ type: mount
1856+ - device: sda-part1_format
1857+ id: sda-part1_mount
1858+ options: ''
1859+ path: /boot/efi
1860+ type: mount
1861+ version: 1
1862diff --git a/examples/tests/bcache-wipe-xfs.yaml b/examples/tests/bcache-wipe-xfs.yaml
1863index 558d442..1a181a8 100644
1864--- a/examples/tests/bcache-wipe-xfs.yaml
1865+++ b/examples/tests/bcache-wipe-xfs.yaml
1866@@ -6,9 +6,10 @@ early_commands:
1867 # would be seen as soon as the disk was partitioned and cause problems
1868 # for curtin's use of the disk.
1869 # This config recreates issue LP: #1718699
1870- 00_blockmeta: [env, -u, OUTPUT_FSTAB, TARGET_MOUNT_POINT=/tmp/my.bdir/target,
1871- WORKING_DIR=/tmp/my.bdir/work.d, curtin, --showtrace, -v,
1872- block-meta, --umount, custom]
1873+ 00_blockmeta: [env, OUTPUT_FSTAB=/tmp/my.bdir/state/fstab,
1874+ TARGET_MOUNT_POINT=/tmp/my.bdir/target,
1875+ WORKING_DIR=/tmp/my.bdir/work.d, curtin, --showtrace, -v,
1876+ block-meta, --umount, custom]
1877 01_clear_holders: [curtin, clear-holders, --preserve, /dev/disk/by-id/virtio-disk-b]
1878 02_quick_erase: [curtin, block-wipe, --mode, superblock, /dev/disk/by-id/virtio-disk-b]
1879
1880diff --git a/examples/tests/bridging_network_v2.yaml b/examples/tests/bridging_network_v2.yaml
1881new file mode 100644
1882index 0000000..b208972
1883--- /dev/null
1884+++ b/examples/tests/bridging_network_v2.yaml
1885@@ -0,0 +1,38 @@
1886+# v2 equivalent of examples/tests/bridging_network.yaml
1887+showtrace: true
1888+network:
1889+ version: 2
1890+ ethernets:
1891+ eth0:
1892+ dhcp4: true
1893+ match:
1894+ macaddress: '52:54:00:12:34:00'
1895+ set-name: eth0
1896+ eth1:
1897+ match:
1898+ macaddress: '52:54:00:12:34:02'
1899+ set-name: eth1
1900+ eth2:
1901+ match:
1902+ macaddress: '52:54:00:12:34:04'
1903+ set-name: eth2
1904+ bridges:
1905+ br0:
1906+ addresses:
1907+ - 192.168.14.2/24
1908+ interfaces:
1909+ - eth1
1910+ - eth2
1911+ parameters:
1912+ ageing-time: 250
1913+ forward-delay: 1
1914+ hello-time: 1
1915+ max-age: 10
1916+ path-cost:
1917+ eth1: 50
1918+ eth2: 75
1919+ port-priority:
1920+ eth1: 28
1921+ eth2: 14
1922+ priority: 22
1923+ stp: false
1924diff --git a/examples/tests/dirty_disks_config.yaml b/examples/tests/dirty_disks_config.yaml
1925index bcf3fbc..2f86f9e 100644
1926--- a/examples/tests/dirty_disks_config.yaml
1927+++ b/examples/tests/dirty_disks_config.yaml
1928@@ -22,6 +22,13 @@ bucket:
1929 done
1930 swapon --show
1931 exit 0
1932+ - &multipath_on |
1933+ #!/bin/sh
1934+ if command -v multipath; then
1935+ multipath -ll
1936+ multipath -r
1937+ multipath -ll
1938+ fi
1939 - &zpool_export |
1940 #!/bin/sh
1941 # disable any rpools to trigger disks with zfs_member label but inactive
1942@@ -75,11 +82,12 @@ early_commands:
1943 # the disks exactly as in this config before the rest of the install
1944 # will just blow it all away. We have clean out other environment
1945 # that could unintentionally mess things up.
1946- 01-blockmeta: [env, -u, OUTPUT_FSTAB,
1947+ 01-blockmeta: [env, OUTPUT_FSTAB=/tmp/my.bdir/state/fstab,
1948 TARGET_MOUNT_POINT=/tmp/my.bdir/target,
1949 WORKING_DIR=/tmp/my.bdir/work.d,
1950 curtin, --showtrace, -v, block-meta, --umount, custom]
1951 02-enable_swaps: [sh, -c, *swapon]
1952+ 02-multipath_on: [sh, -c, *multipath_on]
1953 03-disable_rpool: [sh, -c, *zpool_export]
1954 04-lvm_stop: [sh, -c, *lvm_stop]
1955 05-mdadm_stop: [sh, -c, *mdadm_stop]
1956diff --git a/examples/tests/network_mtu_networkd.yaml b/examples/tests/network_mtu_networkd.yaml
1957new file mode 100644
1958index 0000000..e2ac444
1959--- /dev/null
1960+++ b/examples/tests/network_mtu_networkd.yaml
1961@@ -0,0 +1,93 @@
1962+showtrace: true
1963+network:
1964+ version: 1
1965+ config:
1966+ - type: physical
1967+ name: interface0
1968+ mac_address: "52:54:00:12:34:00"
1969+ subnets:
1970+ - type: static
1971+ address: 192.168.1.2/24
1972+ mtu: 1601
1973+ - type: static
1974+ address: 2001:4800:78ff:1b:be76:4eff:fe06:1000
1975+ netmask: 'ffff:ffff:ffff:ffff::'
1976+ mtu: 1501
1977+ - type: physical
1978+ name: interface1
1979+ mac_address: "52:54:00:12:34:02"
1980+ subnets:
1981+ - type: static
1982+ address: 192.168.2.2/24
1983+ mtu: 1501
1984+ - type: static
1985+ address: 2001:4800:78ff:1b:be76:4eff:fe06:2000
1986+ netmask: 'ffff:ffff:ffff:ffff::'
1987+ mtu: 1501
1988+ - type: physical
1989+ name: interface2
1990+ mac_address: "52:54:00:12:34:04"
1991+ subnets:
1992+ - type: dhcp
1993+ - type: physical
1994+ name: interface4
1995+ mac_address: "52:54:00:12:34:08"
1996+ subnets:
1997+ - type: static
1998+ address: 2001:4800:78ff:1b:be76:4eff:fe06:5000
1999+ netmask: 'ffff:ffff:ffff:ffff::'
2000+ mtu: 8900
2001+ - type: static
2002+ address: 192.168.5.2/24
2003+ mtu: 9000
2004+ - type: physical
2005+ name: interface5
2006+ mac_address: "52:54:00:12:34:0c"
2007+ subnets:
2008+ - type: static
2009+ address: 2001:4800:78ff:1b:be76:4eff:fe06:6000
2010+ netmask: 'ffff:ffff:ffff:ffff::'
2011+ mtu: 1480
2012+ - type: static
2013+ address: 192.168.6.2/24
2014+ mtu: 1480
2015+
2016+write_files:
2017+ capture_mtu:
2018+ path: '/usr/local/bin/capture-mtu'
2019+ permissions: '0755'
2020+ owner: 'root:root'
2021+ content: |
2022+ #!/bin/sh
2023+ for x in 0 1 2 4 5; do
2024+ dev_mtu=$(cat /sys/class/net/interface${x}/mtu)
2025+ ipv6_mtu=$(cat /proc/sys/net/ipv6/conf/interface${x}/mtu)
2026+ sys=$(sysctl net.ipv6.conf.interface${x}.mtu)
2027+ echo "WARK: interface${x} dev_mtu=$dev_mtu proc_ipv6_mtu=$ipv6_mtu"
2028+ echo "WARK: $sys"
2029+ done
2030+
2031+bucket:
2032+ - &networkd_debug |
2033+ #!/bin/sh
2034+ MP=$TARGET_MOUNT_POINT
2035+ mkdir -p "${MP}/etc/systemd/system/systemd-networkd.service.d"
2036+ conf="${MP}/etc/systemd/system/systemd-networkd.service.d/10-debug.conf"
2037+ echo "[Service]" >$conf
2038+ echo "Environment=SYSTEMD_LOG_LEVEL=debug" >>$conf
2039+ echo "ExecStartPost=/usr/local/bin/capture-mtu" >>$conf
2040+ exit 0
2041+
2042+ - &capture_mtu |
2043+ #!/bin/sh -x
2044+ MP=$TARGET_MOUNT_POINT
2045+ for service in cloud-init-local cloud-init cloud-config; do
2046+ mkdir -p "${MP}/etc/systemd/system/${service}.service.d"
2047+ conf="${MP}/etc/systemd/system/${service}.service.d/10-debug.conf"
2048+ echo "[Service]" >$conf
2049+ echo "ExecStartPre=/usr/local/bin/capture-mtu" >>$conf
2050+ done
2051+
2052+late_commands:
2053+ 01-networkd_debug: [sh, -c, *networkd_debug]
2054+ 02-capture_mtu: [sh, -c, *capture_mtu]
2055diff --git a/examples/tests/reuse-raid-member-partition.yaml b/examples/tests/reuse-raid-member-partition.yaml
2056new file mode 100644
2057index 0000000..3fe2d83
2058--- /dev/null
2059+++ b/examples/tests/reuse-raid-member-partition.yaml
2060@@ -0,0 +1,73 @@
2061+showtrace: true
2062+
2063+# The point of this test is to test installing to a partition that used to
2064+# be a RAID member where the other disks that used to be part of the
2065+# RAID are not present (the scenario that the disk was just grabbed
2066+# out of a pile of previously used disks and shoved into a server).
2067+
2068+# So what it does is to create a RAID0 out of two partition from two
2069+# disks, stop the RAID, wipe one of the disks and then install to the
2070+# other, reusing the partition that was part of the RAID.
2071+
2072+bucket:
2073+ - &setup |
2074+ parted /dev/disk/by-id/virtio-disk-a --script -- \
2075+ mklabel gpt \
2076+ mkpart primary 1GiB 2GiB \
2077+ mkpart primary 2GiB 9GiB
2078+ parted /dev/disk/by-id/virtio-disk-b --script -- \
2079+ mklabel gpt \
2080+ mkpart primary 2GiB 9GiB
2081+ udevadm settle
2082+ mdadm --create --metadata 1.2 --level 0 -n 2 /dev/md1 --assume-clean \
2083+ /dev/disk/by-id/virtio-disk-a-part2 /dev/disk/by-id/virtio-disk-b-part1
2084+ udevadm settle
2085+ mdadm --stop /dev/md1
2086+ udevadm settle
2087+ mdadm --zero-superblock /dev/disk/by-id/virtio-disk-b-part1
2088+ wipefs -a /dev/disk/by-id/virtio-disk-b
2089+ udevadm settle
2090+
2091+early_commands:
2092+ 00-setup-raid: [sh, -exuc, *setup]
2093+
2094+storage:
2095+ config:
2096+ - type: disk
2097+ id: id_disk0
2098+ serial: disk-a
2099+ ptable: gpt
2100+ preserve: true
2101+ - type: disk
2102+ id: id_disk1
2103+ serial: disk-b
2104+ - type: partition
2105+ id: id_disk0_part1
2106+ preserve: true
2107+ device: id_disk0
2108+ flag: boot
2109+ number: 1
2110+ size: 1G
2111+ - type: partition
2112+ id: id_disk0_part2
2113+ preserve: true
2114+ device: id_disk0
2115+ number: 2
2116+ size: 7G
2117+ - type: format
2118+ id: id_efi_format
2119+ volume: id_disk0_part1
2120+ fstype: fat32
2121+ - type: format
2122+ id: id_root_format
2123+ volume: id_disk0_part2
2124+ fstype: ext4
2125+ - type: mount
2126+ device: id_root_format
2127+ id: id_root_mount
2128+ path: /
2129+ - type: mount
2130+ id: id_efi_mount
2131+ device: id_efi_format
2132+ path: /boot/efi
2133+ version: 1
2134diff --git a/examples/tests/reuse-raid-member-wipe.yaml b/examples/tests/reuse-raid-member-wipe.yaml
2135new file mode 100644
2136index 0000000..84a2686
2137--- /dev/null
2138+++ b/examples/tests/reuse-raid-member-wipe.yaml
2139@@ -0,0 +1,71 @@
2140+showtrace: true
2141+
2142+# The point of this test is to test installing to a disk that contains
2143+# a partition that used to be a RAID member where the other parts of
2144+# the RAID are not present (the scenario is that the disk was just
2145+# grabbed out of a pile of previously used disks and shoved into a
2146+# server).
2147+
2148+# So what it does is to create a RAID0 out of partitions on two disks,
2149+# stop the RAID, wipe the superblock on one of them and then install
2150+# to the other using a standard partitioning scheme.
2151+
2152+bucket:
2153+ - &setup |
2154+ parted /dev/disk/by-id/virtio-disk-a --script -- \
2155+ mklabel gpt \
2156+ mkpart primary 1GiB 9GiB
2157+ parted /dev/disk/by-id/virtio-disk-b --script -- \
2158+ mklabel gpt \
2159+ mkpart primary 1GiB 9GiB
2160+ udevadm settle
2161+ mdadm --create --metadata 1.2 --level 0 -n 2 /dev/md1 --assume-clean \
2162+ /dev/disk/by-id/virtio-disk-a-part1 /dev/disk/by-id/virtio-disk-b-part1
2163+ udevadm settle
2164+ mdadm --stop /dev/md1
2165+ udevadm settle
2166+ mdadm --zero-superblock /dev/disk/by-id/virtio-disk-b-part1
2167+ wipefs -a /dev/disk/by-id/virtio-disk-b
2168+ udevadm settle
2169+
2170+early_commands:
2171+ 00-setup-raid: [sh, -exuc, *setup]
2172+
2173+storage:
2174+ config:
2175+ - type: disk
2176+ id: id_disk0
2177+ serial: disk-a
2178+ ptable: gpt
2179+ wipe: superblock-recursive
2180+ - type: disk
2181+ id: id_disk1
2182+ serial: disk-b
2183+ - type: partition
2184+ id: id_disk0_part1
2185+ device: id_disk0
2186+ flag: boot
2187+ number: 1
2188+ size: 512M
2189+ - type: partition
2190+ id: id_disk0_part2
2191+ device: id_disk0
2192+ number: 2
2193+ size: 8G
2194+ - type: format
2195+ id: id_efi_format
2196+ volume: id_disk0_part1
2197+ fstype: fat32
2198+ - type: format
2199+ id: id_root_format
2200+ volume: id_disk0_part2
2201+ fstype: ext4
2202+ - type: mount
2203+ device: id_root_format
2204+ id: id_root_mount
2205+ path: /
2206+ - type: mount
2207+ id: id_efi_mount
2208+ device: id_efi_format
2209+ path: /boot/efi
2210+ version: 1
2211diff --git a/helpers/common b/helpers/common
2212index 5928150..6c8e4f0 100644
2213--- a/helpers/common
2214+++ b/helpers/common
2215@@ -679,7 +679,7 @@ install_grub() {
2216
2217 # grub is not the bootloader you are looking for
2218 if [ "${target_arch}" = "s390x" ]; then
2219- return 0;
2220+ return 0;
2221 fi
2222
2223 # set correct grub package
2224@@ -694,7 +694,7 @@ install_grub() {
2225 x86_64)
2226 case $rhel_ver in
2227 6) grub_name="grub";;
2228- 7) grub_name="grub2-pc";;
2229+ 7|8) grub_name="grub2-pc";;
2230 *)
2231 error "Unknown rhel_ver [$rhel_ver]";
2232 return 1;
2233@@ -711,7 +711,10 @@ install_grub() {
2234 case "$target_arch" in
2235 x86_64)
2236 # centos 7+, no centos6 support
2237- grub_name="grub2-efi-x64-modules"
2238+ # grub2-efi-x64 installs a signed grub bootloader while
2239+ # curtin uses grub2-efi-x64-modules to generate grubx64.efi.
2240+ # Either works just check that one of them is installed.
2241+ grub_name="grub2-efi-x64 grub2-efi-x64-modules"
2242 grub_target="x86_64-efi"
2243 ;;
2244 amd64)
2245@@ -739,11 +742,13 @@ install_grub() {
2246 error "failed to check if $grub_name installed";
2247 return 1;
2248 fi
2249- case "$tmp" in
2250- install\ ok\ installed) :;;
2251- *) debug 1 "$grub_name not installed, not doing anything";
2252- return 1;;
2253- esac
2254+ # Check that any of the packages in $grub_name are installed. If
2255+ # grub_name contains multiple packages, as it does for CentOS 7+,
2256+ # only one package has to be installed for this to pass.
2257+ if ! echo $tmp | grep -q 'install ok installed'; then
2258+ debug 1 "$grub_name not installed, not doing anything"
2259+ return 1
2260+ fi
2261
2262 local grub_d="etc/default/grub.d"
2263 # ubuntu writes to /etc/default/grub.d/50-curtin-settings.cfg
2264@@ -822,11 +827,31 @@ install_grub() {
2265 if [ "$update_nvram" -ge 1 ]; then
2266 nvram=""
2267 fi
2268+ if [ "${#grubdevs_new[@]}" -eq 1 ] && [ -f "${grubdevs_new[0]}" ]; then
2269+ # Currently UEFI can only be pointed to one system partition. If
2270+ # for some reason multiple install locations are given only use the
2271+ # first.
2272+ efi_dev="${grubdevs_new[0]}"
2273+ elif [ "${#grubdevs_new[@]}" -gt 1 ]; then
2274+ error "Only one grub device supported on UEFI!"
2275+ exit 1
2276+ else
2277+ # If no storage configuration was given try to determine the system
2278+ # partition.
2279+ efi_dev=$(awk -v "MP=${mp}/boot/efi" '$2 == MP { print $1 }' /proc/mounts)
2280+ fi
2281+ # The partition number of block device name need to be determined here
2282+ # so both getting the UEFI device from Curtin config and discovering it
2283+ # work.
2284+ efi_part_num=$(cat /sys/class/block/$(basename $efi_dev)/partition)
2285+ efi_disk="/dev/$(lsblk -no pkname $efi_dev)"
2286 debug 1 "curtin uefi: installing ${grub_name} to: /boot/efi"
2287 chroot "$mp" env DEBIAN_FRONTEND=noninteractive sh -exc '
2288 echo "before grub-install efiboot settings"
2289 efibootmgr -v || echo "WARN: efibootmgr exited $?"
2290 bootid="$4"
2291+ efi_disk="$5"
2292+ efi_part_num="$6"
2293 grubpost=""
2294 case $bootid in
2295 debian|ubuntu)
2296@@ -836,7 +861,15 @@ install_grub() {
2297 ;;
2298 centos|redhat|rhel)
2299 grubcmd="grub2-install"
2300- grubpost="grub2-mkconfig -o /boot/grub2/grub.cfg"
2301+ # RHEL uses redhat instead of the os_variant rhel for the bootid.
2302+ if [ "$bootid" = "rhel" ]; then
2303+ bootid="redhat"
2304+ fi
2305+ if [ -f /boot/efi/EFI/$bootid/grubx64.efi ]; then
2306+ grubpost="grub2-mkconfig -o /boot/efi/EFI/$bootid/grub.cfg"
2307+ else
2308+ grubpost="grub2-mkconfig -o /boot/grub2/grub.cfg"
2309+ fi
2310 ;;
2311 *)
2312 echo "Unsupported OS: $bootid" 1>&2
2313@@ -852,10 +885,45 @@ install_grub() {
2314 echo "$gi_out" | grep -q -- "$no_nvram" || no_nvram=""
2315 echo "$gi_out" | grep -q -- "--target" || target=""
2316 echo "$gi_out" | grep -q -- "--efi-directory" || efi_dir=""
2317- $grubcmd $target $efi_dir \
2318- --bootloader-id=$bootid --recheck $no_nvram
2319+
2320+ # Do not overwrite grubx64.efi if it already exists. grub-install
2321+ # generates grubx64.efi and overwrites any existing binary in
2322+ # /boot/efi/EFI/$bootid. This binary is not signed and will cause
2323+ # secure boot to fail.
2324+ #
2325+ # CentOS, RHEL, Fedora ship the signed boot loader in the package
2326+ # grub2-efi-x64 which installs the signed boot loader to
2327+ # /boot/efi/EFI/$bootid/grubx64.efi. All Curtin has to do is
2328+ # configure the firmware. This mirrors what Anaconda does.
2329+ #
2330+ # Debian and Ubuntu come with a patched version of grub which
2331+ # add the install flag --uefi-secure-boot which is enabled by
2332+ # default. When enabled if a signed version of grub exists on
2333+ # the filesystem it will be copied into /boot/efi/EFI/$bootid.
2334+ # Stock Ubuntu images do not ship with anything in /boot. Those
2335+ # files are generated by installing a kernel and grub.
2336+ if [ -f /boot/efi/EFI/$bootid/grubx64.efi ]; then
2337+ if [ -z "$no_nvram" ]; then
2338+ # UEFI firmware should be pointed to the shim if available to
2339+ # enable secure boot.
2340+ for boot_uefi in \
2341+ /boot/efi/EFI/$bootid/shimx64.efi \
2342+ /boot/efi/EFI/BOOT/BOOTX64.EFI \
2343+ /boot/efi/EFI/$bootid/grubx64.efi; do
2344+ if [ -f $boot_uefi ]; then
2345+ break
2346+ fi
2347+ done
2348+ loader=$(echo ${boot_uefi##/boot/efi} | sed "s|/|\\\|g")
2349+ efibootmgr --create --write-signature --label $bootid \
2350+ --disk $efi_disk --part $efi_part_num --loader $loader
2351+ fi
2352+ else
2353+ $grubcmd $target $efi_dir \
2354+ --bootloader-id=$bootid --recheck $no_nvram
2355+ fi
2356 [ -z "$grubpost" ] || $grubpost;' \
2357- -- "${grub_name}" "${grub_target}" "$nvram" "$os_variant" </dev/null ||
2358+ -- "$grub_name" "$grub_target" "$nvram" "$os_variant" "$efi_disk" "$efi_part_num" </dev/null ||
2359 { error "failed to install grub!"; return 1; }
2360
2361 chroot "$mp" sh -exc '
2362@@ -885,8 +953,11 @@ install_grub() {
2363 centos|redhat|rhel)
2364 case $bootver in
2365 6) grubcmd="grub-install";;
2366- 7) grubcmd="grub2-install"
2367+ 7|8) grubcmd="grub2-install"
2368 grubpost="grub2-mkconfig -o /boot/grub2/grub.cfg";;
2369+ *)
2370+ echo "Unknown rhel_ver [$bootver]"
2371+ exit 1
2372 esac
2373 ;;
2374 *)
2375diff --git a/tests/data/probert_storage_multipath.json b/tests/data/probert_storage_multipath.json
2376new file mode 100644
2377index 0000000..53d9f93
2378--- /dev/null
2379+++ b/tests/data/probert_storage_multipath.json
2380@@ -0,0 +1,1059 @@
2381+{
2382+ "lvm": {},
2383+ "raid": {},
2384+ "filesystem": {
2385+ "/dev/sr0": {
2386+ "BOOT_SYSTEM_ID": "EL\\x20TORITO\\x20SPECIFICATION",
2387+ "LABEL": "Ubuntu-Server_19.10_amd64",
2388+ "LABEL_ENC": "Ubuntu-Server\\x2019.10\\x20amd64",
2389+ "TYPE": "iso9660",
2390+ "USAGE": "filesystem",
2391+ "UUID": "2019-08-11-07-41-33-00",
2392+ "UUID_ENC": "2019-08-11-07-41-33-00",
2393+ "VERSION": "Joliet Extension"
2394+ },
2395+ "/dev/sda2": {
2396+ "TYPE": "ext4",
2397+ "USAGE": "filesystem",
2398+ "UUID": "80ca57a0-60b7-4328-be41-afedf915effd",
2399+ "UUID_ENC": "80ca57a0-60b7-4328-be41-afedf915effd",
2400+ "VERSION": "1.0"
2401+ },
2402+ "/dev/sdb2": {
2403+ "TYPE": "ext4",
2404+ "USAGE": "filesystem",
2405+ "UUID": "80ca57a0-60b7-4328-be41-afedf915effd",
2406+ "UUID_ENC": "80ca57a0-60b7-4328-be41-afedf915effd",
2407+ "VERSION": "1.0"
2408+ },
2409+ "/dev/dm-2": {
2410+ "TYPE": "ext4",
2411+ "USAGE": "filesystem",
2412+ "UUID": "80ca57a0-60b7-4328-be41-afedf915effd",
2413+ "UUID_ENC": "80ca57a0-60b7-4328-be41-afedf915effd",
2414+ "VERSION": "1.0"
2415+ }
2416+ },
2417+ "mount": [
2418+ {
2419+ "target": "/",
2420+ "source": "/cow",
2421+ "fstype": "overlay",
2422+ "options": "rw,relatime,lowerdir=//installer.squashfs://filesystem.squashfs,upperdir=/cow/upper,workdir=/cow/work",
2423+ "children": [
2424+ {
2425+ "target": "/sys",
2426+ "source": "sysfs",
2427+ "fstype": "sysfs",
2428+ "options": "rw,nosuid,nodev,noexec,relatime",
2429+ "children": [
2430+ {
2431+ "target": "/sys/kernel/security",
2432+ "source": "securityfs",
2433+ "fstype": "securityfs",
2434+ "options": "rw,nosuid,nodev,noexec,relatime"
2435+ },
2436+ {
2437+ "target": "/sys/fs/cgroup",
2438+ "source": "tmpfs",
2439+ "fstype": "tmpfs",
2440+ "options": "ro,nosuid,nodev,noexec,mode=755",
2441+ "children": [
2442+ {
2443+ "target": "/sys/fs/cgroup/unified",
2444+ "source": "cgroup2",
2445+ "fstype": "cgroup2",
2446+ "options": "rw,nosuid,nodev,noexec,relatime,nsdelegate"
2447+ },
2448+ {
2449+ "target": "/sys/fs/cgroup/systemd",
2450+ "source": "cgroup",
2451+ "fstype": "cgroup",
2452+ "options": "rw,nosuid,nodev,noexec,relatime,xattr,name=systemd"
2453+ },
2454+ {
2455+ "target": "/sys/fs/cgroup/cpu,cpuacct",
2456+ "source": "cgroup",
2457+ "fstype": "cgroup",
2458+ "options": "rw,nosuid,nodev,noexec,relatime,cpu,cpuacct"
2459+ },
2460+ {
2461+ "target": "/sys/fs/cgroup/devices",
2462+ "source": "cgroup",
2463+ "fstype": "cgroup",
2464+ "options": "rw,nosuid,nodev,noexec,relatime,devices"
2465+ },
2466+ {
2467+ "target": "/sys/fs/cgroup/perf_event",
2468+ "source": "cgroup",
2469+ "fstype": "cgroup",
2470+ "options": "rw,nosuid,nodev,noexec,relatime,perf_event"
2471+ },
2472+ {
2473+ "target": "/sys/fs/cgroup/hugetlb",
2474+ "source": "cgroup",
2475+ "fstype": "cgroup",
2476+ "options": "rw,nosuid,nodev,noexec,relatime,hugetlb"
2477+ },
2478+ {
2479+ "target": "/sys/fs/cgroup/rdma",
2480+ "source": "cgroup",
2481+ "fstype": "cgroup",
2482+ "options": "rw,nosuid,nodev,noexec,relatime,rdma"
2483+ },
2484+ {
2485+ "target": "/sys/fs/cgroup/net_cls,net_prio",
2486+ "source": "cgroup",
2487+ "fstype": "cgroup",
2488+ "options": "rw,nosuid,nodev,noexec,relatime,net_cls,net_prio"
2489+ },
2490+ {
2491+ "target": "/sys/fs/cgroup/freezer",
2492+ "source": "cgroup",
2493+ "fstype": "cgroup",
2494+ "options": "rw,nosuid,nodev,noexec,relatime,freezer"
2495+ },
2496+ {
2497+ "target": "/sys/fs/cgroup/cpuset",
2498+ "source": "cgroup",
2499+ "fstype": "cgroup",
2500+ "options": "rw,nosuid,nodev,noexec,relatime,cpuset"
2501+ },
2502+ {
2503+ "target": "/sys/fs/cgroup/memory",
2504+ "source": "cgroup",
2505+ "fstype": "cgroup",
2506+ "options": "rw,nosuid,nodev,noexec,relatime,memory"
2507+ },
2508+ {
2509+ "target": "/sys/fs/cgroup/blkio",
2510+ "source": "cgroup",
2511+ "fstype": "cgroup",
2512+ "options": "rw,nosuid,nodev,noexec,relatime,blkio"
2513+ },
2514+ {
2515+ "target": "/sys/fs/cgroup/pids",
2516+ "source": "cgroup",
2517+ "fstype": "cgroup",
2518+ "options": "rw,nosuid,nodev,noexec,relatime,pids"
2519+ }
2520+ ]
2521+ },
2522+ {
2523+ "target": "/sys/fs/pstore",
2524+ "source": "pstore",
2525+ "fstype": "pstore",
2526+ "options": "rw,nosuid,nodev,noexec,relatime"
2527+ },
2528+ {
2529+ "target": "/sys/fs/bpf",
2530+ "source": "bpf",
2531+ "fstype": "bpf",
2532+ "options": "rw,nosuid,nodev,noexec,relatime,mode=700"
2533+ },
2534+ {
2535+ "target": "/sys/kernel/debug",
2536+ "source": "debugfs",
2537+ "fstype": "debugfs",
2538+ "options": "rw,relatime"
2539+ },
2540+ {
2541+ "target": "/sys/kernel/config",
2542+ "source": "configfs",
2543+ "fstype": "configfs",
2544+ "options": "rw,relatime"
2545+ },
2546+ {
2547+ "target": "/sys/fs/fuse/connections",
2548+ "source": "fusectl",
2549+ "fstype": "fusectl",
2550+ "options": "rw,relatime"
2551+ }
2552+ ]
2553+ },
2554+ {
2555+ "target": "/proc",
2556+ "source": "proc",
2557+ "fstype": "proc",
2558+ "options": "rw,nosuid,nodev,noexec,relatime",
2559+ "children": [
2560+ {
2561+ "target": "/proc/sys/fs/binfmt_misc",
2562+ "source": "systemd-1",
2563+ "fstype": "autofs",
2564+ "options": "rw,relatime,fd=28,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=13765"
2565+ }
2566+ ]
2567+ },
2568+ {
2569+ "target": "/dev",
2570+ "source": "udev",
2571+ "fstype": "devtmpfs",
2572+ "options": "rw,nosuid,relatime,size=462516k,nr_inodes=115629,mode=755",
2573+ "children": [
2574+ {
2575+ "target": "/dev/pts",
2576+ "source": "devpts",
2577+ "fstype": "devpts",
2578+ "options": "rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000"
2579+ },
2580+ {
2581+ "target": "/dev/shm",
2582+ "source": "tmpfs",
2583+ "fstype": "tmpfs",
2584+ "options": "rw,nosuid,nodev"
2585+ },
2586+ {
2587+ "target": "/dev/hugepages",
2588+ "source": "hugetlbfs",
2589+ "fstype": "hugetlbfs",
2590+ "options": "rw,relatime,pagesize=2M"
2591+ },
2592+ {
2593+ "target": "/dev/mqueue",
2594+ "source": "mqueue",
2595+ "fstype": "mqueue",
2596+ "options": "rw,relatime"
2597+ }
2598+ ]
2599+ },
2600+ {
2601+ "target": "/run",
2602+ "source": "tmpfs",
2603+ "fstype": "tmpfs",
2604+ "options": "rw,nosuid,noexec,relatime,size=100568k,mode=755",
2605+ "children": [
2606+ {
2607+ "target": "/run/lock",
2608+ "source": "tmpfs",
2609+ "fstype": "tmpfs",
2610+ "options": "rw,nosuid,nodev,noexec,relatime,size=5120k"
2611+ }
2612+ ]
2613+ },
2614+ {
2615+ "target": "/cdrom",
2616+ "source": "/dev/sr0",
2617+ "fstype": "iso9660",
2618+ "options": "ro,noatime,nojoliet,check=s,map=n,blocksize=2048"
2619+ },
2620+ {
2621+ "target": "/rofs",
2622+ "source": "/dev/loop0",
2623+ "fstype": "squashfs",
2624+ "options": "ro,noatime"
2625+ },
2626+ {
2627+ "target": "/usr/lib/modules",
2628+ "source": "/dev/loop2",
2629+ "fstype": "squashfs",
2630+ "options": "ro,relatime"
2631+ },
2632+ {
2633+ "target": "/media/filesystem",
2634+ "source": "/dev/loop0",
2635+ "fstype": "squashfs",
2636+ "options": "ro,relatime"
2637+ },
2638+ {
2639+ "target": "/tmp",
2640+ "source": "tmpfs",
2641+ "fstype": "tmpfs",
2642+ "options": "rw,nosuid,nodev,relatime"
2643+ },
2644+ {
2645+ "target": "/snap/core/7270",
2646+ "source": "/dev/loop3",
2647+ "fstype": "squashfs",
2648+ "options": "ro,nodev,relatime"
2649+ },
2650+ {
2651+ "target": "/snap/subiquity/1093",
2652+ "source": "/dev/loop4",
2653+ "fstype": "squashfs",
2654+ "options": "ro,nodev,relatime"
2655+ }
2656+ ]
2657+ }
2658+ ],
2659+ "multipath": {
2660+ "maps": [
2661+ {
2662+ "multipath": "30000000000000064",
2663+ "sysfs": "dm-0",
2664+ "paths": "2"
2665+ }
2666+ ],
2667+ "paths": [
2668+ {
2669+ "device": "sda",
2670+ "serial": "serial-a",
2671+ "multipath": "mpatha",
2672+ "host_wwnn": "[undef]",
2673+ "target_wwnn": "[undef]",
2674+ "host_wwpn": "[undef]",
2675+ "target_wwpn": "[undef]",
2676+ "host_adapter": "[undef]"
2677+ },
2678+ {
2679+ "device": "sdb",
2680+ "serial": "serial-a",
2681+ "multipath": "mpatha",
2682+ "host_wwnn": "[undef]",
2683+ "target_wwnn": "[undef]",
2684+ "host_wwpn": "[undef]",
2685+ "target_wwpn": "[undef]",
2686+ "host_adapter": "[undef]"
2687+ }
2688+ ]
2689+ },
2690+ "dmcrypt": {},
2691+ "blockdev": {
2692+ "/dev/sr0": {
2693+ "DEVLINKS": "/dev/disk/by-label/Ubuntu-Server\\x2019.10\\x20amd64 /dev/dvd /dev/disk/by-uuid/2019-08-11-07-41-33-00 /dev/disk/by-id/ata-QEMU_DVD-ROM_QM00003 /dev/cdrom /dev/disk/by-path/pci-0000:00:01.1-ata-2",
2694+ "DEVNAME": "/dev/sr0",
2695+ "DEVPATH": "/devices/pci0000:00/0000:00:01.1/ata2/host1/target1:0:0/1:0:0:0/block/sr0",
2696+ "DEVTYPE": "disk",
2697+ "ID_ATA": "1",
2698+ "ID_BUS": "ata",
2699+ "ID_CDROM": "1",
2700+ "ID_CDROM_DVD": "1",
2701+ "ID_CDROM_MEDIA": "1",
2702+ "ID_CDROM_MEDIA_CD": "1",
2703+ "ID_CDROM_MEDIA_SESSION_COUNT": "1",
2704+ "ID_CDROM_MEDIA_TRACK_COUNT": "1",
2705+ "ID_CDROM_MEDIA_TRACK_COUNT_DATA": "1",
2706+ "ID_CDROM_MRW": "1",
2707+ "ID_CDROM_MRW_W": "1",
2708+ "ID_FOR_SEAT": "block-pci-0000_00_01_1-ata-2",
2709+ "ID_FS_BOOT_SYSTEM_ID": "EL\\x20TORITO\\x20SPECIFICATION",
2710+ "ID_FS_LABEL": "Ubuntu-Server_19.10_amd64",
2711+ "ID_FS_LABEL_ENC": "Ubuntu-Server\\x2019.10\\x20amd64",
2712+ "ID_FS_TYPE": "iso9660",
2713+ "ID_FS_USAGE": "filesystem",
2714+ "ID_FS_UUID": "2019-08-11-07-41-33-00",
2715+ "ID_FS_UUID_ENC": "2019-08-11-07-41-33-00",
2716+ "ID_FS_VERSION": "Joliet Extension",
2717+ "ID_MODEL": "QEMU_DVD-ROM",
2718+ "ID_MODEL_ENC": "QEMU\\x20DVD-ROM\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20",
2719+ "ID_PART_TABLE_TYPE": "dos",
2720+ "ID_PART_TABLE_UUID": "6612a5ed",
2721+ "ID_PATH": "pci-0000:00:01.1-ata-2",
2722+ "ID_PATH_TAG": "pci-0000_00_01_1-ata-2",
2723+ "ID_REVISION": "2.5+",
2724+ "ID_SCSI": "1",
2725+ "ID_SCSI_INQUIRY": "1",
2726+ "ID_SERIAL": "QEMU_DVD-ROM_QM00003",
2727+ "ID_SERIAL_SHORT": "QM00003",
2728+ "ID_TYPE": "cd",
2729+ "ID_VENDOR": "QEMU",
2730+ "ID_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20",
2731+ "MAJOR": "11",
2732+ "MINOR": "0",
2733+ "SCSI_MODEL": "QEMU_DVD-ROM",
2734+ "SCSI_MODEL_ENC": "QEMU\\x20DVD-ROM\\x20\\x20\\x20\\x20",
2735+ "SCSI_REVISION": "2.5+",
2736+ "SCSI_TPGS": "0",
2737+ "SCSI_TYPE": "cd/dvd",
2738+ "SCSI_VENDOR": "QEMU",
2739+ "SCSI_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20",
2740+ "SUBSYSTEM": "block",
2741+ "SYSTEMD_MOUNT_DEVICE_BOUND": "1",
2742+ "TAGS": ":systemd:uaccess:seat:",
2743+ "USEC_INITIALIZED": "1162968",
2744+ "attrs": {
2745+ "alignment_offset": "0",
2746+ "bdi": null,
2747+ "capability": "119",
2748+ "dev": "11:0",
2749+ "device": null,
2750+ "discard_alignment": "0",
2751+ "events": "media_change eject_request",
2752+ "events_async": "",
2753+ "events_poll_msecs": "-1",
2754+ "ext_range": "1",
2755+ "hidden": "0",
2756+ "inflight": " 0 0",
2757+ "range": "1",
2758+ "removable": "1",
2759+ "ro": "0",
2760+ "size": "2881486848",
2761+ "stat": " 3177 16 427476 210179 0 0 0 0 0 6880 207800 0 0 0 0",
2762+ "subsystem": "block",
2763+ "uevent": "MAJOR=11\nMINOR=0\nDEVNAME=sr0\nDEVTYPE=disk"
2764+ },
2765+ "partitiontable": {
2766+ "label": "dos",
2767+ "id": "0x6612a5ed",
2768+ "device": "/dev/sr0",
2769+ "unit": "sectors",
2770+ "partitions": [
2771+ {
2772+ "node": "/dev/sr0p1",
2773+ "start": 0,
2774+ "size": 1406976,
2775+ "type": "0",
2776+ "bootable": true
2777+ },
2778+ {
2779+ "node": "/dev/sr0p2",
2780+ "start": 790864,
2781+ "size": 7936,
2782+ "type": "ef"
2783+ }
2784+ ]
2785+ }
2786+ },
2787+ "/dev/sda": {
2788+ "DEVLINKS": "/dev/disk/by-id/scsi-30000000000000064 /dev/disk/by-path/pci-0000:00:04.0-scsi-0:0:0:0 /dev/disk/by-id/scsi-SQEMU_QEMU_HARDDISK_serial-a /dev/disk/by-id/wwn-0x0000000000000064 /dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_serial-a",
2789+ "DEVNAME": "/dev/sda",
2790+ "DEVPATH": "/devices/pci0000:00/0000:00:04.0/virtio0/host2/target2:0:0/2:0:0:0/block/sda",
2791+ "DEVTYPE": "disk",
2792+ "DM_DEL_PART_NODES": "1",
2793+ "DM_MULTIPATH_DEVICE_PATH": "1",
2794+ "ID_BUS": "scsi",
2795+ "ID_FS_TYPE": "mpath_member",
2796+ "ID_MODEL": "QEMU_HARDDISK",
2797+ "ID_MODEL_ENC": "QEMU\\x20HARDDISK\\x20\\x20\\x20",
2798+ "ID_PART_TABLE_TYPE": "gpt",
2799+ "ID_PART_TABLE_UUID": "8261cd75-2234-4dbd-920a-d21a7c083c94",
2800+ "ID_PATH": "pci-0000:00:04.0-scsi-0:0:0:0",
2801+ "ID_PATH_TAG": "pci-0000_00_04_0-scsi-0_0_0_0",
2802+ "ID_REVISION": "2.5+",
2803+ "ID_SCSI": "1",
2804+ "ID_SCSI_INQUIRY": "1",
2805+ "ID_SERIAL": "30000000000000064",
2806+ "ID_SERIAL_SHORT": "0000000000000064",
2807+ "ID_TYPE": "disk",
2808+ "ID_VENDOR": "QEMU",
2809+ "ID_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20",
2810+ "ID_WWN": "0x0000000000000064",
2811+ "ID_WWN_WITH_EXTENSION": "0x0000000000000064",
2812+ "MAJOR": "8",
2813+ "MINOR": "0",
2814+ "MPATH_SBIN_PATH": "/sbin",
2815+ "SCSI_IDENT_LUN_NAA_LOCAL": "0000000000000064",
2816+ "SCSI_IDENT_LUN_VENDOR": "serial-a",
2817+ "SCSI_IDENT_SERIAL": "serial-a",
2818+ "SCSI_MODEL": "QEMU_HARDDISK",
2819+ "SCSI_MODEL_ENC": "QEMU\\x20HARDDISK\\x20\\x20\\x20",
2820+ "SCSI_REVISION": "2.5+",
2821+ "SCSI_TPGS": "0",
2822+ "SCSI_TYPE": "disk",
2823+ "SCSI_VENDOR": "QEMU",
2824+ "SCSI_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20",
2825+ "SUBSYSTEM": "block",
2826+ "SYSTEMD_READY": "0",
2827+ "TAGS": ":systemd:",
2828+ "USEC_INITIALIZED": "1357719",
2829+ "attrs": {
2830+ "alignment_offset": "0",
2831+ "bdi": null,
2832+ "capability": "50",
2833+ "dev": "8:0",
2834+ "device": null,
2835+ "discard_alignment": "0",
2836+ "events": "",
2837+ "events_async": "",
2838+ "events_poll_msecs": "-1",
2839+ "ext_range": "256",
2840+ "hidden": "0",
2841+ "inflight": " 0 0",
2842+ "range": "16",
2843+ "removable": "0",
2844+ "ro": "0",
2845+ "size": "10737418240",
2846+ "stat": " 820 0 37338 127 0 0 0 0 0 452 4 0 0 0 0",
2847+ "subsystem": "block",
2848+ "uevent": "MAJOR=8\nMINOR=0\nDEVNAME=sda\nDEVTYPE=disk"
2849+ },
2850+ "partitiontable": {
2851+ "label": "gpt",
2852+ "id": "8261CD75-2234-4DBD-920A-D21A7C083C94",
2853+ "device": "/dev/sda",
2854+ "unit": "sectors",
2855+ "firstlba": 34,
2856+ "lastlba": 20971486,
2857+ "partitions": [
2858+ {
2859+ "node": "/dev/sda1",
2860+ "start": 2048,
2861+ "size": 2048,
2862+ "type": "21686148-6449-6E6F-744E-656564454649",
2863+ "uuid": "8088175C-362A-4B46-9603-F3595065FA73"
2864+ },
2865+ {
2866+ "node": "/dev/sda2",
2867+ "start": 4096,
2868+ "size": 20965376,
2869+ "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
2870+ "uuid": "760493AC-7945-44C5-A6BD-58FCD6632EA7"
2871+ }
2872+ ]
2873+ }
2874+ },
2875+ "/dev/sda1": {
2876+ "DEVLINKS": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_serial-a-part1 /dev/disk/by-id/scsi-30000000000000064-part1 /dev/disk/by-path/pci-0000:00:04.0-scsi-0:0:0:0-part1 /dev/disk/by-id/scsi-SQEMU_QEMU_HARDDISK_serial-a-part1 /dev/disk/by-partuuid/8088175c-362a-4b46-9603-f3595065fa73 /dev/disk/by-id/wwn-0x0000000000000064-part1",
2877+ "DEVNAME": "/dev/sda1",
2878+ "DEVPATH": "/devices/pci0000:00/0000:00:04.0/virtio0/host2/target2:0:0/2:0:0:0/block/sda/sda1",
2879+ "DEVTYPE": "partition",
2880+ "DM_MULTIPATH_DEVICE_PATH": "1",
2881+ "ID_BUS": "scsi",
2882+ "ID_FS_TYPE": "mpath_member",
2883+ "ID_MODEL": "QEMU_HARDDISK",
2884+ "ID_MODEL_ENC": "QEMU\\x20HARDDISK\\x20\\x20\\x20",
2885+ "ID_PART_ENTRY_DISK": "8:0",
2886+ "ID_PART_ENTRY_NUMBER": "1",
2887+ "ID_PART_ENTRY_OFFSET": "2048",
2888+ "ID_PART_ENTRY_SCHEME": "gpt",
2889+ "ID_PART_ENTRY_SIZE": "2048",
2890+ "ID_PART_ENTRY_TYPE": "21686148-6449-6e6f-744e-656564454649",
2891+ "ID_PART_ENTRY_UUID": "8088175c-362a-4b46-9603-f3595065fa73",
2892+ "ID_PART_TABLE_TYPE": "gpt",
2893+ "ID_PART_TABLE_UUID": "8261cd75-2234-4dbd-920a-d21a7c083c94",
2894+ "ID_PATH": "pci-0000:00:04.0-scsi-0:0:0:0",
2895+ "ID_PATH_TAG": "pci-0000_00_04_0-scsi-0_0_0_0",
2896+ "ID_REVISION": "2.5+",
2897+ "ID_SCSI": "1",
2898+ "ID_SCSI_INQUIRY": "1",
2899+ "ID_SERIAL": "30000000000000064",
2900+ "ID_SERIAL_SHORT": "0000000000000064",
2901+ "ID_TYPE": "disk",
2902+ "ID_VENDOR": "QEMU",
2903+ "ID_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20",
2904+ "ID_WWN": "0x0000000000000064",
2905+ "ID_WWN_WITH_EXTENSION": "0x0000000000000064",
2906+ "MAJOR": "8",
2907+ "MINOR": "1",
2908+ "PARTN": "1",
2909+ "SCSI_IDENT_LUN_NAA_LOCAL": "0000000000000064",
2910+ "SCSI_IDENT_LUN_VENDOR": "serial-a",
2911+ "SCSI_IDENT_SERIAL": "serial-a",
2912+ "SCSI_MODEL": "QEMU_HARDDISK",
2913+ "SCSI_MODEL_ENC": "QEMU\\x20HARDDISK\\x20\\x20\\x20",
2914+ "SCSI_REVISION": "2.5+",
2915+ "SCSI_TPGS": "0",
2916+ "SCSI_TYPE": "disk",
2917+ "SCSI_VENDOR": "QEMU",
2918+ "SCSI_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20",
2919+ "SUBSYSTEM": "block",
2920+ "SYSTEMD_READY": "0",
2921+ "TAGS": ":systemd:",
2922+ "USEC_INITIALIZED": "1409047",
2923+ "attrs": {
2924+ "alignment_offset": "0",
2925+ "dev": "8:1",
2926+ "discard_alignment": "0",
2927+ "inflight": " 0 0",
2928+ "partition": "1",
2929+ "ro": "0",
2930+ "size": "1048576",
2931+ "start": "2048",
2932+ "stat": " 167 0 1360 14 0 0 0 0 0 172 0 0 0 0 0",
2933+ "subsystem": "block",
2934+ "uevent": "MAJOR=8\nMINOR=1\nDEVNAME=sda1\nDEVTYPE=partition\nPARTN=1"
2935+ }
2936+ },
2937+ "/dev/sda2": {
2938+ "DEVLINKS": "/dev/disk/by-id/wwn-0x0000000000000064-part2 /dev/disk/by-id/scsi-SQEMU_QEMU_HARDDISK_serial-a-part2 /dev/disk/by-uuid/80ca57a0-60b7-4328-be41-afedf915effd /dev/disk/by-partuuid/760493ac-7945-44c5-a6bd-58fcd6632ea7 /dev/disk/by-path/pci-0000:00:04.0-scsi-0:0:0:0-part2 /dev/disk/by-id/scsi-30000000000000064-part2 /dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_serial-a-part2",
2939+ "DEVNAME": "/dev/sda2",
2940+ "DEVPATH": "/devices/pci0000:00/0000:00:04.0/virtio0/host2/target2:0:0/2:0:0:0/block/sda/sda2",
2941+ "DEVTYPE": "partition",
2942+ "DM_MULTIPATH_DEVICE_PATH": "1",
2943+ "ID_BUS": "scsi",
2944+ "ID_FS_TYPE": "ext4",
2945+ "ID_FS_USAGE": "filesystem",
2946+ "ID_FS_UUID": "80ca57a0-60b7-4328-be41-afedf915effd",
2947+ "ID_FS_UUID_ENC": "80ca57a0-60b7-4328-be41-afedf915effd",
2948+ "ID_FS_VERSION": "1.0",
2949+ "ID_MODEL": "QEMU_HARDDISK",
2950+ "ID_MODEL_ENC": "QEMU\\x20HARDDISK\\x20\\x20\\x20",
2951+ "ID_PART_ENTRY_DISK": "8:0",
2952+ "ID_PART_ENTRY_NUMBER": "2",
2953+ "ID_PART_ENTRY_OFFSET": "4096",
2954+ "ID_PART_ENTRY_SCHEME": "gpt",
2955+ "ID_PART_ENTRY_SIZE": "20965376",
2956+ "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4",
2957+ "ID_PART_ENTRY_UUID": "760493ac-7945-44c5-a6bd-58fcd6632ea7",
2958+ "ID_PART_TABLE_TYPE": "gpt",
2959+ "ID_PART_TABLE_UUID": "8261cd75-2234-4dbd-920a-d21a7c083c94",
2960+ "ID_PATH": "pci-0000:00:04.0-scsi-0:0:0:0",
2961+ "ID_PATH_TAG": "pci-0000_00_04_0-scsi-0_0_0_0",
2962+ "ID_REVISION": "2.5+",
2963+ "ID_SCSI": "1",
2964+ "ID_SCSI_INQUIRY": "1",
2965+ "ID_SERIAL": "30000000000000064",
2966+ "ID_SERIAL_SHORT": "0000000000000064",
2967+ "ID_TYPE": "disk",
2968+ "ID_VENDOR": "QEMU",
2969+ "ID_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20",
2970+ "ID_WWN": "0x0000000000000064",
2971+ "ID_WWN_WITH_EXTENSION": "0x0000000000000064",
2972+ "MAJOR": "8",
2973+ "MINOR": "2",
2974+ "PARTN": "2",
2975+ "SCSI_IDENT_LUN_NAA_LOCAL": "0000000000000064",
2976+ "SCSI_IDENT_LUN_VENDOR": "serial-a",
2977+ "SCSI_IDENT_SERIAL": "serial-a",
2978+ "SCSI_MODEL": "QEMU_HARDDISK",
2979+ "SCSI_MODEL_ENC": "QEMU\\x20HARDDISK\\x20\\x20\\x20",
2980+ "SCSI_REVISION": "2.5+",
2981+ "SCSI_TPGS": "0",
2982+ "SCSI_TYPE": "disk",
2983+ "SCSI_VENDOR": "QEMU",
2984+ "SCSI_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20",
2985+ "SUBSYSTEM": "block",
2986+ "SYSTEMD_READY": "0",
2987+ "TAGS": ":systemd:",
2988+ "USEC_INITIALIZED": "1364238",
2989+ "attrs": {
2990+ "alignment_offset": "0",
2991+ "dev": "8:2",
2992+ "discard_alignment": "0",
2993+ "inflight": " 0 0",
2994+ "partition": "2",
2995+ "ro": "0",
2996+ "size": "10734272512",
2997+ "start": "4096",
2998+ "stat": " 268 0 17138 61 0 0 0 0 0 156 4 0 0 0 0",
2999+ "subsystem": "block",
3000+ "uevent": "MAJOR=8\nMINOR=2\nDEVNAME=sda2\nDEVTYPE=partition\nPARTN=2"
3001+ }
3002+ },
3003+ "/dev/sdb": {
3004+ "DEVLINKS": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_serial-a /dev/disk/by-id/scsi-30000000000000064 /dev/disk/by-id/wwn-0x0000000000000064 /dev/disk/by-path/pci-0000:00:04.0-scsi-0:0:1:0 /dev/disk/by-id/scsi-SQEMU_QEMU_HARDDISK_serial-a",
3005+ "DEVNAME": "/dev/sdb",
3006+ "DEVPATH": "/devices/pci0000:00/0000:00:04.0/virtio0/host2/target2:0:1/2:0:1:0/block/sdb",
3007+ "DEVTYPE": "disk",
3008+ "DM_DEL_PART_NODES": "1",
3009+ "DM_MULTIPATH_DEVICE_PATH": "1",
3010+ "ID_BUS": "scsi",
3011+ "ID_FS_TYPE": "mpath_member",
3012+ "ID_MODEL": "QEMU_HARDDISK",
3013+ "ID_MODEL_ENC": "QEMU\\x20HARDDISK\\x20\\x20\\x20",
3014+ "ID_PART_TABLE_TYPE": "gpt",
3015+ "ID_PART_TABLE_UUID": "8261cd75-2234-4dbd-920a-d21a7c083c94",
3016+ "ID_PATH": "pci-0000:00:04.0-scsi-0:0:1:0",
3017+ "ID_PATH_TAG": "pci-0000_00_04_0-scsi-0_0_1_0",
3018+ "ID_REVISION": "2.5+",
3019+ "ID_SCSI": "1",
3020+ "ID_SCSI_INQUIRY": "1",
3021+ "ID_SERIAL": "30000000000000064",
3022+ "ID_SERIAL_SHORT": "0000000000000064",
3023+ "ID_TYPE": "disk",
3024+ "ID_VENDOR": "QEMU",
3025+ "ID_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20",
3026+ "ID_WWN": "0x0000000000000064",
3027+ "ID_WWN_WITH_EXTENSION": "0x0000000000000064",
3028+ "MAJOR": "8",
3029+ "MINOR": "16",
3030+ "MPATH_SBIN_PATH": "/sbin",
3031+ "SCSI_IDENT_LUN_NAA_LOCAL": "0000000000000064",
3032+ "SCSI_IDENT_LUN_VENDOR": "serial-a",
3033+ "SCSI_IDENT_SERIAL": "serial-a",
3034+ "SCSI_MODEL": "QEMU_HARDDISK",
3035+ "SCSI_MODEL_ENC": "QEMU\\x20HARDDISK\\x20\\x20\\x20",
3036+ "SCSI_REVISION": "2.5+",
3037+ "SCSI_TPGS": "0",
3038+ "SCSI_TYPE": "disk",
3039+ "SCSI_VENDOR": "QEMU",
3040+ "SCSI_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20",
3041+ "SUBSYSTEM": "block",
3042+ "SYSTEMD_READY": "0",
3043+ "TAGS": ":systemd:",
3044+ "USEC_INITIALIZED": "1342677",
3045+ "attrs": {
3046+ "alignment_offset": "0",
3047+ "bdi": null,
3048+ "capability": "50",
3049+ "dev": "8:16",
3050+ "device": null,
3051+ "discard_alignment": "0",
3052+ "events": "",
3053+ "events_async": "",
3054+ "events_poll_msecs": "-1",
3055+ "ext_range": "256",
3056+ "hidden": "0",
3057+ "inflight": " 0 0",
3058+ "range": "16",
3059+ "removable": "0",
3060+ "ro": "0",
3061+ "size": "10737418240",
3062+ "stat": " 460 0 20312 70 0 0 0 0 0 280 12 0 0 0 0",
3063+ "subsystem": "block",
3064+ "uevent": "MAJOR=8\nMINOR=16\nDEVNAME=sdb\nDEVTYPE=disk"
3065+ },
3066+ "partitiontable": {
3067+ "label": "gpt",
3068+ "id": "8261CD75-2234-4DBD-920A-D21A7C083C94",
3069+ "device": "/dev/sdb",
3070+ "unit": "sectors",
3071+ "firstlba": 34,
3072+ "lastlba": 20971486,
3073+ "partitions": [
3074+ {
3075+ "node": "/dev/sdb1",
3076+ "start": 2048,
3077+ "size": 2048,
3078+ "type": "21686148-6449-6E6F-744E-656564454649",
3079+ "uuid": "8088175C-362A-4B46-9603-F3595065FA73"
3080+ },
3081+ {
3082+ "node": "/dev/sdb2",
3083+ "start": 4096,
3084+ "size": 20965376,
3085+ "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
3086+ "uuid": "760493AC-7945-44C5-A6BD-58FCD6632EA7"
3087+ }
3088+ ]
3089+ }
3090+ },
3091+ "/dev/sdb1": {
3092+ "DEVLINKS": "/dev/disk/by-path/pci-0000:00:04.0-scsi-0:0:1:0-part1 /dev/disk/by-id/scsi-30000000000000064-part1 /dev/disk/by-partuuid/8088175c-362a-4b46-9603-f3595065fa73 /dev/disk/by-id/scsi-SQEMU_QEMU_HARDDISK_serial-a-part1 /dev/disk/by-id/wwn-0x0000000000000064-part1 /dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_serial-a-part1",
3093+ "DEVNAME": "/dev/sdb1",
3094+ "DEVPATH": "/devices/pci0000:00/0000:00:04.0/virtio0/host2/target2:0:1/2:0:1:0/block/sdb/sdb1",
3095+ "DEVTYPE": "partition",
3096+ "DM_MULTIPATH_DEVICE_PATH": "1",
3097+ "ID_BUS": "scsi",
3098+ "ID_FS_TYPE": "mpath_member",
3099+ "ID_MODEL": "QEMU_HARDDISK",
3100+ "ID_MODEL_ENC": "QEMU\\x20HARDDISK\\x20\\x20\\x20",
3101+ "ID_PART_ENTRY_DISK": "8:16",
3102+ "ID_PART_ENTRY_NUMBER": "1",
3103+ "ID_PART_ENTRY_OFFSET": "2048",
3104+ "ID_PART_ENTRY_SCHEME": "gpt",
3105+ "ID_PART_ENTRY_SIZE": "2048",
3106+ "ID_PART_ENTRY_TYPE": "21686148-6449-6e6f-744e-656564454649",
3107+ "ID_PART_ENTRY_UUID": "8088175c-362a-4b46-9603-f3595065fa73",
3108+ "ID_PART_TABLE_TYPE": "gpt",
3109+ "ID_PART_TABLE_UUID": "8261cd75-2234-4dbd-920a-d21a7c083c94",
3110+ "ID_PATH": "pci-0000:00:04.0-scsi-0:0:1:0",
3111+ "ID_PATH_TAG": "pci-0000_00_04_0-scsi-0_0_1_0",
3112+ "ID_REVISION": "2.5+",
3113+ "ID_SCSI": "1",
3114+ "ID_SCSI_INQUIRY": "1",
3115+ "ID_SERIAL": "30000000000000064",
3116+ "ID_SERIAL_SHORT": "0000000000000064",
3117+ "ID_TYPE": "disk",
3118+ "ID_VENDOR": "QEMU",
3119+ "ID_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20",
3120+ "ID_WWN": "0x0000000000000064",
3121+ "ID_WWN_WITH_EXTENSION": "0x0000000000000064",
3122+ "MAJOR": "8",
3123+ "MINOR": "17",
3124+ "PARTN": "1",
3125+ "SCSI_IDENT_LUN_NAA_LOCAL": "0000000000000064",
3126+ "SCSI_IDENT_LUN_VENDOR": "serial-a",
3127+ "SCSI_IDENT_SERIAL": "serial-a",
3128+ "SCSI_MODEL": "QEMU_HARDDISK",
3129+ "SCSI_MODEL_ENC": "QEMU\\x20HARDDISK\\x20\\x20\\x20",
3130+ "SCSI_REVISION": "2.5+",
3131+ "SCSI_TPGS": "0",
3132+ "SCSI_TYPE": "disk",
3133+ "SCSI_VENDOR": "QEMU",
3134+ "SCSI_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20",
3135+ "SUBSYSTEM": "block",
3136+ "SYSTEMD_READY": "0",
3137+ "TAGS": ":systemd:",
3138+ "USEC_INITIALIZED": "1383416",
3139+ "attrs": {
3140+ "alignment_offset": "0",
3141+ "dev": "8:17",
3142+ "discard_alignment": "0",
3143+ "inflight": " 0 0",
3144+ "partition": "1",
3145+ "ro": "0",
3146+ "size": "1048576",
3147+ "start": "2048",
3148+ "stat": " 86 0 712 7 0 0 0 0 0 72 0 0 0 0 0",
3149+ "subsystem": "block",
3150+ "uevent": "MAJOR=8\nMINOR=17\nDEVNAME=sdb1\nDEVTYPE=partition\nPARTN=1"
3151+ }
3152+ },
3153+ "/dev/sdb2": {
3154+ "DEVLINKS": "/dev/disk/by-id/wwn-0x0000000000000064-part2 /dev/disk/by-id/scsi-SQEMU_QEMU_HARDDISK_serial-a-part2 /dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_serial-a-part2 /dev/disk/by-partuuid/760493ac-7945-44c5-a6bd-58fcd6632ea7 /dev/disk/by-path/pci-0000:00:04.0-scsi-0:0:1:0-part2 /dev/disk/by-uuid/80ca57a0-60b7-4328-be41-afedf915effd /dev/disk/by-id/scsi-30000000000000064-part2",
3155+ "DEVNAME": "/dev/sdb2",
3156+ "DEVPATH": "/devices/pci0000:00/0000:00:04.0/virtio0/host2/target2:0:1/2:0:1:0/block/sdb/sdb2",
3157+ "DEVTYPE": "partition",
3158+ "DM_MULTIPATH_DEVICE_PATH": "1",
3159+ "ID_BUS": "scsi",
3160+ "ID_FS_TYPE": "ext4",
3161+ "ID_FS_USAGE": "filesystem",
3162+ "ID_FS_UUID": "80ca57a0-60b7-4328-be41-afedf915effd",
3163+ "ID_FS_UUID_ENC": "80ca57a0-60b7-4328-be41-afedf915effd",
3164+ "ID_FS_VERSION": "1.0",
3165+ "ID_MODEL": "QEMU_HARDDISK",
3166+ "ID_MODEL_ENC": "QEMU\\x20HARDDISK\\x20\\x20\\x20",
3167+ "ID_PART_ENTRY_DISK": "8:16",
3168+ "ID_PART_ENTRY_NUMBER": "2",
3169+ "ID_PART_ENTRY_OFFSET": "4096",
3170+ "ID_PART_ENTRY_SCHEME": "gpt",
3171+ "ID_PART_ENTRY_SIZE": "20965376",
3172+ "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4",
3173+ "ID_PART_ENTRY_UUID": "760493ac-7945-44c5-a6bd-58fcd6632ea7",
3174+ "ID_PART_TABLE_TYPE": "gpt",
3175+ "ID_PART_TABLE_UUID": "8261cd75-2234-4dbd-920a-d21a7c083c94",
3176+ "ID_PATH": "pci-0000:00:04.0-scsi-0:0:1:0",
3177+ "ID_PATH_TAG": "pci-0000_00_04_0-scsi-0_0_1_0",
3178+ "ID_REVISION": "2.5+",
3179+ "ID_SCSI": "1",
3180+ "ID_SCSI_INQUIRY": "1",
3181+ "ID_SERIAL": "30000000000000064",
3182+ "ID_SERIAL_SHORT": "0000000000000064",
3183+ "ID_TYPE": "disk",
3184+ "ID_VENDOR": "QEMU",
3185+ "ID_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20",
3186+ "ID_WWN": "0x0000000000000064",
3187+ "ID_WWN_WITH_EXTENSION": "0x0000000000000064",
3188+ "MAJOR": "8",
3189+ "MINOR": "18",
3190+ "PARTN": "2",
3191+ "SCSI_IDENT_LUN_NAA_LOCAL": "0000000000000064",
3192+ "SCSI_IDENT_LUN_VENDOR": "serial-a",
3193+ "SCSI_IDENT_SERIAL": "serial-a",
3194+ "SCSI_MODEL": "QEMU_HARDDISK",
3195+ "SCSI_MODEL_ENC": "QEMU\\x20HARDDISK\\x20\\x20\\x20",
3196+ "SCSI_REVISION": "2.5+",
3197+ "SCSI_TPGS": "0",
3198+ "SCSI_TYPE": "disk",
3199+ "SCSI_VENDOR": "QEMU",
3200+ "SCSI_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20",
3201+ "SUBSYSTEM": "block",
3202+ "SYSTEMD_READY": "0",
3203+ "TAGS": ":systemd:",
3204+ "USEC_INITIALIZED": "1355435",
3205+ "attrs": {
3206+ "alignment_offset": "0",
3207+ "dev": "8:18",
3208+ "discard_alignment": "0",
3209+ "inflight": " 0 0",
3210+ "partition": "2",
3211+ "ro": "0",
3212+ "size": "10734272512",
3213+ "start": "4096",
3214+ "stat": " 129 0 8728 20 0 0 0 0 0 96 4 0 0 0 0",
3215+ "subsystem": "block",
3216+ "uevent": "MAJOR=8\nMINOR=18\nDEVNAME=sdb2\nDEVTYPE=partition\nPARTN=2"
3217+ }
3218+ },
3219+ "/dev/fd0": {
3220+ "DEVNAME": "/dev/fd0",
3221+ "DEVPATH": "/devices/platform/floppy.0/block/fd0",
3222+ "DEVTYPE": "disk",
3223+ "MAJOR": "2",
3224+ "MINOR": "0",
3225+ "SUBSYSTEM": "block",
3226+ "TAGS": ":systemd:",
3227+ "USEC_INITIALIZED": "1182861",
3228+ "attrs": {
3229+ "alignment_offset": "0",
3230+ "bdi": null,
3231+ "capability": "11",
3232+ "dev": "2:0",
3233+ "device": null,
3234+ "discard_alignment": "0",
3235+ "events": "",
3236+ "events_async": "",
3237+ "events_poll_msecs": "-1",
3238+ "ext_range": "1",
3239+ "hidden": "0",
3240+ "inflight": " 0 0",
3241+ "range": "1",
3242+ "removable": "1",
3243+ "ro": "0",
3244+ "size": "4096",
3245+ "stat": " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0",
3246+ "subsystem": "block",
3247+ "uevent": "MAJOR=2\nMINOR=0\nDEVNAME=fd0\nDEVTYPE=disk"
3248+ }
3249+ },
3250+ "/dev/dm-0": {
3251+ "DEVLINKS": "/dev/disk/by-id/wwn-0x0000000000000064 /dev/disk/by-id/dm-name-mpatha /dev/disk/by-id/dm-uuid-mpath-30000000000000064 /dev/mapper/mpatha",
3252+ "DEVNAME": "/dev/dm-0",
3253+ "DEVPATH": "/devices/virtual/block/dm-0",
3254+ "DEVTYPE": "disk",
3255+ "DM_NAME": "mpatha",
3256+ "DM_STATE": "ACTIVE",
3257+ "DM_SUSPENDED": "0",
3258+ "DM_TABLE_STATE": "LIVE",
3259+ "DM_TYPE": "scsi",
3260+ "DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG": "1",
3261+ "DM_UDEV_PRIMARY_SOURCE_FLAG": "1",
3262+ "DM_UDEV_RULES": "1",
3263+ "DM_UDEV_RULES_VSN": "2",
3264+ "DM_UUID": "mpath-30000000000000064",
3265+ "DM_WWN": "0x0000000000000064",
3266+ "ID_PART_TABLE_TYPE": "gpt",
3267+ "ID_PART_TABLE_UUID": "8261cd75-2234-4dbd-920a-d21a7c083c94",
3268+ "MAJOR": "253",
3269+ "MINOR": "0",
3270+ "MPATH_DEVICE_READY": "1",
3271+ "MPATH_SBIN_PATH": "/sbin",
3272+ "SUBSYSTEM": "block",
3273+ "TAGS": ":systemd:",
3274+ "USEC_INITIALIZED": "9639027",
3275+ "attrs": {
3276+ "alignment_offset": "0",
3277+ "bdi": null,
3278+ "capability": "10",
3279+ "dev": "253:0",
3280+ "discard_alignment": "0",
3281+ "events": "",
3282+ "events_async": "",
3283+ "events_poll_msecs": "-1",
3284+ "ext_range": "1",
3285+ "hidden": "0",
3286+ "inflight": " 0 0",
3287+ "range": "1",
3288+ "removable": "0",
3289+ "ro": "0",
3290+ "size": "10737418240",
3291+ "stat": " 321 0 16720 46 0 0 0 0 0 172 0 0 0 0 0",
3292+ "subsystem": "block",
3293+ "uevent": "MAJOR=253\nMINOR=0\nDEVNAME=dm-0\nDEVTYPE=disk"
3294+ },
3295+ "partitiontable": {
3296+ "label": "gpt",
3297+ "id": "8261CD75-2234-4DBD-920A-D21A7C083C94",
3298+ "device": "/dev/dm-0",
3299+ "unit": "sectors",
3300+ "firstlba": 34,
3301+ "lastlba": 20971486,
3302+ "partitions": [
3303+ {
3304+ "node": "/dev/mapper/mpatha-part1",
3305+ "start": 2048,
3306+ "size": 2048,
3307+ "type": "21686148-6449-6E6F-744E-656564454649",
3308+ "uuid": "8088175C-362A-4B46-9603-F3595065FA73"
3309+ },
3310+ {
3311+ "node": "/dev/mapper/mpatha-part2",
3312+ "start": 4096,
3313+ "size": 20965376,
3314+ "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
3315+ "uuid": "760493AC-7945-44C5-A6BD-58FCD6632EA7"
3316+ }
3317+ ]
3318+ }
3319+ },
3320+ "/dev/dm-1": {
3321+ "DEVLINKS": "/dev/disk/by-id/dm-name-mpatha-part1 /dev/mapper/mpatha-part1 /dev/disk/by-id/wwn-0x0000000000000064-part1 /dev/disk/by-partuuid/8088175c-362a-4b46-9603-f3595065fa73 /dev/disk/by-id/dm-uuid-part1-mpath-30000000000000064",
3322+ "DEVNAME": "/dev/dm-1",
3323+ "DEVPATH": "/devices/virtual/block/dm-1",
3324+ "DEVTYPE": "disk",
3325+ "DM_ACTIVATION": "1",
3326+ "DM_MPATH": "mpatha",
3327+ "DM_NAME": "mpatha-part1",
3328+ "DM_PART": "1",
3329+ "DM_STATE": "ACTIVE",
3330+ "DM_SUBSYSTEM_UDEV_FLAG0": "1",
3331+ "DM_SUSPENDED": "0",
3332+ "DM_TABLE_STATE": "LIVE",
3333+ "DM_TYPE": "scsi",
3334+ "DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG": "1",
3335+ "DM_UDEV_PRIMARY_SOURCE_FLAG": "1",
3336+ "DM_UDEV_RULES": "1",
3337+ "DM_UDEV_RULES_VSN": "2",
3338+ "DM_UUID": "part1-mpath-30000000000000064",
3339+ "DM_WWN": "0x0000000000000064",
3340+ "ID_PART_ENTRY_DISK": "253:0",
3341+ "ID_PART_ENTRY_NUMBER": "1",
3342+ "ID_PART_ENTRY_OFFSET": "2048",
3343+ "ID_PART_ENTRY_SCHEME": "gpt",
3344+ "ID_PART_ENTRY_SIZE": "2048",
3345+ "ID_PART_ENTRY_TYPE": "21686148-6449-6e6f-744e-656564454649",
3346+ "ID_PART_ENTRY_UUID": "8088175c-362a-4b46-9603-f3595065fa73",
3347+ "MAJOR": "253",
3348+ "MINOR": "1",
3349+ "SUBSYSTEM": "block",
3350+ "TAGS": ":systemd:",
3351+ "USEC_INITIALIZED": "10556653",
3352+ "attrs": {
3353+ "alignment_offset": "0",
3354+ "bdi": null,
3355+ "capability": "10",
3356+ "dev": "253:1",
3357+ "discard_alignment": "0",
3358+ "events": "",
3359+ "events_async": "",
3360+ "events_poll_msecs": "-1",
3361+ "ext_range": "1",
3362+ "hidden": "0",
3363+ "inflight": " 0 0",
3364+ "range": "1",
3365+ "removable": "0",
3366+ "ro": "0",
3367+ "size": "1048576",
3368+ "stat": " 78 0 624 8 0 0 0 0 0 56 8 0 0 0 0",
3369+ "subsystem": "block",
3370+ "uevent": "MAJOR=253\nMINOR=1\nDEVNAME=dm-1\nDEVTYPE=disk"
3371+ }
3372+ },
3373+ "/dev/dm-2": {
3374+ "DEVLINKS": "/dev/mapper/mpatha-part2 /dev/disk/by-id/dm-uuid-part2-mpath-30000000000000064 /dev/disk/by-id/dm-name-mpatha-part2 /dev/disk/by-partuuid/760493ac-7945-44c5-a6bd-58fcd6632ea7 /dev/disk/by-uuid/80ca57a0-60b7-4328-be41-afedf915effd /dev/disk/by-id/wwn-0x0000000000000064-part2",
3375+ "DEVNAME": "/dev/dm-2",
3376+ "DEVPATH": "/devices/virtual/block/dm-2",
3377+ "DEVTYPE": "disk",
3378+ "DM_ACTIVATION": "1",
3379+ "DM_MPATH": "mpatha",
3380+ "DM_NAME": "mpatha-part2",
3381+ "DM_PART": "2",
3382+ "DM_STATE": "ACTIVE",
3383+ "DM_SUBSYSTEM_UDEV_FLAG0": "1",
3384+ "DM_SUSPENDED": "0",
3385+ "DM_TABLE_STATE": "LIVE",
3386+ "DM_TYPE": "scsi",
3387+ "DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG": "1",
3388+ "DM_UDEV_PRIMARY_SOURCE_FLAG": "1",
3389+ "DM_UDEV_RULES": "1",
3390+ "DM_UDEV_RULES_VSN": "2",
3391+ "DM_UUID": "part2-mpath-30000000000000064",
3392+ "DM_WWN": "0x0000000000000064",
3393+ "ID_FS_TYPE": "ext4",
3394+ "ID_FS_USAGE": "filesystem",
3395+ "ID_FS_UUID": "80ca57a0-60b7-4328-be41-afedf915effd",
3396+ "ID_FS_UUID_ENC": "80ca57a0-60b7-4328-be41-afedf915effd",
3397+ "ID_FS_VERSION": "1.0",
3398+ "ID_PART_ENTRY_DISK": "253:0",
3399+ "ID_PART_ENTRY_NUMBER": "2",
3400+ "ID_PART_ENTRY_OFFSET": "4096",
3401+ "ID_PART_ENTRY_SCHEME": "gpt",
3402+ "ID_PART_ENTRY_SIZE": "20965376",
3403+ "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4",
3404+ "ID_PART_ENTRY_UUID": "760493ac-7945-44c5-a6bd-58fcd6632ea7",
3405+ "MAJOR": "253",
3406+ "MINOR": "2",
3407+ "SUBSYSTEM": "block",
3408+ "TAGS": ":systemd:",
3409+ "USEC_INITIALIZED": "10583306",
3410+ "attrs": {
3411+ "alignment_offset": "0",
3412+ "bdi": null,
3413+ "capability": "10",
3414+ "dev": "253:2",
3415+ "discard_alignment": "0",
3416+ "events": "",
3417+ "events_async": "",
3418+ "events_poll_msecs": "-1",
3419+ "ext_range": "1",
3420+ "hidden": "0",
3421+ "inflight": " 0 0",
3422+ "range": "1",
3423+ "removable": "0",
3424+ "ro": "0",
3425+ "size": "10734272512",
3426+ "stat": " 91 0 8032 4 0 0 0 0 0 52 4 0 0 0 0",
3427+ "subsystem": "block",
3428+ "uevent": "MAJOR=253\nMINOR=2\nDEVNAME=dm-2\nDEVTYPE=disk"
3429+ }
3430+ }
3431+ },
3432+ "bcache": {
3433+ "backing": {},
3434+ "caching": {}
3435+ },
3436+ "zfs": {
3437+ "zpools": {}
3438+ }
3439+}
3440diff --git a/tests/data/probert_storage_raid1_partitions.json b/tests/data/probert_storage_raid1_partitions.json
3441new file mode 100644
3442index 0000000..709da5a
3443--- /dev/null
3444+++ b/tests/data/probert_storage_raid1_partitions.json
3445@@ -0,0 +1,951 @@
3446+{
3447+ "zfs": {
3448+ "zpools": {}
3449+ },
3450+ "dmcrypt": {},
3451+ "blockdev": {
3452+ "/dev/sr0": {
3453+ "DEVLINKS": "/dev/disk/by-label/Ubuntu-Server\\x2020.04\\x20LTS\\x20ppc64 /dev/disk/by-id/scsi-0QEMU_QEMU_CD-ROM_drive-scsi0-0-0-0 /dev/dvd /dev/cdrom /dev/disk/by-path/pci-0000:00:02.0-scsi-0:0:0:0 /dev/disk/by-uuid/2019-11-16-08-09-20-00",
3454+ "DEVNAME": "/dev/sr0",
3455+ "DEVPATH": "/devices/pci0000:00/0000:00:02.0/virtio1/host0/target0:0:0/0:0:0:0/block/sr0",
3456+ "DEVTYPE": "disk",
3457+ "ID_BUS": "scsi",
3458+ "ID_CDROM": "1",
3459+ "ID_CDROM_CD": "1",
3460+ "ID_CDROM_DVD": "1",
3461+ "ID_CDROM_MEDIA": "1",
3462+ "ID_CDROM_MEDIA_DVD": "1",
3463+ "ID_CDROM_MEDIA_SESSION_COUNT": "1",
3464+ "ID_CDROM_MEDIA_STATE": "complete",
3465+ "ID_CDROM_MEDIA_TRACK_COUNT": "1",
3466+ "ID_CDROM_MEDIA_TRACK_COUNT_DATA": "1",
3467+ "ID_CDROM_MRW": "1",
3468+ "ID_CDROM_MRW_W": "1",
3469+ "ID_FOR_SEAT": "block-pci-0000_00_02_0-scsi-0_0_0_0",
3470+ "ID_FS_APPLICATION_ID": "GENISOIMAGE\\x20ISO\\x209660\\x2fHFS\\x20FILESYSTEM\\x20CREATOR\\x20\\x28C\\x29\\x201993\\x20E.YOUNGDALE\\x20\\x28C\\x29\\x201997-2006\\x20J.PEARSON\\x2fJ.SCHILLING\\x20\\x28C\\x29\\x202006-2007\\x20CDRKIT\\x20TEAM",
3471+ "ID_FS_LABEL": "Ubuntu-Server_20.04_LTS_ppc64",
3472+ "ID_FS_LABEL_ENC": "Ubuntu-Server\\x2020.04\\x20LTS\\x20ppc64",
3473+ "ID_FS_SYSTEM_ID": "LINUX",
3474+ "ID_FS_TYPE": "iso9660",
3475+ "ID_FS_USAGE": "filesystem",
3476+ "ID_FS_UUID": "2019-11-16-08-09-20-00",
3477+ "ID_FS_UUID_ENC": "2019-11-16-08-09-20-00",
3478+ "ID_MODEL": "QEMU_CD-ROM",
3479+ "ID_MODEL_ENC": "QEMU\\x20CD-ROM\\x20\\x20\\x20\\x20\\x20",
3480+ "ID_PART_TABLE_TYPE": "mac",
3481+ "ID_PATH": "pci-0000:00:02.0-scsi-0:0:0:0",
3482+ "ID_PATH_TAG": "pci-0000_00_02_0-scsi-0_0_0_0",
3483+ "ID_REVISION": "2.5+",
3484+ "ID_SCSI": "1",
3485+ "ID_SCSI_INQUIRY": "1",
3486+ "ID_SERIAL": "0QEMU_QEMU_CD-ROM_drive-scsi0-0-0-0",
3487+ "ID_SERIAL_SHORT": "drive-scsi0-0-0-0",
3488+ "ID_TYPE": "cd",
3489+ "ID_VENDOR": "QEMU",
3490+ "ID_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20",
3491+ "MAJOR": "11",
3492+ "MINOR": "0",
3493+ "SCSI_MODEL": "QEMU_CD-ROM",
3494+ "SCSI_MODEL_ENC": "QEMU\\x20CD-ROM\\x20\\x20\\x20\\x20\\x20",
3495+ "SCSI_REVISION": "2.5+",
3496+ "SCSI_TPGS": "0",
3497+ "SCSI_TYPE": "cd/dvd",
3498+ "SCSI_VENDOR": "QEMU",
3499+ "SCSI_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20",
3500+ "SUBSYSTEM": "block",
3501+ "SYSTEMD_MOUNT_DEVICE_BOUND": "1",
3502+ "TAGS": ":uaccess:seat:systemd:",
3503+ "USEC_INITIALIZED": "626053",
3504+ "attrs": {
3505+ "alignment_offset": "0",
3506+ "bdi": null,
3507+ "capability": "119",
3508+ "dev": "11:0",
3509+ "device": null,
3510+ "discard_alignment": "0",
3511+ "events": "media_change eject_request",
3512+ "events_async": "",
3513+ "events_poll_msecs": "-1",
3514+ "ext_range": "1",
3515+ "hidden": "0",
3516+ "inflight": " 0 0",
3517+ "range": "1",
3518+ "removable": "1",
3519+ "ro": "0",
3520+ "size": "911030272",
3521+ "stat": " 6887 0 1582024 636 0 0 0 0 0 17552 64 0 0 0 0",
3522+ "subsystem": "block",
3523+ "uevent": "MAJOR=11\nMINOR=0\nDEVNAME=sr0\nDEVTYPE=disk"
3524+ },
3525+ "partitiontable": {
3526+ "label": "dos",
3527+ "id": "0x64040020",
3528+ "device": "/dev/sr0",
3529+ "unit": "sectors",
3530+ "partitions": [
3531+ {
3532+ "node": "/dev/sr0p1",
3533+ "start": 0,
3534+ "size": 1778756,
3535+ "type": "96",
3536+ "bootable": true
3537+ },
3538+ {
3539+ "node": "/dev/sr0p2",
3540+ "start": 2129919,
3541+ "size": 1936615684,
3542+ "type": "ff"
3543+ },
3544+ {
3545+ "node": "/dev/sr0p3",
3546+ "start": 1024,
3547+ "size": 0,
3548+ "type": "0"
3549+ },
3550+ {
3551+ "node": "/dev/sr0p4",
3552+ "start": 0,
3553+ "size": 0,
3554+ "type": "0"
3555+ }
3556+ ]
3557+ }
3558+ },
3559+ "/dev/vda": {
3560+ "DEVLINKS": "/dev/disk/by-path/pci-0000:00:04.0 /dev/disk/by-path/virtio-pci-0000:00:04.0",
3561+ "DEVNAME": "/dev/vda",
3562+ "DEVPATH": "/devices/pci0000:00/0000:00:04.0/virtio2/block/vda",
3563+ "DEVTYPE": "disk",
3564+ "ID_PART_TABLE_TYPE": "gpt",
3565+ "ID_PART_TABLE_UUID": "c43bafba-6f3f-4ac7-8c3a-3808451ad55e",
3566+ "ID_PATH": "pci-0000:00:04.0",
3567+ "ID_PATH_TAG": "pci-0000_00_04_0",
3568+ "MAJOR": "252",
3569+ "MINOR": "0",
3570+ "SUBSYSTEM": "block",
3571+ "TAGS": ":systemd:",
3572+ "USEC_INITIALIZED": "592200",
3573+ "attrs": {
3574+ "alignment_offset": "0",
3575+ "bdi": null,
3576+ "cache_type": "write back",
3577+ "capability": "50",
3578+ "dev": "252:0",
3579+ "device": null,
3580+ "discard_alignment": "0",
3581+ "events": "",
3582+ "events_async": "",
3583+ "events_poll_msecs": "-1",
3584+ "ext_range": "256",
3585+ "hidden": "0",
3586+ "inflight": " 0 0",
3587+ "range": "16",
3588+ "removable": "0",
3589+ "ro": "0",
3590+ "serial": "",
3591+ "size": "6442450944",
3592+ "stat": " 2923 0 473854 187 1654 3072 402696 427 0 3300 12 0 0 0 0",
3593+ "subsystem": "block",
3594+ "uevent": "MAJOR=252\nMINOR=0\nDEVNAME=vda\nDEVTYPE=disk"
3595+ },
3596+ "partitiontable": {
3597+ "label": "gpt",
3598+ "id": "C43BAFBA-6F3F-4AC7-8C3A-3808451AD55E",
3599+ "device": "/dev/vda",
3600+ "unit": "sectors",
3601+ "firstlba": 34,
3602+ "lastlba": 12582878,
3603+ "partitions": [
3604+ {
3605+ "node": "/dev/vda1",
3606+ "start": 2048,
3607+ "size": 16384,
3608+ "type": "9E1A2D38-C612-4316-AA26-8B49521E5A8B",
3609+ "uuid": "CFECC68C-325E-4066-8F6F-0FE4F57D1AF5"
3610+ },
3611+ {
3612+ "node": "/dev/vda2",
3613+ "start": 18432,
3614+ "size": 2097152,
3615+ "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
3616+ "uuid": "D29ADB04-DF89-4D54-9B50-8DB8EEDAB339"
3617+ }
3618+ ]
3619+ }
3620+ },
3621+ "/dev/vda1": {
3622+ "DEVLINKS": "/dev/disk/by-path/pci-0000:00:04.0-part1 /dev/disk/by-partuuid/cfecc68c-325e-4066-8f6f-0fe4f57d1af5 /dev/disk/by-path/virtio-pci-0000:00:04.0-part1",
3623+ "DEVNAME": "/dev/vda1",
3624+ "DEVPATH": "/devices/pci0000:00/0000:00:04.0/virtio2/block/vda/vda1",
3625+ "DEVTYPE": "partition",
3626+ "ID_PART_ENTRY_DISK": "252:0",
3627+ "ID_PART_ENTRY_NUMBER": "1",
3628+ "ID_PART_ENTRY_OFFSET": "2048",
3629+ "ID_PART_ENTRY_SCHEME": "gpt",
3630+ "ID_PART_ENTRY_SIZE": "16384",
3631+ "ID_PART_ENTRY_TYPE": "9e1a2d38-c612-4316-aa26-8b49521e5a8b",
3632+ "ID_PART_ENTRY_UUID": "cfecc68c-325e-4066-8f6f-0fe4f57d1af5",
3633+ "ID_PART_TABLE_TYPE": "gpt",
3634+ "ID_PART_TABLE_UUID": "c43bafba-6f3f-4ac7-8c3a-3808451ad55e",
3635+ "ID_PATH": "pci-0000:00:04.0",
3636+ "ID_PATH_TAG": "pci-0000_00_04_0",
3637+ "ID_SCSI": "1",
3638+ "MAJOR": "252",
3639+ "MINOR": "1",
3640+ "PARTN": "1",
3641+ "SUBSYSTEM": "block",
3642+ "TAGS": ":systemd:",
3643+ "USEC_INITIALIZED": "62680508",
3644+ "attrs": {
3645+ "alignment_offset": "0",
3646+ "dev": "252:1",
3647+ "discard_alignment": "0",
3648+ "inflight": " 0 0",
3649+ "partition": "1",
3650+ "ro": "0",
3651+ "size": "8388608",
3652+ "start": "2048",
3653+ "stat": " 449 0 74496 31 6 3 1152 0 0 620 0 0 0 0 0",
3654+ "subsystem": "block",
3655+ "uevent": "MAJOR=252\nMINOR=1\nDEVNAME=vda1\nDEVTYPE=partition\nPARTN=1"
3656+ }
3657+ },
3658+ "/dev/vda2": {
3659+ "DEVLINKS": "/dev/disk/by-partuuid/d29adb04-df89-4d54-9b50-8db8eedab339 /dev/disk/by-uuid/0a3b5403-d358-4f30-9094-e5a19d60b222 /dev/disk/by-path/pci-0000:00:04.0-part2 /dev/disk/by-path/virtio-pci-0000:00:04.0-part2",
3660+ "DEVNAME": "/dev/vda2",
3661+ "DEVPATH": "/devices/pci0000:00/0000:00:04.0/virtio2/block/vda/vda2",
3662+ "DEVTYPE": "partition",
3663+ "ID_FS_TYPE": "ext4",
3664+ "ID_FS_USAGE": "filesystem",
3665+ "ID_FS_UUID": "0a3b5403-d358-4f30-9094-e5a19d60b222",
3666+ "ID_FS_UUID_ENC": "0a3b5403-d358-4f30-9094-e5a19d60b222",
3667+ "ID_FS_VERSION": "1.0",
3668+ "ID_PART_ENTRY_DISK": "252:0",
3669+ "ID_PART_ENTRY_NUMBER": "2",
3670+ "ID_PART_ENTRY_OFFSET": "18432",
3671+ "ID_PART_ENTRY_SCHEME": "gpt",
3672+ "ID_PART_ENTRY_SIZE": "2097152",
3673+ "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4",
3674+ "ID_PART_ENTRY_UUID": "d29adb04-df89-4d54-9b50-8db8eedab339",
3675+ "ID_PART_TABLE_TYPE": "gpt",
3676+ "ID_PART_TABLE_UUID": "c43bafba-6f3f-4ac7-8c3a-3808451ad55e",
3677+ "ID_PATH": "pci-0000:00:04.0",
3678+ "ID_PATH_TAG": "pci-0000_00_04_0",
3679+ "ID_SCSI": "1",
3680+ "MAJOR": "252",
3681+ "MINOR": "2",
3682+ "PARTN": "2",
3683+ "SUBSYSTEM": "block",
3684+ "TAGS": ":systemd:",
3685+ "USEC_INITIALIZED": "62650105",
3686+ "attrs": {
3687+ "alignment_offset": "0",
3688+ "dev": "252:2",
3689+ "discard_alignment": "0",
3690+ "inflight": " 0 0",
3691+ "partition": "2",
3692+ "ro": "0",
3693+ "size": "1073741824",
3694+ "start": "18432",
3695+ "stat": " 322 0 50394 22 1522 2894 310648 343 0 756 12 0 0 0 0",
3696+ "subsystem": "block",
3697+ "uevent": "MAJOR=252\nMINOR=2\nDEVNAME=vda2\nDEVTYPE=partition\nPARTN=2"
3698+ }
3699+ },
3700+ "/dev/vdb": {
3701+ "DEVLINKS": "/dev/disk/by-path/virtio-pci-0000:00:05.0 /dev/disk/by-path/pci-0000:00:05.0",
3702+ "DEVNAME": "/dev/vdb",
3703+ "DEVPATH": "/devices/pci0000:00/0000:00:05.0/virtio3/block/vdb",
3704+ "DEVTYPE": "disk",
3705+ "ID_PART_TABLE_TYPE": "gpt",
3706+ "ID_PART_TABLE_UUID": "0c49cc0b-d527-4a88-a61a-4684bcdf8a5e",
3707+ "ID_PATH": "pci-0000:00:05.0",
3708+ "ID_PATH_TAG": "pci-0000_00_05_0",
3709+ "MAJOR": "252",
3710+ "MINOR": "16",
3711+ "SUBSYSTEM": "block",
3712+ "TAGS": ":systemd:",
3713+ "USEC_INITIALIZED": "600195",
3714+ "attrs": {
3715+ "alignment_offset": "0",
3716+ "bdi": null,
3717+ "cache_type": "write back",
3718+ "capability": "50",
3719+ "dev": "252:16",
3720+ "device": null,
3721+ "discard_alignment": "0",
3722+ "events": "",
3723+ "events_async": "",
3724+ "events_poll_msecs": "-1",
3725+ "ext_range": "256",
3726+ "hidden": "0",
3727+ "inflight": " 0 0",
3728+ "range": "16",
3729+ "removable": "0",
3730+ "ro": "0",
3731+ "serial": "",
3732+ "size": "6442450944",
3733+ "stat": " 20457 64216 10072248 3184 39416 65487 5219881 24281 0 27324 8488 0 0 0 0",
3734+ "subsystem": "block",
3735+ "uevent": "MAJOR=252\nMINOR=16\nDEVNAME=vdb\nDEVTYPE=disk"
3736+ },
3737+ "partitiontable": {
3738+ "label": "gpt",
3739+ "id": "0C49CC0B-D527-4A88-A61A-4684BCDF8A5E",
3740+ "device": "/dev/vdb",
3741+ "unit": "sectors",
3742+ "firstlba": 34,
3743+ "lastlba": 12582878,
3744+ "partitions": [
3745+ {
3746+ "node": "/dev/vdb1",
3747+ "start": 2048,
3748+ "size": 8388608,
3749+ "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
3750+ "uuid": "408078B3-15C1-4315-A376-C2F1E3F13A63"
3751+ }
3752+ ]
3753+ }
3754+ },
3755+ "/dev/vdb1": {
3756+ "DEVLINKS": "/dev/disk/by-partuuid/408078b3-15c1-4315-a376-c2f1e3f13a63 /dev/disk/by-path/virtio-pci-0000:00:05.0-part1 /dev/disk/by-path/pci-0000:00:05.0-part1",
3757+ "DEVNAME": "/dev/vdb1",
3758+ "DEVPATH": "/devices/pci0000:00/0000:00:05.0/virtio3/block/vdb/vdb1",
3759+ "DEVTYPE": "partition",
3760+ "ID_FS_LABEL": "ubuntu-server:1",
3761+ "ID_FS_LABEL_ENC": "ubuntu-server:1",
3762+ "ID_FS_TYPE": "linux_raid_member",
3763+ "ID_FS_USAGE": "raid",
3764+ "ID_FS_UUID": "1e4e3ac4-abd1-ee76-6fdb-871a4d6677af",
3765+ "ID_FS_UUID_ENC": "1e4e3ac4-abd1-ee76-6fdb-871a4d6677af",
3766+ "ID_FS_UUID_SUB": "f1366f7f-319f-81e6-7550-edb94d240727",
3767+ "ID_FS_UUID_SUB_ENC": "f1366f7f-319f-81e6-7550-edb94d240727",
3768+ "ID_FS_VERSION": "1.2",
3769+ "ID_PART_ENTRY_DISK": "252:16",
3770+ "ID_PART_ENTRY_NUMBER": "1",
3771+ "ID_PART_ENTRY_OFFSET": "2048",
3772+ "ID_PART_ENTRY_SCHEME": "gpt",
3773+ "ID_PART_ENTRY_SIZE": "8388608",
3774+ "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4",
3775+ "ID_PART_ENTRY_UUID": "408078b3-15c1-4315-a376-c2f1e3f13a63",
3776+ "ID_PART_TABLE_TYPE": "gpt",
3777+ "ID_PART_TABLE_UUID": "0c49cc0b-d527-4a88-a61a-4684bcdf8a5e",
3778+ "ID_PATH": "pci-0000:00:05.0",
3779+ "ID_PATH_TAG": "pci-0000_00_05_0",
3780+ "ID_SCSI": "1",
3781+ "MAJOR": "252",
3782+ "MINOR": "17",
3783+ "PARTN": "1",
3784+ "SUBSYSTEM": "block",
3785+ "TAGS": ":systemd:",
3786+ "USEC_INITIALIZED": "52064605",
3787+ "attrs": {
3788+ "alignment_offset": "0",
3789+ "dev": "252:17",
3790+ "discard_alignment": "0",
3791+ "inflight": " 0 0",
3792+ "partition": "1",
3793+ "ro": "0",
3794+ "size": "4294967296",
3795+ "start": "2048",
3796+ "stat": " 19443 64216 9896724 3125 39280 65397 5207337 24270 0 26204 8488 0 0 0 0",
3797+ "subsystem": "block",
3798+ "uevent": "MAJOR=252\nMINOR=17\nDEVNAME=vdb1\nDEVTYPE=partition\nPARTN=1"
3799+ }
3800+ },
3801+ "/dev/vdc": {
3802+ "DEVLINKS": "/dev/disk/by-path/pci-0000:00:06.0 /dev/disk/by-path/virtio-pci-0000:00:06.0",
3803+ "DEVNAME": "/dev/vdc",
3804+ "DEVPATH": "/devices/pci0000:00/0000:00:06.0/virtio4/block/vdc",
3805+ "DEVTYPE": "disk",
3806+ "ID_PART_TABLE_TYPE": "gpt",
3807+ "ID_PART_TABLE_UUID": "c805b10b-ded9-4519-947c-bcad1d6e81ed",
3808+ "ID_PATH": "pci-0000:00:06.0",
3809+ "ID_PATH_TAG": "pci-0000_00_06_0",
3810+ "MAJOR": "252",
3811+ "MINOR": "32",
3812+ "SUBSYSTEM": "block",
3813+ "TAGS": ":systemd:",
3814+ "USEC_INITIALIZED": "600459",
3815+ "attrs": {
3816+ "alignment_offset": "0",
3817+ "bdi": null,
3818+ "cache_type": "write back",
3819+ "capability": "50",
3820+ "dev": "252:32",
3821+ "device": null,
3822+ "discard_alignment": "0",
3823+ "events": "",
3824+ "events_async": "",
3825+ "events_poll_msecs": "-1",
3826+ "ext_range": "256",
3827+ "hidden": "0",
3828+ "inflight": " 0 0",
3829+ "range": "16",
3830+ "removable": "0",
3831+ "ro": "0",
3832+ "serial": "",
3833+ "size": "6442450944",
3834+ "stat": " 2791 749 264502 172 43737 126620 13598249 40301 0 19796 23016 0 0 0 0",
3835+ "subsystem": "block",
3836+ "uevent": "MAJOR=252\nMINOR=32\nDEVNAME=vdc\nDEVTYPE=disk"
3837+ },
3838+ "partitiontable": {
3839+ "label": "gpt",
3840+ "id": "C805B10B-DED9-4519-947C-BCAD1D6E81ED",
3841+ "device": "/dev/vdc",
3842+ "unit": "sectors",
3843+ "firstlba": 34,
3844+ "lastlba": 12582878,
3845+ "partitions": [
3846+ {
3847+ "node": "/dev/vdc1",
3848+ "start": 2048,
3849+ "size": 8388608,
3850+ "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
3851+ "uuid": "69441F30-8321-4A70-A4CF-6A4B92393CD6"
3852+ }
3853+ ]
3854+ }
3855+ },
3856+ "/dev/vdc1": {
3857+ "DEVLINKS": "/dev/disk/by-partuuid/69441f30-8321-4a70-a4cf-6a4b92393cd6 /dev/disk/by-path/pci-0000:00:06.0-part1 /dev/disk/by-path/virtio-pci-0000:00:06.0-part1",
3858+ "DEVNAME": "/dev/vdc1",
3859+ "DEVPATH": "/devices/pci0000:00/0000:00:06.0/virtio4/block/vdc/vdc1",
3860+ "DEVTYPE": "partition",
3861+ "ID_FS_LABEL": "ubuntu-server:1",
3862+ "ID_FS_LABEL_ENC": "ubuntu-server:1",
3863+ "ID_FS_TYPE": "linux_raid_member",
3864+ "ID_FS_USAGE": "raid",
3865+ "ID_FS_UUID": "1e4e3ac4-abd1-ee76-6fdb-871a4d6677af",
3866+ "ID_FS_UUID_ENC": "1e4e3ac4-abd1-ee76-6fdb-871a4d6677af",
3867+ "ID_FS_UUID_SUB": "52929a1d-d9f0-e3a9-c16e-c40433201114",
3868+ "ID_FS_UUID_SUB_ENC": "52929a1d-d9f0-e3a9-c16e-c40433201114",
3869+ "ID_FS_VERSION": "1.2",
3870+ "ID_PART_ENTRY_DISK": "252:32",
3871+ "ID_PART_ENTRY_NUMBER": "1",
3872+ "ID_PART_ENTRY_OFFSET": "2048",
3873+ "ID_PART_ENTRY_SCHEME": "gpt",
3874+ "ID_PART_ENTRY_SIZE": "8388608",
3875+ "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4",
3876+ "ID_PART_ENTRY_UUID": "69441f30-8321-4a70-a4cf-6a4b92393cd6",
3877+ "ID_PART_TABLE_TYPE": "gpt",
3878+ "ID_PART_TABLE_UUID": "c805b10b-ded9-4519-947c-bcad1d6e81ed",
3879+ "ID_PATH": "pci-0000:00:06.0",
3880+ "ID_PATH_TAG": "pci-0000_00_06_0",
3881+ "ID_SCSI": "1",
3882+ "MAJOR": "252",
3883+ "MINOR": "33",
3884+ "PARTN": "1",
3885+ "SUBSYSTEM": "block",
3886+ "TAGS": ":systemd:",
3887+ "USEC_INITIALIZED": "52548543",
3888+ "attrs": {
3889+ "alignment_offset": "0",
3890+ "dev": "252:33",
3891+ "discard_alignment": "0",
3892+ "inflight": " 0 0",
3893+ "partition": "1",
3894+ "ro": "0",
3895+ "size": "4294967296",
3896+ "start": "2048",
3897+ "stat": " 1756 749 86802 112 43601 126530 13585705 40291 0 18404 23016 0 0 0 0",
3898+ "subsystem": "block",
3899+ "uevent": "MAJOR=252\nMINOR=33\nDEVNAME=vdc1\nDEVTYPE=partition\nPARTN=1"
3900+ }
3901+ },
3902+ "/dev/vdd": {
3903+ "DEVLINKS": "/dev/disk/by-path/virtio-pci-0000:00:07.0 /dev/disk/by-uuid/00c629d6-06ab-4dfd-b21e-c3186f34105d /dev/disk/by-path/pci-0000:00:07.0",
3904+ "DEVNAME": "/dev/vdd",
3905+ "DEVPATH": "/devices/pci0000:00/0000:00:07.0/virtio5/block/vdd",
3906+ "DEVTYPE": "disk",
3907+ "ID_FS_TYPE": "ext2",
3908+ "ID_FS_USAGE": "filesystem",
3909+ "ID_FS_UUID": "00c629d6-06ab-4dfd-b21e-c3186f34105d",
3910+ "ID_FS_UUID_ENC": "00c629d6-06ab-4dfd-b21e-c3186f34105d",
3911+ "ID_FS_VERSION": "1.0",
3912+ "ID_PATH": "pci-0000:00:07.0",
3913+ "ID_PATH_TAG": "pci-0000_00_07_0",
3914+ "MAJOR": "252",
3915+ "MINOR": "48",
3916+ "SUBSYSTEM": "block",
3917+ "TAGS": ":systemd:",
3918+ "USEC_INITIALIZED": "563993",
3919+ "attrs": {
3920+ "alignment_offset": "0",
3921+ "bdi": null,
3922+ "cache_type": "write back",
3923+ "capability": "50",
3924+ "dev": "252:48",
3925+ "device": null,
3926+ "discard_alignment": "0",
3927+ "events": "",
3928+ "events_async": "",
3929+ "events_poll_msecs": "-1",
3930+ "ext_range": "256",
3931+ "hidden": "0",
3932+ "inflight": " 0 0",
3933+ "range": "16",
3934+ "removable": "0",
3935+ "ro": "1",
3936+ "serial": "",
3937+ "size": "1048576",
3938+ "stat": " 97 0 3367 4 2 0 0 0 0 76 0 0 0 0 0",
3939+ "subsystem": "block",
3940+ "uevent": "MAJOR=252\nMINOR=48\nDEVNAME=vdd\nDEVTYPE=disk"
3941+ }
3942+ },
3943+ "/dev/md1": {
3944+ "DEVLINKS": "/dev/disk/by-id/md-name-ubuntu-server:1 /dev/disk/by-id/md-uuid-1e4e3ac4:abd1ee76:6fdb871a:4d6677af",
3945+ "DEVNAME": "/dev/md1",
3946+ "DEVPATH": "/devices/virtual/block/md1",
3947+ "DEVTYPE": "disk",
3948+ "ID_PART_TABLE_TYPE": "gpt",
3949+ "ID_PART_TABLE_UUID": "18f354ee-3557-4a37-9508-c947edb21b5c",
3950+ "MAJOR": "9",
3951+ "MD_DEVICES": "2",
3952+ "MD_DEVICE_ev_vdb1_DEV": "/dev/vdb1",
3953+ "MD_DEVICE_ev_vdb1_ROLE": "0",
3954+ "MD_DEVICE_ev_vdc1_DEV": "/dev/vdc1",
3955+ "MD_DEVICE_ev_vdc1_ROLE": "1",
3956+ "MD_LEVEL": "raid1",
3957+ "MD_METADATA": "1.2",
3958+ "MD_NAME": "ubuntu-server:1",
3959+ "MD_UUID": "1e4e3ac4:abd1ee76:6fdb871a:4d6677af",
3960+ "MINOR": "1",
3961+ "SUBSYSTEM": "block",
3962+ "SYSTEMD_WANTS": "mdmonitor.service",
3963+ "TAGS": ":systemd:",
3964+ "USEC_INITIALIZED": "52972570",
3965+ "attrs": {
3966+ "alignment_offset": "0",
3967+ "bdi": null,
3968+ "capability": "50",
3969+ "dev": "9:1",
3970+ "discard_alignment": "0",
3971+ "events": "",
3972+ "events_async": "",
3973+ "events_poll_msecs": "-1",
3974+ "ext_range": "256",
3975+ "hidden": "0",
3976+ "inflight": " 0 0",
3977+ "range": "1",
3978+ "removable": "0",
3979+ "ro": "0",
3980+ "size": "4289724416",
3981+ "stat": " 20095 0 1539578 0 105192 0 5220984 0 0 0 0 0 0 0 0",
3982+ "subsystem": "block",
3983+ "uevent": "MAJOR=9\nMINOR=1\nDEVNAME=md1\nDEVTYPE=disk"
3984+ },
3985+ "partitiontable": {
3986+ "label": "gpt",
3987+ "id": "18F354EE-3557-4A37-9508-C947EDB21B5C",
3988+ "device": "/dev/md1",
3989+ "unit": "sectors",
3990+ "firstlba": 34,
3991+ "lastlba": 8378334,
3992+ "partitions": [
3993+ {
3994+ "node": "/dev/md1p1",
3995+ "start": 2048,
3996+ "size": 8370176,
3997+ "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
3998+ "uuid": "5B3F90C0-2432-45C1-98E2-6E9E6649430E"
3999+ }
4000+ ]
4001+ }
4002+ },
4003+ "/dev/md1p1": {
4004+ "DEVLINKS": "/dev/disk/by-uuid/b312e605-d330-43ad-aa9b-2d503412977d /dev/disk/by-id/md-uuid-1e4e3ac4:abd1ee76:6fdb871a:4d6677af-part1 /dev/disk/by-id/md-name-ubuntu-server:1-part1",
4005+ "DEVNAME": "/dev/md1p1",
4006+ "DEVPATH": "/devices/virtual/block/md1/md1p1",
4007+ "DEVTYPE": "partition",
4008+ "ID_FS_TYPE": "ext4",
4009+ "ID_FS_USAGE": "filesystem",
4010+ "ID_FS_UUID": "b312e605-d330-43ad-aa9b-2d503412977d",
4011+ "ID_FS_UUID_ENC": "b312e605-d330-43ad-aa9b-2d503412977d",
4012+ "ID_FS_VERSION": "1.0",
4013+ "ID_PART_ENTRY_DISK": "9:1",
4014+ "ID_PART_ENTRY_NUMBER": "1",
4015+ "ID_PART_ENTRY_OFFSET": "2048",
4016+ "ID_PART_ENTRY_SCHEME": "gpt",
4017+ "ID_PART_ENTRY_SIZE": "8370176",
4018+ "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4",
4019+ "ID_PART_ENTRY_UUID": "5b3f90c0-2432-45c1-98e2-6e9e6649430e",
4020+ "ID_SCSI": "1",
4021+ "MAJOR": "259",
4022+ "MD_DEVICES": "2",
4023+ "MD_DEVICE_ev_vdb1_DEV": "/dev/vdb1",
4024+ "MD_DEVICE_ev_vdb1_ROLE": "0",
4025+ "MD_DEVICE_ev_vdc1_DEV": "/dev/vdc1",
4026+ "MD_DEVICE_ev_vdc1_ROLE": "1",
4027+ "MD_LEVEL": "raid1",
4028+ "MD_METADATA": "1.2",
4029+ "MD_NAME": "ubuntu-server:1",
4030+ "MD_UUID": "1e4e3ac4:abd1ee76:6fdb871a:4d6677af",
4031+ "MINOR": "1",
4032+ "PARTN": "1",
4033+ "SUBSYSTEM": "block",
4034+ "SYSTEMD_WANTS": "mdmonitor.service",
4035+ "TAGS": ":systemd:",
4036+ "USEC_INITIALIZED": "62053949",
4037+ "attrs": {
4038+ "alignment_offset": "0",
4039+ "dev": "259:1",
4040+ "discard_alignment": "0",
4041+ "inflight": " 0 0",
4042+ "partition": "1",
4043+ "ro": "0",
4044+ "size": "4285530112",
4045+ "start": "2048",
4046+ "stat": " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0",
4047+ "subsystem": "block",
4048+ "uevent": "MAJOR=259\nMINOR=1\nDEVNAME=md1p1\nDEVTYPE=partition\nPARTN=1"
4049+ }
4050+ }
4051+ },
4052+ "bcache": {
4053+ "backing": {},
4054+ "caching": {}
4055+ },
4056+ "lvm": {},
4057+ "mount": [
4058+ {
4059+ "target": "/",
4060+ "source": "/cow",
4061+ "fstype": "overlay",
4062+ "options": "rw,relatime,lowerdir=/installer.squashfs:/filesystem.squashfs,upperdir=/cow/upper,workdir=/cow/work",
4063+ "children": [
4064+ {
4065+ "target": "/sys",
4066+ "source": "sysfs",
4067+ "fstype": "sysfs",
4068+ "options": "rw,nosuid,nodev,noexec,relatime",
4069+ "children": [
4070+ {
4071+ "target": "/sys/kernel/security",
4072+ "source": "securityfs",
4073+ "fstype": "securityfs",
4074+ "options": "rw,nosuid,nodev,noexec,relatime"
4075+ },
4076+ {
4077+ "target": "/sys/fs/cgroup",
4078+ "source": "tmpfs",
4079+ "fstype": "tmpfs",
4080+ "options": "ro,nosuid,nodev,noexec,mode=755",
4081+ "children": [
4082+ {
4083+ "target": "/sys/fs/cgroup/unified",
4084+ "source": "cgroup2",
4085+ "fstype": "cgroup2",
4086+ "options": "rw,nosuid,nodev,noexec,relatime,nsdelegate"
4087+ },
4088+ {
4089+ "target": "/sys/fs/cgroup/systemd",
4090+ "source": "cgroup",
4091+ "fstype": "cgroup",
4092+ "options": "rw,nosuid,nodev,noexec,relatime,xattr,name=systemd"
4093+ },
4094+ {
4095+ "target": "/sys/fs/cgroup/freezer",
4096+ "source": "cgroup",
4097+ "fstype": "cgroup",
4098+ "options": "rw,nosuid,nodev,noexec,relatime,freezer"
4099+ },
4100+ {
4101+ "target": "/sys/fs/cgroup/pids",
4102+ "source": "cgroup",
4103+ "fstype": "cgroup",
4104+ "options": "rw,nosuid,nodev,noexec,relatime,pids"
4105+ },
4106+ {
4107+ "target": "/sys/fs/cgroup/cpuset",
4108+ "source": "cgroup",
4109+ "fstype": "cgroup",
4110+ "options": "rw,nosuid,nodev,noexec,relatime,cpuset"
4111+ },
4112+ {
4113+ "target": "/sys/fs/cgroup/cpu,cpuacct",
4114+ "source": "cgroup",
4115+ "fstype": "cgroup",
4116+ "options": "rw,nosuid,nodev,noexec,relatime,cpu,cpuacct"
4117+ },
4118+ {
4119+ "target": "/sys/fs/cgroup/blkio",
4120+ "source": "cgroup",
4121+ "fstype": "cgroup",
4122+ "options": "rw,nosuid,nodev,noexec,relatime,blkio"
4123+ },
4124+ {
4125+ "target": "/sys/fs/cgroup/net_cls,net_prio",
4126+ "source": "cgroup",
4127+ "fstype": "cgroup",
4128+ "options": "rw,nosuid,nodev,noexec,relatime,net_cls,net_prio"
4129+ },
4130+ {
4131+ "target": "/sys/fs/cgroup/rdma",
4132+ "source": "cgroup",
4133+ "fstype": "cgroup",
4134+ "options": "rw,nosuid,nodev,noexec,relatime,rdma"
4135+ },
4136+ {
4137+ "target": "/sys/fs/cgroup/devices",
4138+ "source": "cgroup",
4139+ "fstype": "cgroup",
4140+ "options": "rw,nosuid,nodev,noexec,relatime,devices"
4141+ },
4142+ {
4143+ "target": "/sys/fs/cgroup/memory",
4144+ "source": "cgroup",
4145+ "fstype": "cgroup",
4146+ "options": "rw,nosuid,nodev,noexec,relatime,memory"
4147+ },
4148+ {
4149+ "target": "/sys/fs/cgroup/perf_event",
4150+ "source": "cgroup",
4151+ "fstype": "cgroup",
4152+ "options": "rw,nosuid,nodev,noexec,relatime,perf_event"
4153+ },
4154+ {
4155+ "target": "/sys/fs/cgroup/hugetlb",
4156+ "source": "cgroup",
4157+ "fstype": "cgroup",
4158+ "options": "rw,nosuid,nodev,noexec,relatime,hugetlb"
4159+ }
4160+ ]
4161+ },
4162+ {
4163+ "target": "/sys/fs/pstore",
4164+ "source": "pstore",
4165+ "fstype": "pstore",
4166+ "options": "rw,nosuid,nodev,noexec,relatime"
4167+ },
4168+ {
4169+ "target": "/sys/fs/bpf",
4170+ "source": "bpf",
4171+ "fstype": "bpf",
4172+ "options": "rw,nosuid,nodev,noexec,relatime,mode=700"
4173+ },
4174+ {
4175+ "target": "/sys/kernel/debug",
4176+ "source": "debugfs",
4177+ "fstype": "debugfs",
4178+ "options": "rw,nosuid,nodev,noexec,relatime"
4179+ },
4180+ {
4181+ "target": "/sys/fs/fuse/connections",
4182+ "source": "fusectl",
4183+ "fstype": "fusectl",
4184+ "options": "rw,nosuid,nodev,noexec,relatime"
4185+ },
4186+ {
4187+ "target": "/sys/kernel/config",
4188+ "source": "configfs",
4189+ "fstype": "configfs",
4190+ "options": "rw,nosuid,nodev,noexec,relatime"
4191+ }
4192+ ]
4193+ },
4194+ {
4195+ "target": "/proc",
4196+ "source": "proc",
4197+ "fstype": "proc",
4198+ "options": "rw,nosuid,nodev,noexec,relatime",
4199+ "children": [
4200+ {
4201+ "target": "/proc/sys/fs/binfmt_misc",
4202+ "source": "systemd-1",
4203+ "fstype": "autofs",
4204+ "options": "rw,relatime,fd=27,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=13520"
4205+ }
4206+ ]
4207+ },
4208+ {
4209+ "target": "/dev",
4210+ "source": "udev",
4211+ "fstype": "devtmpfs",
4212+ "options": "rw,nosuid,relatime,size=956672k,nr_inodes=14948,mode=755",
4213+ "children": [
4214+ {
4215+ "target": "/dev/pts",
4216+ "source": "devpts",
4217+ "fstype": "devpts",
4218+ "options": "rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000"
4219+ },
4220+ {
4221+ "target": "/dev/shm",
4222+ "source": "tmpfs",
4223+ "fstype": "tmpfs",
4224+ "options": "rw,nosuid,nodev"
4225+ },
4226+ {
4227+ "target": "/dev/mqueue",
4228+ "source": "mqueue",
4229+ "fstype": "mqueue",
4230+ "options": "rw,nosuid,nodev,noexec,relatime"
4231+ }
4232+ ]
4233+ },
4234+ {
4235+ "target": "/run",
4236+ "source": "tmpfs",
4237+ "fstype": "tmpfs",
4238+ "options": "rw,nosuid,noexec,relatime,size=206720k,mode=755",
4239+ "children": [
4240+ {
4241+ "target": "/run/lock",
4242+ "source": "tmpfs",
4243+ "fstype": "tmpfs",
4244+ "options": "rw,nosuid,nodev,noexec,relatime,size=5120k"
4245+ }
4246+ ]
4247+ },
4248+ {
4249+ "target": "/cdrom",
4250+ "source": "/dev/sr0",
4251+ "fstype": "iso9660",
4252+ "options": "ro,noatime,nojoliet,check=s,map=n,blocksize=2048"
4253+ },
4254+ {
4255+ "target": "/rofs",
4256+ "source": "/dev/loop0",
4257+ "fstype": "squashfs",
4258+ "options": "ro,noatime"
4259+ },
4260+ {
4261+ "target": "/usr/lib/modules",
4262+ "source": "/dev/loop2",
4263+ "fstype": "squashfs",
4264+ "options": "ro,relatime"
4265+ },
4266+ {
4267+ "target": "/media/filesystem",
4268+ "source": "/dev/loop0",
4269+ "fstype": "squashfs",
4270+ "options": "ro,relatime"
4271+ },
4272+ {
4273+ "target": "/tmp",
4274+ "source": "tmpfs",
4275+ "fstype": "tmpfs",
4276+ "options": "rw,nosuid,nodev,relatime"
4277+ },
4278+ {
4279+ "target": "/subiquity_config",
4280+ "source": "/dev/vdd",
4281+ "fstype": "ext4",
4282+ "options": "ro,relatime"
4283+ },
4284+ {
4285+ "target": "/snap/core/8041",
4286+ "source": "/dev/loop3",
4287+ "fstype": "squashfs",
4288+ "options": "ro,nodev,relatime"
4289+ },
4290+ {
4291+ "target": "/snap/subiquity/1335",
4292+ "source": "/dev/loop4",
4293+ "fstype": "squashfs",
4294+ "options": "ro,nodev,relatime"
4295+ },
4296+ {
4297+ "target": "/target",
4298+ "source": "/dev/md1p1",
4299+ "fstype": "ext4",
4300+ "options": "rw,relatime",
4301+ "children": [
4302+ {
4303+ "target": "/target/run",
4304+ "source": "tmpfs",
4305+ "fstype": "tmpfs",
4306+ "options": "rw,nosuid,noexec,relatime,size=206720k,mode=755"
4307+ },
4308+ {
4309+ "target": "/target/boot",
4310+ "source": "/dev/vda2",
4311+ "fstype": "ext4",
4312+ "options": "rw,relatime"
4313+ },
4314+ {
4315+ "target": "/target/etc/apt",
4316+ "source": "overlay",
4317+ "fstype": "overlay",
4318+ "options": "rw,relatime,lowerdir=/target/etc/apt,upperdir=/tmp/tmp.dFi4ai53r1/upper,workdir=/tmp/tmp.dFi4ai53r1/work"
4319+ },
4320+ {
4321+ "target": "/target/cdrom",
4322+ "source": "/dev/sr0",
4323+ "fstype": "iso9660",
4324+ "options": "ro,noatime,nojoliet,check=s,map=n,blocksize=2048"
4325+ }
4326+ ]
4327+ }
4328+ ]
4329+ }
4330+ ],
4331+ "filesystem": {
4332+ "/dev/sr0": {
4333+ "APPLICATION_ID": "GENISOIMAGE\\x20ISO\\x209660\\x2fHFS\\x20FILESYSTEM\\x20CREATOR\\x20\\x28C\\x29\\x201993\\x20E.YOUNGDALE\\x20\\x28C\\x29\\x201997-2006\\x20J.PEARSON\\x2fJ.SCHILLING\\x20\\x28C\\x29\\x202006-2007\\x20CDRKIT\\x20TEAM",
4334+ "LABEL": "Ubuntu-Server_20.04_LTS_ppc64",
4335+ "LABEL_ENC": "Ubuntu-Server\\x2020.04\\x20LTS\\x20ppc64",
4336+ "SYSTEM_ID": "LINUX",
4337+ "TYPE": "iso9660",
4338+ "USAGE": "filesystem",
4339+ "UUID": "2019-11-16-08-09-20-00",
4340+ "UUID_ENC": "2019-11-16-08-09-20-00"
4341+ },
4342+ "/dev/vda2": {
4343+ "TYPE": "ext4",
4344+ "USAGE": "filesystem",
4345+ "UUID": "0a3b5403-d358-4f30-9094-e5a19d60b222",
4346+ "UUID_ENC": "0a3b5403-d358-4f30-9094-e5a19d60b222",
4347+ "VERSION": "1.0"
4348+ },
4349+ "/dev/vdd": {
4350+ "TYPE": "ext2",
4351+ "USAGE": "filesystem",
4352+ "UUID": "00c629d6-06ab-4dfd-b21e-c3186f34105d",
4353+ "UUID_ENC": "00c629d6-06ab-4dfd-b21e-c3186f34105d",
4354+ "VERSION": "1.0"
4355+ },
4356+ "/dev/md1p1": {
4357+ "TYPE": "ext4",
4358+ "USAGE": "filesystem",
4359+ "UUID": "b312e605-d330-43ad-aa9b-2d503412977d",
4360+ "UUID_ENC": "b312e605-d330-43ad-aa9b-2d503412977d",
4361+ "VERSION": "1.0"
4362+ }
4363+ },
4364+ "raid": {
4365+ "/dev/md1": {
4366+ "DEVLINKS": "/dev/disk/by-id/md-name-ubuntu-server:1 /dev/disk/by-id/md-uuid-1e4e3ac4:abd1ee76:6fdb871a:4d6677af",
4367+ "DEVNAME": "/dev/md1",
4368+ "DEVPATH": "/devices/virtual/block/md1",
4369+ "DEVTYPE": "disk",
4370+ "ID_PART_TABLE_TYPE": "gpt",
4371+ "ID_PART_TABLE_UUID": "18f354ee-3557-4a37-9508-c947edb21b5c",
4372+ "MAJOR": "9",
4373+ "MD_DEVICES": "2",
4374+ "MD_DEVICE_ev_vdb1_DEV": "/dev/vdb1",
4375+ "MD_DEVICE_ev_vdb1_ROLE": "0",
4376+ "MD_DEVICE_ev_vdc1_DEV": "/dev/vdc1",
4377+ "MD_DEVICE_ev_vdc1_ROLE": "1",
4378+ "MD_LEVEL": "raid1",
4379+ "MD_METADATA": "1.2",
4380+ "MD_NAME": "ubuntu-server:1",
4381+ "MD_UUID": "1e4e3ac4:abd1ee76:6fdb871a:4d6677af",
4382+ "MINOR": "1",
4383+ "SUBSYSTEM": "block",
4384+ "SYSTEMD_WANTS": "mdmonitor.service",
4385+ "TAGS": ":systemd:",
4386+ "USEC_INITIALIZED": "52972570",
4387+ "raidlevel": "raid1",
4388+ "devices": [
4389+ "/dev/vdb1",
4390+ "/dev/vdc1"
4391+ ],
4392+ "spare_devices": []
4393+ }
4394+ },
4395+ "multipath": {}
4396+}
4397diff --git a/tests/data/probert_storage_zlp6.json b/tests/data/probert_storage_zlp6.json
4398new file mode 100644
4399index 0000000..b56a02b
4400--- /dev/null
4401+++ b/tests/data/probert_storage_zlp6.json
4402@@ -0,0 +1,6980 @@
4403+{
4404+ "storage": {
4405+ "bcache": {
4406+ "backing": {},
4407+ "caching": {}
4408+ },
4409+ "blockdev": {
4410+ "/dev/dasda": {
4411+ "DEVLINKS": "/dev/disk/by-id/ccw-IBM.750000000DXP71.1500.20 /dev/disk/by-path/ccw-0.0.1520 /dev/disk/by-uuid/3f168f0c-d0c7-4d8b-b23d-92c7476b092b",
4412+ "DEVNAME": "/dev/dasda",
4413+ "DEVPATH": "/devices/css0/0.0.0180/0.0.1520/block/dasda",
4414+ "DEVTYPE": "disk",
4415+ "ID_BUS": "ccw",
4416+ "ID_FS_TYPE": "bcache",
4417+ "ID_FS_UUID": "3f168f0c-d0c7-4d8b-b23d-92c7476b092b",
4418+ "ID_FS_UUID_ENC": "3f168f0c-d0c7-4d8b-b23d-92c7476b092b",
4419+ "ID_PATH": "ccw-0.0.1520",
4420+ "ID_PATH_TAG": "ccw-0_0_1520",
4421+ "ID_TYPE": "disk",
4422+ "ID_UID": "IBM.750000000DXP71.1500.20",
4423+ "ID_XUID": "IBM.750000000DXP71.1500.20",
4424+ "MAJOR": "94",
4425+ "MINOR": "0",
4426+ "MPATH_SBIN_PATH": "/sbin",
4427+ "SUBSYSTEM": "block",
4428+ "TAGS": ":systemd:",
4429+ "USEC_INITIALIZED": "9522332",
4430+ "attrs": {
4431+ "alignment_offset": "0",
4432+ "bdi": null,
4433+ "capability": "10",
4434+ "dev": "94:0",
4435+ "device": null,
4436+ "discard_alignment": "0",
4437+ "ext_range": "4",
4438+ "hidden": "0",
4439+ "inflight": " 0 0",
4440+ "range": "4",
4441+ "removable": "0",
4442+ "ro": "0",
4443+ "size": "59082670080",
4444+ "stat": " 16869 0 1012184 2450 12685 171372 4061544 74710 0 56227200 56332580",
4445+ "subsystem": "block",
4446+ "uevent": "MAJOR=94\nMINOR=0\nDEVNAME=dasda\nDEVTYPE=disk"
4447+ }
4448+ },
4449+ "/dev/dasdb": {
4450+ "DEVLINKS": "/dev/disk/by-id/ccw-IBM.750000000DXP71.1500.1f /dev/disk/by-id/ccw-0X151F /dev/disk/by-path/ccw-0.0.151f",
4451+ "DEVNAME": "/dev/dasdb",
4452+ "DEVPATH": "/devices/css0/0.0.017f/0.0.151f/block/dasdb",
4453+ "DEVTYPE": "disk",
4454+ "ID_BUS": "ccw",
4455+ "ID_PATH": "ccw-0.0.151f",
4456+ "ID_PATH_TAG": "ccw-0_0_151f",
4457+ "ID_SERIAL": "0X151F",
4458+ "ID_TYPE": "disk",
4459+ "ID_UID": "IBM.750000000DXP71.1500.1f",
4460+ "ID_XUID": "IBM.750000000DXP71.1500.1f",
4461+ "MAJOR": "94",
4462+ "MINOR": "4",
4463+ "MPATH_SBIN_PATH": "/sbin",
4464+ "SUBSYSTEM": "block",
4465+ "TAGS": ":systemd:",
4466+ "USEC_INITIALIZED": "9552537",
4467+ "attrs": {
4468+ "alignment_offset": "0",
4469+ "bdi": null,
4470+ "capability": "10",
4471+ "dev": "94:4",
4472+ "device": null,
4473+ "discard_alignment": "0",
4474+ "ext_range": "4",
4475+ "hidden": "0",
4476+ "inflight": " 0 0",
4477+ "range": "4",
4478+ "removable": "0",
4479+ "ro": "0",
4480+ "size": "59082670080",
4481+ "stat": " 2590 0 61872 750 0 0 0 0 0 1514773090 1514775410",
4482+ "subsystem": "block",
4483+ "uevent": "MAJOR=94\nMINOR=4\nDEVNAME=dasdb\nDEVTYPE=disk"
4484+ }
4485+ },
4486+ "/dev/dasdb1": {
4487+ "DEVLINKS": "/dev/disk/by-uuid/45824f3e-2b61-48c6-912f-6142ce21827c /dev/disk/by-id/ccw-IBM.750000000DXP71.1500.1f-part1 /dev/disk/by-path/ccw-0.0.151f-part1 /dev/disk/by-id/ccw-0X151F-part1",
4488+ "DEVNAME": "/dev/dasdb1",
4489+ "DEVPATH": "/devices/css0/0.0.017f/0.0.151f/block/dasdb/dasdb1",
4490+ "DEVTYPE": "partition",
4491+ "ID_BUS": "ccw",
4492+ "ID_FS_TYPE": "ext4",
4493+ "ID_FS_USAGE": "filesystem",
4494+ "ID_FS_UUID": "45824f3e-2b61-48c6-912f-6142ce21827c",
4495+ "ID_FS_UUID_ENC": "45824f3e-2b61-48c6-912f-6142ce21827c",
4496+ "ID_FS_VERSION": "1.0",
4497+ "ID_PATH": "ccw-0.0.151f",
4498+ "ID_PATH_TAG": "ccw-0_0_151f",
4499+ "ID_SCSI": "1",
4500+ "ID_SERIAL": "0X151F",
4501+ "ID_TYPE": "disk",
4502+ "ID_UID": "IBM.750000000DXP71.1500.1f",
4503+ "ID_XUID": "IBM.750000000DXP71.1500.1f",
4504+ "MAJOR": "94",
4505+ "MINOR": "5",
4506+ "PARTN": "1",
4507+ "SUBSYSTEM": "block",
4508+ "TAGS": ":systemd:",
4509+ "USEC_INITIALIZED": "1279563953260",
4510+ "attrs": {
4511+ "alignment_offset": "0",
4512+ "dev": "94:5",
4513+ "discard_alignment": "0",
4514+ "inflight": " 0 0",
4515+ "partition": "1",
4516+ "ro": "0",
4517+ "size": "6144000000",
4518+ "start": "192",
4519+ "stat": " 128 0 5568 160 0 0 0 0 0 280 280",
4520+ "subsystem": "block",
4521+ "uevent": "MAJOR=94\nMINOR=5\nDEVNAME=dasdb1\nDEVTYPE=partition\nPARTN=1"
4522+ }
4523+ },
4524+ "/dev/dasdb2": {
4525+ "DEVLINKS": "/dev/disk/by-id/ccw-0X151F-part2 /dev/disk/by-id/ccw-IBM.750000000DXP71.1500.1f-part2 /dev/disk/by-uuid/07c44238-17da-4548-8f94-046e5c1251d3 /dev/disk/by-path/ccw-0.0.151f-part2",
4526+ "DEVNAME": "/dev/dasdb2",
4527+ "DEVPATH": "/devices/css0/0.0.017f/0.0.151f/block/dasdb/dasdb2",
4528+ "DEVTYPE": "partition",
4529+ "ID_BUS": "ccw",
4530+ "ID_FS_TYPE": "crypto_LUKS",
4531+ "ID_FS_USAGE": "crypto",
4532+ "ID_FS_UUID": "07c44238-17da-4548-8f94-046e5c1251d3",
4533+ "ID_FS_UUID_ENC": "07c44238-17da-4548-8f94-046e5c1251d3",
4534+ "ID_FS_VERSION": "2",
4535+ "ID_PATH": "ccw-0.0.151f",
4536+ "ID_PATH_TAG": "ccw-0_0_151f",
4537+ "ID_SCSI": "1",
4538+ "ID_SERIAL": "0X151F",
4539+ "ID_TYPE": "disk",
4540+ "ID_UID": "IBM.750000000DXP71.1500.1f",
4541+ "ID_XUID": "IBM.750000000DXP71.1500.1f",
4542+ "MAJOR": "94",
4543+ "MINOR": "6",
4544+ "PARTN": "2",
4545+ "SUBSYSTEM": "block",
4546+ "TAGS": ":systemd:",
4547+ "USEC_INITIALIZED": "1279563871011",
4548+ "attrs": {
4549+ "alignment_offset": "0",
4550+ "dev": "94:6",
4551+ "discard_alignment": "0",
4552+ "inflight": " 0 0",
4553+ "partition": "2",
4554+ "ro": "0",
4555+ "size": "52937490432",
4556+ "start": "1500192",
4557+ "stat": " 113 0 1832 200 0 0 0 0 0 230 320",
4558+ "subsystem": "block",
4559+ "uevent": "MAJOR=94\nMINOR=6\nDEVNAME=dasdb2\nDEVTYPE=partition\nPARTN=2"
4560+ }
4561+ },
4562+ "/dev/dasdc": {
4563+ "DEVLINKS": "/dev/disk/by-path/ccw-0.0.1522 /dev/disk/by-id/ccw-IBM.750000000DXP71.1500.22 /dev/disk/by-id/ccw-0X1522",
4564+ "DEVNAME": "/dev/dasdc",
4565+ "DEVPATH": "/devices/css0/0.0.0182/0.0.1522/block/dasdc",
4566+ "DEVTYPE": "disk",
4567+ "ID_BUS": "ccw",
4568+ "ID_PATH": "ccw-0.0.1522",
4569+ "ID_PATH_TAG": "ccw-0_0_1522",
4570+ "ID_SERIAL": "0X1522",
4571+ "ID_TYPE": "disk",
4572+ "ID_UID": "IBM.750000000DXP71.1500.22",
4573+ "ID_XUID": "IBM.750000000DXP71.1500.22",
4574+ "MAJOR": "94",
4575+ "MINOR": "8",
4576+ "MPATH_SBIN_PATH": "/sbin",
4577+ "SUBSYSTEM": "block",
4578+ "TAGS": ":systemd:",
4579+ "USEC_INITIALIZED": "9503072",
4580+ "attrs": {
4581+ "alignment_offset": "0",
4582+ "bdi": null,
4583+ "capability": "10",
4584+ "dev": "94:8",
4585+ "device": null,
4586+ "discard_alignment": "0",
4587+ "ext_range": "4",
4588+ "hidden": "0",
4589+ "inflight": " 0 0",
4590+ "range": "4",
4591+ "removable": "0",
4592+ "ro": "0",
4593+ "size": "59082670080",
4594+ "stat": " 46350 0 3209608 4010 55144 368331 13826720 190440 0 1083958950 1084285940",
4595+ "subsystem": "block",
4596+ "uevent": "MAJOR=94\nMINOR=8\nDEVNAME=dasdc\nDEVTYPE=disk"
4597+ }
4598+ },
4599+ "/dev/dasdc1": {
4600+ "DEVLINKS": "/dev/disk/by-id/ccw-IBM.750000000DXP71.1500.22-part1 /dev/disk/by-id/ccw-0X1522-part1 /dev/disk/by-path/ccw-0.0.1522-part1",
4601+ "DEVNAME": "/dev/dasdc1",
4602+ "DEVPATH": "/devices/css0/0.0.0182/0.0.1522/block/dasdc/dasdc1",
4603+ "DEVTYPE": "partition",
4604+ "ID_BUS": "ccw",
4605+ "ID_PATH": "ccw-0.0.1522",
4606+ "ID_PATH_TAG": "ccw-0_0_1522",
4607+ "ID_SCSI": "1",
4608+ "ID_SERIAL": "0X1522",
4609+ "ID_TYPE": "disk",
4610+ "ID_UID": "IBM.750000000DXP71.1500.22",
4611+ "ID_XUID": "IBM.750000000DXP71.1500.22",
4612+ "MAJOR": "94",
4613+ "MINOR": "9",
4614+ "PARTN": "1",
4615+ "SUBSYSTEM": "block",
4616+ "TAGS": ":systemd:",
4617+ "USEC_INITIALIZED": "1279589828313",
4618+ "attrs": {
4619+ "alignment_offset": "0",
4620+ "dev": "94:9",
4621+ "discard_alignment": "0",
4622+ "inflight": " 0 0",
4623+ "partition": "1",
4624+ "ro": "0",
4625+ "size": "17180786688",
4626+ "start": "192",
4627+ "stat": " 102 0 5328 140 0 0 0 0 0 210 210",
4628+ "subsystem": "block",
4629+ "uevent": "MAJOR=94\nMINOR=9\nDEVNAME=dasdc1\nDEVTYPE=partition\nPARTN=1"
4630+ }
4631+ },
4632+ "/dev/dasdc2": {
4633+ "DEVLINKS": "/dev/disk/by-id/ccw-IBM.750000000DXP71.1500.22-part2 /dev/disk/by-path/ccw-0.0.1522-part2 /dev/disk/by-id/ccw-0X1522-part2",
4634+ "DEVNAME": "/dev/dasdc2",
4635+ "DEVPATH": "/devices/css0/0.0.0182/0.0.1522/block/dasdc/dasdc2",
4636+ "DEVTYPE": "partition",
4637+ "ID_BUS": "ccw",
4638+ "ID_PATH": "ccw-0.0.1522",
4639+ "ID_PATH_TAG": "ccw-0_0_1522",
4640+ "ID_SCSI": "1",
4641+ "ID_SERIAL": "0X1522",
4642+ "ID_TYPE": "disk",
4643+ "ID_UID": "IBM.750000000DXP71.1500.22",
4644+ "ID_XUID": "IBM.750000000DXP71.1500.22",
4645+ "MAJOR": "94",
4646+ "MINOR": "10",
4647+ "PARTN": "2",
4648+ "SUBSYSTEM": "block",
4649+ "TAGS": ":systemd:",
4650+ "USEC_INITIALIZED": "1279589824184",
4651+ "attrs": {
4652+ "alignment_offset": "0",
4653+ "dev": "94:10",
4654+ "discard_alignment": "0",
4655+ "inflight": " 0 0",
4656+ "partition": "2",
4657+ "ro": "0",
4658+ "size": "17180786688",
4659+ "start": "4194720",
4660+ "stat": " 94 0 4528 120 0 0 0 0 0 200 210",
4661+ "subsystem": "block",
4662+ "uevent": "MAJOR=94\nMINOR=10\nDEVNAME=dasdc2\nDEVTYPE=partition\nPARTN=2"
4663+ }
4664+ },
4665+ "/dev/dasdc3": {
4666+ "DEVLINKS": "/dev/disk/by-path/ccw-0.0.1522-part3 /dev/disk/by-id/ccw-0X1522-part3 /dev/disk/by-id/ccw-IBM.750000000DXP71.1500.22-part3",
4667+ "DEVNAME": "/dev/dasdc3",
4668+ "DEVPATH": "/devices/css0/0.0.0182/0.0.1522/block/dasdc/dasdc3",
4669+ "DEVTYPE": "partition",
4670+ "ID_BUS": "ccw",
4671+ "ID_PATH": "ccw-0.0.1522",
4672+ "ID_PATH_TAG": "ccw-0_0_1522",
4673+ "ID_SCSI": "1",
4674+ "ID_SERIAL": "0X1522",
4675+ "ID_TYPE": "disk",
4676+ "ID_UID": "IBM.750000000DXP71.1500.22",
4677+ "ID_XUID": "IBM.750000000DXP71.1500.22",
4678+ "MAJOR": "94",
4679+ "MINOR": "11",
4680+ "PARTN": "3",
4681+ "SUBSYSTEM": "block",
4682+ "TAGS": ":systemd:",
4683+ "USEC_INITIALIZED": "1279589831397",
4684+ "attrs": {
4685+ "alignment_offset": "0",
4686+ "dev": "94:11",
4687+ "discard_alignment": "0",
4688+ "inflight": " 0 0",
4689+ "partition": "3",
4690+ "ro": "0",
4691+ "size": "17180786688",
4692+ "start": "8389248",
4693+ "stat": " 94 0 4528 90 0 0 0 0 0 140 150",
4694+ "subsystem": "block",
4695+ "uevent": "MAJOR=94\nMINOR=11\nDEVNAME=dasdc3\nDEVTYPE=partition\nPARTN=3"
4696+ }
4697+ },
4698+ "/dev/dasdd": {
4699+ "DEVLINKS": "/dev/disk/by-path/ccw-0.0.1544",
4700+ "DEVNAME": "/dev/dasdd",
4701+ "DEVPATH": "/devices/css0/0.0.01a4/0.0.1544/block/dasdd",
4702+ "DEVTYPE": "disk",
4703+ "ID_PATH": "ccw-0.0.1544",
4704+ "ID_PATH_TAG": "ccw-0_0_1544",
4705+ "MAJOR": "94",
4706+ "MINOR": "12",
4707+ "MPATH_SBIN_PATH": "/sbin",
4708+ "SUBSYSTEM": "block",
4709+ "TAGS": ":systemd:",
4710+ "USEC_INITIALIZED": "9547551",
4711+ "attrs": {
4712+ "alignment_offset": "0",
4713+ "bdi": null,
4714+ "capability": "10",
4715+ "dev": "94:12",
4716+ "device": null,
4717+ "discard_alignment": "0",
4718+ "ext_range": "4",
4719+ "hidden": "0",
4720+ "inflight": " 0 0",
4721+ "range": "4",
4722+ "removable": "0",
4723+ "ro": "0",
4724+ "size": "177248010240",
4725+ "stat": " 17638 7942 928408 83980 256956 87209 13098840 251560 0 1876199440 1884679730",
4726+ "subsystem": "block",
4727+ "uevent": "MAJOR=94\nMINOR=12\nDEVNAME=dasdd\nDEVTYPE=disk"
4728+ }
4729+ },
4730+ "/dev/dasdd1": {
4731+ "DEVLINKS": "/dev/disk/by-path/ccw-0.0.1544-part1 /dev/disk/by-uuid/0ef8a516-dcab-43d4-84d5-b3fd9d355ca8",
4732+ "DEVNAME": "/dev/dasdd1",
4733+ "DEVPATH": "/devices/css0/0.0.01a4/0.0.1544/block/dasdd/dasdd1",
4734+ "DEVTYPE": "partition",
4735+ "ID_FS_TYPE": "ext4",
4736+ "ID_FS_USAGE": "filesystem",
4737+ "ID_FS_UUID": "0ef8a516-dcab-43d4-84d5-b3fd9d355ca8",
4738+ "ID_FS_UUID_ENC": "0ef8a516-dcab-43d4-84d5-b3fd9d355ca8",
4739+ "ID_FS_VERSION": "1.0",
4740+ "ID_PATH": "ccw-0.0.1544",
4741+ "ID_PATH_TAG": "ccw-0_0_1544",
4742+ "ID_SCSI": "1",
4743+ "MAJOR": "94",
4744+ "MINOR": "13",
4745+ "PARTN": "1",
4746+ "SUBSYSTEM": "block",
4747+ "TAGS": ":systemd:",
4748+ "USEC_INITIALIZED": "9576626",
4749+ "attrs": {
4750+ "alignment_offset": "0",
4751+ "dev": "94:13",
4752+ "discard_alignment": "0",
4753+ "inflight": " 0 0",
4754+ "partition": "1",
4755+ "ro": "0",
4756+ "size": "177246437376",
4757+ "start": "192",
4758+ "stat": " 17433 7942 926616 83910 256956 87209 13098840 251560 0 113880 479170",
4759+ "subsystem": "block",
4760+ "uevent": "MAJOR=94\nMINOR=13\nDEVNAME=dasdd1\nDEVTYPE=partition\nPARTN=1"
4761+ }
4762+ },
4763+ "/dev/dasde": {
4764+ "DEVLINKS": "/dev/disk/by-path/ccw-0.0.2520",
4765+ "DEVNAME": "/dev/dasde",
4766+ "DEVPATH": "/devices/css0/0.0.05e0/0.0.2520/block/dasde",
4767+ "DEVTYPE": "disk",
4768+ "ID_PATH": "ccw-0.0.2520",
4769+ "ID_PATH_TAG": "ccw-0_0_2520",
4770+ "MAJOR": "94",
4771+ "MINOR": "16",
4772+ "MPATH_SBIN_PATH": "/sbin",
4773+ "SUBSYSTEM": "block",
4774+ "TAGS": ":systemd:",
4775+ "USEC_INITIALIZED": "9583304",
4776+ "attrs": {
4777+ "alignment_offset": "0",
4778+ "bdi": null,
4779+ "capability": "10",
4780+ "dev": "94:16",
4781+ "device": null,
4782+ "discard_alignment": "0",
4783+ "ext_range": "4",
4784+ "hidden": "0",
4785+ "inflight": " 0 0",
4786+ "range": "4",
4787+ "removable": "0",
4788+ "ro": "0",
4789+ "size": "0",
4790+ "stat": " 0 0 0 0 0 0 0 0 0 0 0",
4791+ "subsystem": "block",
4792+ "uevent": "MAJOR=94\nMINOR=16\nDEVNAME=dasde\nDEVTYPE=disk"
4793+ }
4794+ },
4795+ "/dev/dm-0": {
4796+ "DEVLINKS": "/dev/disk/by-id/dm-name-36005076306ffd6b60000000000002409 /dev/disk/by-id/dm-uuid-mpath-36005076306ffd6b60000000000002409 /dev/disk/by-id/scsi-36005076306ffd6b60000000000002409 /dev/mapper/36005076306ffd6b60000000000002409 /dev/disk/by-id/wwn-0x6005076306ffd6b60000000000002409",
4797+ "DEVNAME": "/dev/dm-0",
4798+ "DEVPATH": "/devices/virtual/block/dm-0",
4799+ "DEVTYPE": "disk",
4800+ "DM_NAME": "36005076306ffd6b60000000000002409",
4801+ "DM_STATE": "ACTIVE",
4802+ "DM_SUSPENDED": "0",
4803+ "DM_TABLE_STATE": "LIVE",
4804+ "DM_TYPE": "scsi",
4805+ "DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG": "1",
4806+ "DM_UDEV_PRIMARY_SOURCE_FLAG": "1",
4807+ "DM_UDEV_RULES": "1",
4808+ "DM_UDEV_RULES_VSN": "2",
4809+ "DM_UUID": "mpath-36005076306ffd6b60000000000002409",
4810+ "DM_WWN": "0x6005076306ffd6b60000000000002409",
4811+ "ID_FS_LABEL": "s1lp6:raid5-2406-2407-2408-2409",
4812+ "ID_FS_LABEL_ENC": "s1lp6:raid5-2406-2407-2408-2409",
4813+ "ID_FS_TYPE": "linux_raid_member",
4814+ "ID_FS_USAGE": "raid",
4815+ "ID_FS_UUID": "7967c3f6-b6bb-2523-f515-9792ff8ac0f3",
4816+ "ID_FS_UUID_ENC": "7967c3f6-b6bb-2523-f515-9792ff8ac0f3",
4817+ "ID_FS_UUID_SUB": "a18d1237-26f5-d9b4-73dc-6530195cd76a",
4818+ "ID_FS_UUID_SUB_ENC": "a18d1237-26f5-d9b4-73dc-6530195cd76a",
4819+ "ID_FS_VERSION": "1.2",
4820+ "MAJOR": "253",
4821+ "MINOR": "0",
4822+ "MPATH_DEVICE_READY": "1",
4823+ "MPATH_SBIN_PATH": "/sbin",
4824+ "SUBSYSTEM": "block",
4825+ "TAGS": ":systemd:",
4826+ "USEC_INITIALIZED": "52574971799",
4827+ "attrs": {
4828+ "alignment_offset": "0",
4829+ "bdi": null,
4830+ "capability": "10",
4831+ "dev": "253:0",
4832+ "discard_alignment": "0",
4833+ "ext_range": "1",
4834+ "hidden": "0",
4835+ "inflight": " 0 0",
4836+ "range": "1",
4837+ "removable": "0",
4838+ "ro": "0",
4839+ "size": "10737418240",
4840+ "stat": " 1367 0 9532 310 1 0 1 0 0 680 680",
4841+ "subsystem": "block",
4842+ "uevent": "MAJOR=253\nMINOR=0\nDEVNAME=dm-0\nDEVTYPE=disk"
4843+ }
4844+ },
4845+ "/dev/dm-1": {
4846+ "DEVLINKS": "/dev/disk/by-id/dm-uuid-mpath-36005076306ffd6b60000000000002408 /dev/mapper/36005076306ffd6b60000000000002408 /dev/disk/by-id/wwn-0x6005076306ffd6b60000000000002408 /dev/disk/by-id/dm-name-36005076306ffd6b60000000000002408 /dev/disk/by-id/scsi-36005076306ffd6b60000000000002408",
4847+ "DEVNAME": "/dev/dm-1",
4848+ "DEVPATH": "/devices/virtual/block/dm-1",
4849+ "DEVTYPE": "disk",
4850+ "DM_NAME": "36005076306ffd6b60000000000002408",
4851+ "DM_STATE": "ACTIVE",
4852+ "DM_SUSPENDED": "0",
4853+ "DM_TABLE_STATE": "LIVE",
4854+ "DM_TYPE": "scsi",
4855+ "DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG": "1",
4856+ "DM_UDEV_PRIMARY_SOURCE_FLAG": "1",
4857+ "DM_UDEV_RULES": "1",
4858+ "DM_UDEV_RULES_VSN": "2",
4859+ "DM_UUID": "mpath-36005076306ffd6b60000000000002408",
4860+ "DM_WWN": "0x6005076306ffd6b60000000000002408",
4861+ "ID_FS_LABEL": "s1lp6:raid5-2406-2407-2408-2409",
4862+ "ID_FS_LABEL_ENC": "s1lp6:raid5-2406-2407-2408-2409",
4863+ "ID_FS_TYPE": "linux_raid_member",
4864+ "ID_FS_USAGE": "raid",
4865+ "ID_FS_UUID": "7967c3f6-b6bb-2523-f515-9792ff8ac0f3",
4866+ "ID_FS_UUID_ENC": "7967c3f6-b6bb-2523-f515-9792ff8ac0f3",
4867+ "ID_FS_UUID_SUB": "e96ca63b-c454-c133-2bcf-db53103a44f7",
4868+ "ID_FS_UUID_SUB_ENC": "e96ca63b-c454-c133-2bcf-db53103a44f7",
4869+ "ID_FS_VERSION": "1.2",
4870+ "MAJOR": "253",
4871+ "MINOR": "1",
4872+ "MPATH_DEVICE_READY": "1",
4873+ "MPATH_SBIN_PATH": "/sbin",
4874+ "SUBSYSTEM": "block",
4875+ "TAGS": ":systemd:",
4876+ "USEC_INITIALIZED": "52578275554",
4877+ "attrs": {
4878+ "alignment_offset": "0",
4879+ "bdi": null,
4880+ "capability": "10",
4881+ "dev": "253:1",
4882+ "discard_alignment": "0",
4883+ "ext_range": "1",
4884+ "hidden": "0",
4885+ "inflight": " 0 0",
4886+ "range": "1",
4887+ "removable": "0",
4888+ "ro": "0",
4889+ "size": "10737418240",
4890+ "stat": " 2442 213 25630 1230 1 0 1 0 0 1320 2110",
4891+ "subsystem": "block",
4892+ "uevent": "MAJOR=253\nMINOR=1\nDEVNAME=dm-1\nDEVTYPE=disk"
4893+ }
4894+ },
4895+ "/dev/dm-10": {
4896+ "DEVLINKS": "/dev/disk/by-uuid/6b920893-062d-4b24-bafd-7237e7eea19d /dev/mapper/storage_vg_242x-lv_tmp /dev/storage_vg_242x/lv_tmp /dev/disk/by-id/dm-name-storage_vg_242x-lv_tmp /dev/disk/by-id/dm-uuid-LVM-vK8pAtBwlyrZxQgOcgVSlj81LvyUnvq4OF1H7mF23XJIHlznOzyw9TFKGuD2g0ta",
4897+ "DEVNAME": "/dev/dm-10",
4898+ "DEVPATH": "/devices/virtual/block/dm-10",
4899+ "DEVTYPE": "disk",
4900+ "DM_ACTIVATION": "1",
4901+ "DM_LV_NAME": "lv_tmp",
4902+ "DM_NAME": "storage_vg_242x-lv_tmp",
4903+ "DM_STATE": "ACTIVE",
4904+ "DM_SUSPENDED": "0",
4905+ "DM_TABLE_STATE": "LIVE",
4906+ "DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG": "1",
4907+ "DM_UDEV_PRIMARY_SOURCE_FLAG": "1",
4908+ "DM_UDEV_RULES": "1",
4909+ "DM_UDEV_RULES_VSN": "2",
4910+ "DM_UUID": "LVM-vK8pAtBwlyrZxQgOcgVSlj81LvyUnvq4OF1H7mF23XJIHlznOzyw9TFKGuD2g0ta",
4911+ "DM_VG_NAME": "storage_vg_242x",
4912+ "ID_FS_TYPE": "ext4",
4913+ "ID_FS_USAGE": "filesystem",
4914+ "ID_FS_UUID": "6b920893-062d-4b24-bafd-7237e7eea19d",
4915+ "ID_FS_UUID_ENC": "6b920893-062d-4b24-bafd-7237e7eea19d",
4916+ "ID_FS_VERSION": "1.0",
4917+ "MAJOR": "253",
4918+ "MINOR": "10",
4919+ "SUBSYSTEM": "block",
4920+ "TAGS": ":systemd:",
4921+ "USEC_INITIALIZED": "52580163360",
4922+ "attrs": {
4923+ "alignment_offset": "0",
4924+ "bdi": null,
4925+ "capability": "10",
4926+ "dev": "253:10",
4927+ "discard_alignment": "0",
4928+ "ext_range": "1",
4929+ "hidden": "0",
4930+ "inflight": " 0 0",
4931+ "range": "1",
4932+ "removable": "0",
4933+ "ro": "0",
4934+ "size": "103066632192",
4935+ "stat": " 1918 0 63050 980 46606 0 381088 330 0 3947610 3948030",
4936+ "subsystem": "block",
4937+ "uevent": "MAJOR=253\nMINOR=10\nDEVNAME=dm-10\nDEVTYPE=disk"
4938+ }
4939+ },
4940+ "/dev/dm-2": {
4941+ "DEVLINKS": "/dev/disk/by-id/wwn-0x6005076306ffd6b60000000000002406 /dev/disk/by-id/dm-uuid-mpath-36005076306ffd6b60000000000002406 /dev/disk/by-id/dm-name-36005076306ffd6b60000000000002406 /dev/disk/by-id/scsi-36005076306ffd6b60000000000002406 /dev/disk/by-uuid/308b3159-5497-48e7-84d7-cac358c4e228 /dev/mapper/36005076306ffd6b60000000000002406",
4942+ "DEVNAME": "/dev/dm-2",
4943+ "DEVPATH": "/devices/virtual/block/dm-2",
4944+ "DEVTYPE": "disk",
4945+ "DM_NAME": "36005076306ffd6b60000000000002406",
4946+ "DM_STATE": "ACTIVE",
4947+ "DM_SUSPENDED": "0",
4948+ "DM_TABLE_STATE": "LIVE",
4949+ "DM_TYPE": "scsi",
4950+ "DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG": "1",
4951+ "DM_UDEV_PRIMARY_SOURCE_FLAG": "1",
4952+ "DM_UDEV_RULES": "1",
4953+ "DM_UDEV_RULES_VSN": "2",
4954+ "DM_UUID": "mpath-36005076306ffd6b60000000000002406",
4955+ "DM_WWN": "0x6005076306ffd6b60000000000002406",
4956+ "ID_FS_TYPE": "bcache",
4957+ "ID_FS_UUID": "308b3159-5497-48e7-84d7-cac358c4e228",
4958+ "ID_FS_UUID_ENC": "308b3159-5497-48e7-84d7-cac358c4e228",
4959+ "MAJOR": "253",
4960+ "MINOR": "2",
4961+ "MPATH_DEVICE_READY": "1",
4962+ "MPATH_SBIN_PATH": "/sbin",
4963+ "SUBSYSTEM": "block",
4964+ "TAGS": ":systemd:",
4965+ "USEC_INITIALIZED": "52578383687",
4966+ "attrs": {
4967+ "alignment_offset": "0",
4968+ "bdi": null,
4969+ "capability": "10",
4970+ "dev": "253:2",
4971+ "discard_alignment": "0",
4972+ "ext_range": "1",
4973+ "hidden": "0",
4974+ "inflight": " 0 0",
4975+ "range": "1",
4976+ "removable": "0",
4977+ "ro": "0",
4978+ "size": "10737418240",
4979+ "stat": " 1747 0 28036 270 5 1 25 0 0 650 650",
4980+ "subsystem": "block",
4981+ "uevent": "MAJOR=253\nMINOR=2\nDEVNAME=dm-2\nDEVTYPE=disk"
4982+ }
4983+ },
4984+ "/dev/dm-3": {
4985+ "DEVLINKS": "/dev/disk/by-id/lvm-pv-uuid-c9yFym-fhMk-BHHc-nXDt-uxYY-xmQV-oWg69m /dev/mapper/36005076306ffd6b60000000000002422 /dev/disk/by-id/dm-uuid-mpath-36005076306ffd6b60000000000002422 /dev/disk/by-id/scsi-36005076306ffd6b60000000000002422 /dev/disk/by-id/dm-name-36005076306ffd6b60000000000002422 /dev/disk/by-id/wwn-0x6005076306ffd6b60000000000002422",
4986+ "DEVNAME": "/dev/dm-3",
4987+ "DEVPATH": "/devices/virtual/block/dm-3",
4988+ "DEVTYPE": "disk",
4989+ "DM_ACTIVATION": "0",
4990+ "DM_NAME": "36005076306ffd6b60000000000002422",
4991+ "DM_STATE": "ACTIVE",
4992+ "DM_SUBSYSTEM_UDEV_FLAG0": "1",
4993+ "DM_SUSPENDED": "0",
4994+ "DM_TABLE_STATE": "LIVE",
4995+ "DM_TYPE": "scsi",
4996+ "DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG": "1",
4997+ "DM_UDEV_PRIMARY_SOURCE_FLAG": "1",
4998+ "DM_UDEV_RULES": "1",
4999+ "DM_UDEV_RULES_VSN": "2",
5000+ "DM_UUID": "mpath-36005076306ffd6b60000000000002422",
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches