Merge ~raharper/curtin:feature/block-discover into curtin:master

Proposed by Ryan Harper
Status: Merged
Approved by: Ryan Harper
Approved revision: 7a91b3192669514676f038f635c5f33731625782
Merge reported by: Server Team CI bot
Merged at revision: not available
Proposed branch: ~raharper/curtin:feature/block-discover
Merge into: curtin:master
Diff against target: 24190 lines (+23625/-65)
28 files modified
curtin/block/__init__.py (+26/-0)
curtin/block/schemas.py (+53/-16)
curtin/block/zfs.py (+4/-0)
curtin/commands/block_discover.py (+20/-0)
curtin/commands/curthooks.py (+13/-0)
curtin/commands/main.py (+2/-2)
curtin/deps/__init__.py (+1/-0)
curtin/pack.py (+7/-0)
curtin/storage_config.py (+923/-24)
debian/control (+1/-0)
examples/tests/vmtest_defaults.yaml (+33/-0)
pylintrc (+13/-1)
tests/data/live-iso.json (+811/-0)
tests/data/probert_storage_diglett.json (+14624/-0)
tests/data/probert_storage_dmcrypt.json (+2200/-0)
tests/data/probert_storage_lvm.json (+958/-0)
tests/data/probert_storage_mdadm_bcache.json (+1348/-0)
tests/data/probert_storage_zfs.json (+1883/-0)
tests/unittests/test_block_zfs.py (+15/-15)
tests/unittests/test_storage_config.py (+620/-0)
tests/vmtests/__init__.py (+2/-0)
tests/vmtests/test_zfsroot.py (+7/-0)
tools/block-discover-to-config (+33/-0)
tools/run-pep8 (+9/-0)
tools/run-pyflakes (+9/-0)
tools/schema-validate-storage (+3/-2)
tools/vmtest-sync-images (+6/-4)
tools/write-curtin (+1/-1)
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve
Chad Smith Approve
Review via email: mp+365376@code.launchpad.net

Commit message

block-discover: add cli/API for exporting existing storage to config

Curtin can now probe an existing system for block devices and convert that
information into a storage_config yaml document representing the devices,
partitions, filesystems, etc as they would be if created from scratch.

This cli and API depend upon probert for discovery and
curtin.storage_config.validate_config to generate valid configs.

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michael Hudson-Doyle (mwhudson) :
Revision history for this message
Dan Watkins (oddbloke) wrote :

Checkpointing my review before I dig in to the large block of added code line-by-line, and also to kick off a higher-level discussion so we can have that in parallel with my more detailed review:

In that large block of added code, it looks like the parse_* functions are using the same pattern (i.e. parse_foo calls foo_asdict, which then has some helpers). I wonder if we could reduce repeated code and make it a little more formally clear which functions are related to one another if we encapsulated this in a class structure. I'm thinking something like (using raid as the concrete example):

class ProbertParser:

    def parse(self, probe_data):
        configs = []
        errors = []
        for devname, data in probe_data.get(self.probe_data_key, {}).items():
            entry = self.asdict(data, probe_data)
            if entry:
                try:
                    validate_config(entry)
                except ValueError as e:
                    errors.append(e)
                    continue
                configs.append(entry)
        return (configs, errors)

class RaidProbertParser(ProbertParser):

    probe_data_key = 'raid'

    def asdict(self, data, probe_data):
        <the current raid_asdict code>

This pattern wouldn't work perfectly for every parse_* function, but the advantage of using classes is that only those objects that require something extraordinary from the parse method will redefine it (whereas currently you have to keep all the parse_* definitions in your head to effectively determine which ones are using the standard pattern and which are doing something different).

If it turns out that there isn't enough commonality between the parse_* functions to justify a method shared on the super-class, I still think class definitions would be a good way of encapsulating the functions that are required for a particular parse_* function, which would make the code easier to grok.

(
```
$ python -m this | tail -n1
Namespaces are one honking great idea -- let's do more of those!
```
;-)

Revision history for this message
Dan Watkins (oddbloke) wrote :

Another high-level comment: this MP doesn't appear to introduce any testing for the new functionality; am I missing something?

Revision history for this message
Ryan Harper (raharper) wrote :

The pattern is similar, there is some cross parsing helpers I'll need to sort out how that's shared, and while they all accept some form of probe_data, it does vary.

I'll look into classifying in the next iteration.

Revision history for this message
Ryan Harper (raharper) wrote :

> Another high-level comment: this MP doesn't appear to introduce any testing
> for the new functionality; am I missing something?

No, I've not written unittests yet. The work is mostly manually verified so
I'll need to get something more formal in the vmtest.

I was initially interested in comparing the input yaml to a vmtest with what we get
out of curtin block-discover after we boot into it; however some challenges include
that our input isn't strictly ordered in the same way as block-discover, for example

In our input file, we typically list all type:disks at the top and then add further dependent items like partitions, and curtin will ensure that an entries dependencies are ordered before, but something like a disk with a single partition may not be listed in the same spot.

Additionally the id: values are manually created when we defined the scenario, where as block-discover will auto-generate id values based on their type and underlying device:

We might have {type: disk, id: sda}, and discover would produce {type: disk: id: disk-sda}.

Revision history for this message
Dan Watkins (oddbloke) wrote :

(Checkpointing my review to respond to Ryan's comments; I've reached the top of parse_zfs.)

> The pattern is similar, there is some cross parsing helpers I'll need to sort out how that's shared, and while they all accept some form of probe_data, it does vary.

I think it's fine to keep shared helpers as module-level functions (unless they make more sense as methods to you, of course). If only shared helpers are in the module namespace then their presence there is meaningful.

> I'll look into classifying in the next iteration.

Thanks!

> I was initially interested in comparing the input yaml to a vmtest with what we get out of curtin block-discover after we boot into it; however some challenges include that our input isn't strictly ordered in the same way as block-discover, for example

I really like this idea. Given that block-discover is strictly ordered, we presumably _could_ get to a point where the vmtest input matches the output? I don't know a great deal about how the vmtests work, but if we had a flag that defaulted to False that indicated we should perform this test then we would be able to do this progressively.

(If we decide that integrating it in to the vmtests isn't worthwhile, a one-time pass capturing the probert output might make a solid starting point for unittests?)

Revision history for this message
Dan Watkins (oddbloke) wrote :

And I forgot to look at the inline comments.

Revision history for this message
Dan Watkins (oddbloke) wrote :

First review complete.

Revision history for this message
Ryan Harper (raharper) :
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Chad Smith (chad.smith) wrote :

This is huge Ryan. Thanks for this heculean effort. I've commented on a few missed earlier review comments, pylint still doesn't work for me or CI it seems.

Any of my comments are included as changes in this pastebin http://paste.ubuntu.com/p/rVQRwwkzCM/

Note in the above pasebin a TODO for you to decide

If you are able to wrangle pylint to work I'm good on this branch.

review: Approve
Revision history for this message
Ryan Harper (raharper) wrote :

Thanks for the review Chad and the paste for quick apply. All of what you mentioned was worth fixing.

I dropped one comment around the volgroup name, specifically the presence of items in the 'volume_groups' dictionary will necessarily include a key, so we won't get None values for the volgroup field.

There may be no volume_groups at all, but we'll not call volgroup_asdict() without a valid one.

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

Checkpointing my review here as I need to take a break. Made it as far as RaidParser.

Revision history for this message
Dan Watkins (oddbloke) wrote :

A few more additional inline thoughts; I've reviewed the entire available diff, but I believe that there are some changes that Launchpad isn't showing.

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

Thanks for the review. I've accepted most of the changes. I couple of replies in-line for the ones I didn't.

Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Dan Watkins (oddbloke) wrote :
Download full text (3.2 KiB)

Instead of saying thanks on all the inline changes, I'll say it here:
thanks!

On Wed, May 01, 2019 at 06:03:45PM -0000, Ryan Harper wrote:
> > + if self.probe_data_key in probe_data:
> > + data = self.probe_data.get(self.probe_data_key)
>
> In some of the probe types, we'll have keys set but empty, for example
> if probert found no lvm data on the system, we see things like:
>
> storage:
> lvm: {}
>
> And the datatype parser handles the lack of data.
>
> That said, if probe data had something like:
>
> storage:
> lvm: None
>
> We would blow up on non-dict type, so maybe in the base class I can
> check for none-ish values and set the attribute to {}.

Ah, OK, I see. I think that would be an improvement but it probably
isn't vital.

> > + if not self.blockdev_data:
> > + raise ValueError('probe_data missing valid "blockdev" data')
> > +
> > + def parse(self):
> > + raise NotImplementedError()
>
> Probably. What does subclassing from ABC get us over the above?

If a subclass hasn't overriden an abstract method, we will get the error
on instantiation of the class. With the NotImplementedError route, we
only get it once we call the missing method.

I don't think it's hugely important provided we have good test coverage
so we will catch any such missing methods, perhaps just something to
consider for the next time we do something like this.

(It also gives static analysis tools a bit more to work on, so they can
also tell you via your editor when you've failed to correctly subclass
an ABC.)

> > +
> > + def blockdev_byid_to_devname(self, link):
> > + """ Lookup blockdev by devlink and convert to storage_config id. """
> > + bd_key = self.lookup_devname(link)
> > + if bd_key:
> > + return self.blockdev_to_id(self.blockdev_data[bd_key])
> > + return None
> > +
> > +
> > +class BcacheParser(ProbertParser):
> > +
> > + probe_data_key = 'bcache'
> > +
> > + def __init__(self, probe_data):
> > + super(BcacheParser, self).__init__(probe_data)
> > + self.backing = self.bcache_data.get('backing', {})
> > + self.caching = self.bcache_data.get('caching', {})
> > +
> > + def parse(self):
> > + """parse probert 'bcache' data format.
> > +
> > + Collects storage config type: bcache for valid
> > + data and returns tuple of lists, configs, errors.
> > + """
> > + configs = []
> > + errors = []
> > + for dev_uuid, bdata in self.backing.items():
> > + entry = self.asdict(dev_uuid, bdata)
> > + if entry:
> > + try:
> > + validate_config(entry)
> > + except ValueError as e:
> > + errors.append(e)
> > + continue
> > + configs.append(entry)
> > + return (configs, errors)
> > +
> > + def asdict(self, backing_uuid, backing_data):
> > + """ process a specific bcache entry and return
> > + a curtin storage config dictionary. """
> > +
> > + def _sb_get(data, attr):
>
> I see what you're saying (TIL closures vs. anonymous f...

Read more...

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

OK. Full vmtest run revealed three issues that need fixing:

1) msdos partition table flags aren't getting set in exported storage-config (test_lvm.py reveals this)
2) msdos extended partition size is not calculated correctly
3) dm_crypt devices need parsing/handling (test_mdadm_bcache.py:TestAllindata)

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

Thank you for the updates Ryan, a couple of nits, a one minor bug found I think.

Revision history for this message
Ryan Harper (raharper) wrote :

Thanks, I'll fix those up.

Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Chad Smith (chad.smith) wrote :

Thanks for the fixups. LGTM!

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

Commit message lints:
 - Line #0 has 8 too many characters. Line starts with: "block-discover: add cli"...

review: Needs Fixing
Revision history for this message
Ryan Harper (raharper) wrote :

Fixed the commit message

Revision history for this message
Server Team CI bot (server-team-bot) wrote :

FAILED: Autolanding.
More details in the following jenkins job:
https://jenkins.ubuntu.com/server/job/curtin-autoland-test/191/
Executed test runs:
    None: https://jenkins.ubuntu.com/server/job/admin-lp-git-autoland/456/console

review: Needs Fixing (continuous-integration)
Revision history for this message
Ryan Harper (raharper) wrote :

Of course vmtest times out while landing.... trying again..

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/curtin/block/__init__.py b/curtin/block/__init__.py
2index f858b37..5d1b1bd 100644
3--- a/curtin/block/__init__.py
4+++ b/curtin/block/__init__.py
5@@ -13,6 +13,7 @@ from curtin.block import lvm
6 from curtin.block import multipath
7 from curtin.log import LOG
8 from curtin.udev import udevadm_settle, udevadm_info
9+from curtin import storage_config
10
11
12 def get_dev_name_entry(devname):
13@@ -1099,4 +1100,29 @@ def get_supported_filesystems():
14 return [l.split('\t')[1].strip()
15 for l in util.load_file(proc_fs).splitlines()]
16
17+
18+def discover():
19+ try:
20+ LOG.debug('Importing probert prober')
21+ from probert import prober
22+ except Exception:
23+ LOG.error('Failed to import probert, discover disabled')
24+ return {}
25+
26+ probe = prober.Prober()
27+ LOG.debug('Probing system for storage devices')
28+ probe.probe_storage()
29+ probe_data = probe.get_results()
30+ if 'storage' not in probe_data:
31+ raise ValueError('Probing storage failed')
32+
33+ LOG.debug('Extracting storage config from discovered devices')
34+ try:
35+ return storage_config.extract_storage_config(probe_data.get('storage'))
36+ except ImportError as e:
37+ LOG.exception(e)
38+
39+ return {}
40+
41+
42 # vi: ts=4 expandtab syntax=python
43diff --git a/curtin/block/schemas.py b/curtin/block/schemas.py
44index 3761733..fb7507d 100644
45--- a/curtin/block/schemas.py
46+++ b/curtin/block/schemas.py
47@@ -4,6 +4,9 @@ _uuid_pattern = (
48 r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')
49 _path_dev = r'^/dev/[^/]+(/[^/]+)*$'
50 _path_nondev = r'(^/$|^(/[^/]+)+$)'
51+_fstypes = ['btrfs', 'ext2', 'ext3', 'ext4', 'fat', 'fat12', 'fat16', 'fat32',
52+ 'iso9660', 'vfat', 'jfs', 'ntfs', 'reiserfs', 'swap', 'xfs',
53+ 'zfsroot']
54
55 definitions = {
56 'id': {'type': 'string'},
57@@ -11,19 +14,23 @@ definitions = {
58 'devices': {'type': 'array', 'items': {'$ref': '#/definitions/ref_id'}},
59 'name': {'type': 'string'},
60 'preserve': {'type': 'boolean'},
61- 'ptable': {'type': 'string', 'oneOf': [{'enum': ['gpt', 'msdos']}]},
62+ 'ptable': {'type': 'string', 'enum': ['dos', 'gpt', 'msdos']},
63 'size': {'type': ['string', 'number'],
64 'minimum': 1,
65 'pattern': r'^([1-9]\d*(.\d+)?|\d+.\d+)(K|M|G|T)?B?'},
66 'wipe': {
67 'type': 'string',
68- 'oneOf': [{'enum': ['random', 'superblock',
69- 'superblock-recursive', 'zero']}],
70+ 'enum': ['random', 'superblock', 'superblock-recursive', 'zero'],
71 },
72 'uuid': {
73 'type': 'string',
74 'pattern': _uuid_pattern,
75 },
76+ 'fstype': {
77+ 'type': 'string',
78+ 'oneOf': [
79+ {'pattern': r'^__.*__$'}, # XXX: Accept vmtest values?
80+ {'enum': _fstypes}]},
81 'params': {
82 'type': 'object',
83 'patternProperties': {
84@@ -59,8 +66,39 @@ BCACHE = {
85 'type': {'const': 'bcache'},
86 'cache_mode': {
87 'type': ['string'],
88- 'oneOf': [{'enum': ['writethrough', 'writeback',
89- 'writearound', 'none']}],
90+ 'enum': ['writethrough', 'writeback', 'writearound', 'none'],
91+ },
92+ },
93+}
94+DASD = {
95+ '$schema': 'http://json-schema.org/draft-07/schema#',
96+ 'name': 'CURTIN-DASD',
97+ 'title': 'curtin storage configuration for dasds',
98+ 'description': (
99+ 'Declarative syntax for specifying a dasd device.'),
100+ 'definitions': definitions,
101+ 'required': ['id', 'type', 'device_id'],
102+ 'type': 'object',
103+ 'additionalProperties': False,
104+ 'properties': {
105+ 'id': {'$ref': '#/definitions/id'},
106+ 'name': {'$ref': '#/definitions/name'},
107+ 'preserve': {'$ref': '#/definitions/preserve'},
108+ 'type': {'const': 'dasd'},
109+ 'blocksize': {
110+ 'type': ['integer', 'string'],
111+ 'oneOf': [{'enum': [512, 1024, 2048, 4096]},
112+ {'enum': ['512', '1024', '2048', '4096']}],
113+ },
114+ 'device_id': {'type': 'string'},
115+ 'label': {'type': 'string', 'maxLength': 6},
116+ 'mode': {
117+ 'type': ['string'],
118+ 'enum': ['expand', 'full', 'quick'],
119+ },
120+ 'disk_layout': {
121+ 'type': ['string'],
122+ 'enum': ['cdl', 'ldl'],
123 },
124 },
125 }
126@@ -93,7 +131,12 @@ DISK = {
127 {'pattern': r'^iscsi:.*'}],
128 },
129 'model': {'type': 'string'},
130- 'wwn': {'type': 'string', 'pattern': r'^0x(\d|[a-zA-Z])+'},
131+ 'wwn': {
132+ 'type': 'string',
133+ 'oneOf': [
134+ {'pattern': r'^0x(\d|[a-zA-Z])+'},
135+ {'pattern': r'^nvme\.(\d|[a-zA-Z]-)+'}],
136+ },
137 'grub_device': {
138 'type': ['boolean', 'integer'],
139 'minimum': 0,
140@@ -137,13 +180,7 @@ FORMAT = {
141 'preserve': {'$ref': '#/definitions/preserve'},
142 'uuid': {'$ref': '#/definitions/uuid'}, # XXX: This is not used
143 'type': {'const': 'format'},
144- 'fstype': {
145- 'type': 'string',
146- 'oneOf': [
147- {'pattern': r'^__.*__$'}, # XXX: Accept vmtest values?
148- {'enum': ['btrfs', 'ext2', 'ext3', 'ext4', 'fat', 'fat12',
149- 'fat16', 'fat32', 'vfat', 'jfs', 'ntfs', 'reiserfs',
150- 'swap', 'xfs', 'zfsroot']}]},
151+ 'fstype': {'$ref': '#/definitions/fstype'},
152 'label': {'type': 'string'},
153 'volume': {'$ref': '#/definitions/ref_id'},
154 }
155@@ -240,9 +277,9 @@ PARTITION = {
156 'minimum': 1},
157 'device': {'$ref': '#/definitions/ref_id'},
158 'flag': {'type': 'string',
159- 'oneOf': [
160- {'enum': ['bios_grub', 'boot', 'extended', 'home',
161- 'logical', 'lvm', 'prep', 'raid', 'swap', '']}]},
162+ 'enum': ['bios_grub', 'boot', 'extended', 'home', 'linux',
163+ 'logical', 'lvm', 'mbr', 'prep', 'raid', 'swap',
164+ '']},
165 }
166 }
167 RAID = {
168diff --git a/curtin/block/zfs.py b/curtin/block/zfs.py
169index 5615144..dce15c3 100644
170--- a/curtin/block/zfs.py
171+++ b/curtin/block/zfs.py
172@@ -158,6 +158,10 @@ def zpool_create(poolname, vdevs, mountpoint=None, altroot=None,
173 cmd = ["zpool", "create"] + options + [poolname] + vdevs
174 util.subp(cmd, capture=True)
175
176+ # Trigger generation of zpool.cache file
177+ cmd = ["zpool", "set", "cachefile=/etc/zfs/zpool.cache", poolname]
178+ util.subp(cmd, capture=True)
179+
180
181 def zfs_create(poolname, volume, zfs_properties=None):
182 """
183diff --git a/curtin/commands/block_discover.py b/curtin/commands/block_discover.py
184new file mode 100644
185index 0000000..f309970
186--- /dev/null
187+++ b/curtin/commands/block_discover.py
188@@ -0,0 +1,20 @@
189+# This file is part of curtin. See LICENSE file for copyright and license info.
190+
191+import json
192+from . import populate_one_subcmd
193+from curtin import block
194+
195+
196+def block_discover_main(args):
197+ """probe for existing devices and emit Curtin storage config output."""
198+
199+ print(json.dumps(block.discover(), indent=2, sort_keys=True))
200+
201+
202+CMD_ARGUMENTS = ()
203+
204+
205+def POPULATE_SUBCMD(parser):
206+ populate_one_subcmd(parser, CMD_ARGUMENTS, block_discover_main)
207+
208+# vi: ts=4 expandtab syntax=python
209diff --git a/curtin/commands/curthooks.py b/curtin/commands/curthooks.py
210index 7d9cc9f..75f5083 100644
211--- a/curtin/commands/curthooks.py
212+++ b/curtin/commands/curthooks.py
213@@ -586,6 +586,14 @@ def copy_mdadm_conf(mdadm_conf, target):
214 'etc/mdadm/mdadm.conf']))
215
216
217+def copy_zpool_cache(zpool_cache, target):
218+ if not zpool_cache:
219+ LOG.warn("zpool_cache path must be specified, not copying")
220+ return
221+
222+ shutil.copy(zpool_cache, os.path.sep.join([target, 'etc/zfs']))
223+
224+
225 def apply_networking(target, state):
226 netconf = state.get('network_config')
227 interfaces = state.get('interfaces')
228@@ -1366,6 +1374,11 @@ def builtin_curthooks(cfg, target, state):
229 handle_pollinate_user_agent(cfg, target)
230
231 if osfamily == DISTROS.debian:
232+ # check for the zpool cache file and copy to target if present
233+ zpool_cache = '/etc/zfs/zpool.cache'
234+ if os.path.exists(zpool_cache):
235+ copy_zpool_cache(zpool_cache, target)
236+
237 # If a crypttab file was created by block_meta than it needs to be
238 # copied onto the target system, and update_initramfs() needs to be
239 # run, so that the cryptsetup hooks are properly configured on the
240diff --git a/curtin/commands/main.py b/curtin/commands/main.py
241index 150f1e2..df97b7d 100644
242--- a/curtin/commands/main.py
243+++ b/curtin/commands/main.py
244@@ -15,8 +15,8 @@ VERSIONSTR = version.version_string()
245
246 SUB_COMMAND_MODULES = [
247 'apply_net', 'apt-config', 'block-attach-iscsi', 'block-detach-iscsi',
248- 'block-info', 'block-meta', 'block-wipe', 'clear-holders', 'curthooks',
249- 'collect-logs', 'extract', 'features',
250+ 'block-discover', 'block-info', 'block-meta', 'block-wipe',
251+ 'clear-holders', 'curthooks', 'collect-logs', 'extract', 'features',
252 'hook', 'install', 'mkfs', 'in-target', 'net-meta', 'pack',
253 'schema-validate', 'swap', 'system-install', 'system-upgrade',
254 'unmount', 'version',
255diff --git a/curtin/deps/__init__.py b/curtin/deps/__init__.py
256index 96df4f6..37c4469 100644
257--- a/curtin/deps/__init__.py
258+++ b/curtin/deps/__init__.py
259@@ -16,6 +16,7 @@ from curtin.distro import install_packages, lsb_release
260 REQUIRED_IMPORTS = [
261 # import string to execute, python2 package, python3 package
262 ('import yaml', 'python-yaml', 'python3-yaml'),
263+ ('import pyudev', 'python-pyudev', 'python3-pyudev'),
264 ]
265
266 REQUIRED_EXECUTABLES = [
267diff --git a/curtin/pack.py b/curtin/pack.py
268index 11430e9..1dd42fb 100644
269--- a/curtin/pack.py
270+++ b/curtin/pack.py
271@@ -107,6 +107,13 @@ def pack(fdout=None, command=None, paths=None, copy_files=None,
272 if copy_files is None:
273 copy_files = []
274
275+ try:
276+ from probert import prober
277+ psource = os.path.dirname(prober.__file__)
278+ copy_files.append(('probert', psource),)
279+ except Exception:
280+ pass
281+
282 tmpd = None
283 try:
284 tmpd = tempfile.mkdtemp()
285diff --git a/curtin/storage_config.py b/curtin/storage_config.py
286index ce05a09..a79f30b 100644
287--- a/curtin/storage_config.py
288+++ b/curtin/storage_config.py
289@@ -1,15 +1,21 @@
290 # This file is part of curtin. See LICENSE file for copyright and license info.
291-import copy
292 from collections import namedtuple, OrderedDict
293+import copy
294+import operator
295+import os
296+import re
297+import yaml
298
299 from curtin.log import LOG
300 from curtin.block import schemas
301 from curtin import config as curtin_config
302+from curtin import util
303
304
305 StorageConfig = namedtuple('StorageConfig', ('type', 'schema'))
306 STORAGE_CONFIG_TYPES = {
307 'bcache': StorageConfig(type='bcache', schema=schemas.BCACHE),
308+ 'dasd': StorageConfig(type='dasd', schema=schemas.DASD),
309 'disk': StorageConfig(type='disk', schema=schemas.DISK),
310 'dm_crypt': StorageConfig(type='dm_crypt', schema=schemas.DM_CRYPT),
311 'format': StorageConfig(type='format', schema=schemas.FORMAT),
312@@ -62,14 +68,19 @@ def load_and_validate(config_path):
313 LOG.info('Skipping %s, missing "storage" key' % config_path)
314 return
315
316- return validate_config(config.get('storage'))
317+ return validate_config(config.get('storage'), sourcefile=config_path)
318
319
320-def validate_config(config):
321+def validate_config(config, sourcefile=None):
322 """Validate storage config object."""
323+ if not sourcefile:
324+ sourcefile = ''
325 try:
326 import jsonschema
327 jsonschema.validate(config, STORAGE_CONFIG_SCHEMA)
328+ except ImportError:
329+ LOG.error('Cannot validate storage config, missing jsonschema')
330+ raise
331 except jsonschema.exceptions.ValidationError as e:
332 if isinstance(e.instance, int):
333 msg = 'Unexpected value (%s) for property "%s"' % (e.path[0],
334@@ -85,7 +96,8 @@ def validate_config(config):
335 try:
336 jsonschema.validate(e.instance, stype.schema)
337 except jsonschema.exceptions.ValidationError as f:
338- msg = "%s in %s" % (f.message, e.instance)
339+ msg = "%s in %s\n%s" % (f.message, sourcefile,
340+ util.json_dumps(e.instance))
341 raise(ValueError(msg))
342 else:
343 msg = "Unknown storage type: %s in %s" % (instance_type,
344@@ -112,21 +124,43 @@ def _stype_to_deps(stype):
345 """
346
347 depends_keys = {
348- 'bcache': set('backing_device', 'cache_device'),
349- 'disk': set(),
350- 'dm_crypt': set('volume'),
351- 'format': set('volume'),
352- 'lvm_partition': set('volgroup'),
353- 'lvm_volgroup': set('devices'),
354- 'mount': set('device'),
355- 'partition': set('device'),
356- 'raid': set('devices', 'spare_devices'),
357- 'zfs': set('pool'),
358- 'zpool': set('vdevs'),
359+ 'bcache': {'backing_device', 'cache_device'},
360+ 'dasd': set(),
361+ 'disk': {'device_id'},
362+ 'dm_crypt': {'volume'},
363+ 'format': {'volume'},
364+ 'lvm_partition': {'volgroup'},
365+ 'lvm_volgroup': {'devices'},
366+ 'mount': {'device'},
367+ 'partition': {'device'},
368+ 'raid': {'devices', 'spare_devices'},
369+ 'zfs': {'pool'},
370+ 'zpool': {'vdevs'},
371 }
372 return depends_keys[stype]
373
374
375+def _stype_to_order_key(stype):
376+ default_sort = {'id'}
377+ order_key = {
378+ 'bcache': {'name'},
379+ 'disk': default_sort,
380+ 'dm_crypt': default_sort,
381+ 'format': default_sort,
382+ 'lvm_partition': {'name'},
383+ 'lvm_volgroup': {'name'},
384+ 'mount': {'path'},
385+ 'partition': {'number'},
386+ 'raid': default_sort,
387+ 'zfs': {'volume'},
388+ 'zpool': default_sort,
389+ }
390+ if stype not in order_key:
391+ raise ValueError('Unknown storage type: %s' % stype)
392+
393+ return order_key.get(stype)
394+
395+
396 # Document what each storage type can be composed from.
397 def _validate_dep_type(source_id, dep_key, dep_id, sconfig):
398 '''check if dependency type is in the list of allowed by source'''
399@@ -135,7 +169,8 @@ def _validate_dep_type(source_id, dep_key, dep_id, sconfig):
400 depends = {
401 'bcache': {'bcache', 'disk', 'dm_crypt', 'lvm_partition',
402 'partition', 'raid'},
403- 'disk': {},
404+ 'dasd': {},
405+ 'disk': {'device_id'},
406 'dm_crypt': {'bcache', 'disk', 'dm_crypt', 'lvm_partition',
407 'partition', 'raid'},
408 'format': {'bcache', 'disk', 'dm_crypt', 'lvm_partition',
409@@ -143,7 +178,7 @@ def _validate_dep_type(source_id, dep_key, dep_id, sconfig):
410 'lvm_partition': {'lvm_volgroup'},
411 'lvm_volgroup': {'bcache', 'disk', 'dm_crypt', 'partition', 'raid'},
412 'mount': {'format'},
413- 'partition': {'bcache', 'disk', 'raid'},
414+ 'partition': {'bcache', 'disk', 'raid', 'partition'},
415 'raid': {'bcache', 'disk', 'dm_crypt', 'lvm_partition',
416 'partition'},
417 'zfs': {'zpool'},
418@@ -166,8 +201,9 @@ def _validate_dep_type(source_id, dep_key, dep_id, sconfig):
419
420 source_deps = depends[source_type]
421 result = dep_type in source_deps
422- LOG.debug('Validate: SourceType:%s -> (DepId:%s DepType:%s) in '
423- 'SourceDeps:%s ? result=%s' % (source_type, dep_id, dep_type,
424+ LOG.debug('Validate: %s:SourceType:%s -> (DepId:%s DepType:%s) in '
425+ 'SourceDeps:%s ? result=%s' % (source_id, source_type,
426+ dep_id, dep_type,
427 source_deps, result))
428 if not result:
429 # Partition(sda1).device -> Partition(sda3)
430@@ -190,8 +226,13 @@ def find_item_dependencies(item_id, config, validate=True):
431 if not item_cfg:
432 return None
433
434+ def _find_same_dep(dep_key, dep_value, config):
435+ return [item_id for item_id, item_cfg in config.items()
436+ if item_cfg.get(dep_key) == dep_value]
437+
438 deps = []
439 item_type = item_cfg.get('type')
440+ item_order = _stype_to_order_key(item_type)
441 for dep_key in _stype_to_deps(item_type):
442 if dep_key in item_cfg:
443 dep_value = item_cfg[dep_key]
444@@ -202,9 +243,20 @@ def find_item_dependencies(item_id, config, validate=True):
445 if validate:
446 _validate_dep_type(item_id, dep_key, dep, config)
447
448- d = find_item_dependencies(dep, config)
449- if d:
450- deps.extend(d)
451+ # find other items with the same dep_key, dep_value
452+ same_deps = _find_same_dep(dep_key, dep, config)
453+ sdeps_cfgs = [cfg for sdep, cfg in config.items()
454+ if sdep in same_deps]
455+ sorted_deps = (
456+ sorted(sdeps_cfgs,
457+ key=operator.itemgetter(*list(item_order))))
458+ for sdep in sorted_deps:
459+ deps.append(sdep['id'])
460+
461+ # find lower level deps
462+ lower_deps = find_item_dependencies(dep, config)
463+ if lower_deps:
464+ deps.extend(lower_deps)
465
466 return deps
467
468@@ -255,9 +307,35 @@ def merge_config_trees_to_list(config_trees):
469 raise ValueError('Duplicate id: %s' % top_item_id)
470 reg[top_item_id] = {'level': level, 'config': item_cfg}
471
472+ def sort_level(configs):
473+ sreg = {}
474+ for cfg in configs:
475+ if cfg['type'] in sreg:
476+ sreg[cfg['type']].append(cfg)
477+ else:
478+ sreg[cfg['type']] = [cfg]
479+
480+ result = []
481+ for item_type in sorted(sreg.keys()):
482+ iorder = _stype_to_order_key(item_type)
483+ isorted = sorted(sreg[item_type],
484+ key=operator.itemgetter(*list(iorder)))
485+ result.extend(isorted)
486+
487+ return result
488+
489 # [entry for tag in tags]
490- return [entry['config'] for lvl in range(0, max_level + 1)
491- for _, entry in reg.items() if entry['level'] == lvl]
492+ merged = []
493+ for lvl in range(0, max_level + 1):
494+ level_configs = []
495+ for item_id, entry in reg.items():
496+ if entry['level'] == lvl:
497+ level_configs.append(entry['config'])
498+
499+ sconfigs = sort_level(level_configs)
500+ merged.extend(sconfigs)
501+
502+ return merged
503
504
505 def config_tree_to_list(config_tree):
506@@ -283,4 +361,825 @@ def extract_storage_ordered_dict(config):
507 # its index and the component of storage_config as its value
508 return OrderedDict((d["id"], d) for d in scfg)
509
510+
511+class ProbertParser(object):
512+ """ Base class for parsing probert storage configuration.
513+
514+ This will hold common methods of the various storage type
515+ parsers.
516+ """
517+ # In subclasses 'probe_data_key' value will select a subset of
518+ # Probert probe_data if the value is present. If the probe_data
519+ # is incomplete, we raise a ValuError. This selection allows the
520+ # subclass to handle parsing one portion of the data and will be
521+ # accessed in the subclass via 'class_data' member.
522+ probe_data_key = None
523+ class_data = None
524+
525+ def __init__(self, probe_data):
526+ if not probe_data or not isinstance(probe_data, dict):
527+ raise ValueError('Invalid probe_data: %s' % probe_data)
528+
529+ self.probe_data = probe_data
530+ if self.probe_data_key is not None:
531+ if self.probe_data_key in probe_data:
532+ data = self.probe_data.get(self.probe_data_key)
533+ if not data:
534+ data = {}
535+ self.class_data = data
536+ else:
537+ raise ValueError('probe_data missing %s data' %
538+ self.probe_data_key)
539+
540+ # We keep a reference to the blockdev_data on the superclass
541+ # as each specific parser has common needs to reference
542+ # this data separate from the BlockdevParser class.
543+ self.blockdev_data = self.probe_data.get('blockdev')
544+ if not self.blockdev_data:
545+ raise ValueError('probe_data missing valid "blockdev" data')
546+
547+ def parse(self):
548+ raise NotImplementedError()
549+
550+ def asdict(self, data):
551+ raise NotImplementedError()
552+
553+ def lookup_devname(self, devname):
554+ """ Search 'blockdev' space for "devname". The device
555+ name may not be a kernel name, so if not found in
556+ the dictionary keys, search under 'DEVLINKS' of each
557+ device and return the dictionary for the kernel.
558+ """
559+ if devname in self.blockdev_data:
560+ return devname
561+
562+ for bd_key, bdata in self.blockdev_data.items():
563+ devlinks = bdata.get('DEVLINKS', '').split()
564+ if devname in devlinks:
565+ return bd_key
566+
567+ return None
568+
569+ def blockdev_to_id(self, blockdev):
570+ """ Examine a blockdev dictionary and return a tuple of curtin
571+ storage type and name that can be used as a value for
572+ storage_config ids (opaque reference to other storage_config
573+ elements).
574+ """
575+ def is_mpath(blockdev):
576+ return bool(blockdev.get('DM_UUID', '').startswith('mpath-'))
577+
578+ def is_dmcrypt(blockdev):
579+ return bool(blockdev.get('DM_UUID', '').startswith('CRYPT-LUKS'))
580+
581+ devtype = blockdev.get('DEVTYPE', 'MISSING')
582+ devname = blockdev.get('DEVNAME', 'MISSING')
583+ name = os.path.basename(devname)
584+ if devname.startswith('/dev/dm-'):
585+ # device mapper names are composed deviecs, let's
586+ # look at udev data to see what it's really
587+ if 'DM_LV_NAME' in blockdev:
588+ devtype = 'lvm-partition'
589+ name = blockdev['DM_LV_NAME']
590+ elif is_mpath(blockdev):
591+ name = blockdev['DM_UUID']
592+ elif is_dmcrypt(blockdev):
593+ devtype = 'dmcrypt'
594+ name = blockdev['DM_NAME']
595+ elif devname.startswith('/dev/md'):
596+ if 'MD_NAME' in blockdev:
597+ devtype = 'raid'
598+
599+ for key, val in {'name': name, 'devtype': devtype}.items():
600+ if not val or val == 'MISSING':
601+ msg = 'Failed to extract %s data: %s' % (key, blockdev)
602+ raise ValueError(msg)
603+
604+ return "%s-%s" % (devtype, name)
605+
606+ def blockdev_byid_to_devname(self, link):
607+ """ Lookup blockdev by devlink and convert to storage_config id. """
608+ bd_key = self.lookup_devname(link)
609+ if bd_key:
610+ return self.blockdev_to_id(self.blockdev_data[bd_key])
611+ return None
612+
613+
614+class BcacheParser(ProbertParser):
615+
616+ probe_data_key = 'bcache'
617+
618+ def __init__(self, probe_data):
619+ super(BcacheParser, self).__init__(probe_data)
620+ self.backing = self.class_data.get('backing', {})
621+ self.caching = self.class_data.get('caching', {})
622+
623+ def parse(self):
624+ """parse probert 'bcache' data format.
625+
626+ Collects storage config type: bcache for valid
627+ data and returns tuple of lists, configs, errors.
628+ """
629+ configs = []
630+ errors = []
631+ for dev_uuid, bdata in self.backing.items():
632+ entry = self.asdict(dev_uuid, bdata)
633+ if entry:
634+ try:
635+ validate_config(entry)
636+ except ValueError as e:
637+ errors.append(e)
638+ continue
639+ configs.append(entry)
640+ return (configs, errors)
641+
642+ def asdict(self, backing_uuid, backing_data):
643+ """ process a specific bcache entry and return
644+ a curtin storage config dictionary. """
645+
646+ def _sb_get(data, attr):
647+ return data.get('superblock', {}).get(attr)
648+
649+ def _find_cache_device(backing_data, cache_data):
650+ cset_uuid = _sb_get(backing_data, 'cset.uuid')
651+ msg = ('Invalid "blockdev" value for cache device '
652+ 'uuid=%s' % cset_uuid)
653+ if not cset_uuid:
654+ raise ValueError(msg)
655+
656+ for devuuid, config in cache_data.items():
657+ cache = _sb_get(config, 'cset.uuid')
658+ if cache == cset_uuid:
659+ return config['blockdev']
660+
661+ return None
662+
663+ def _find_bcache_devname(uuid, backing_data, blockdev_data):
664+ by_uuid = '/dev/bcache/by-uuid/' + uuid
665+ label = _sb_get(backing_data, 'dev.label')
666+ for devname, data in blockdev_data.items():
667+ if devname.startswith('/dev/bcache'):
668+ # DEVLINKS is a space separated list
669+ devlinks = data.get('DEVLINKS', '').split()
670+ if by_uuid in devlinks:
671+ return devname
672+ if label:
673+ return label
674+ raise ValueError('Failed to find bcache %s ' % (by_uuid))
675+
676+ def _cache_mode(dev_data):
677+ # "1 [writeback]" -> "writeback"
678+ attr = _sb_get(dev_data, 'dev.data.cache_mode')
679+ if attr:
680+ return attr.split()[1][1:-1]
681+
682+ return None
683+
684+ backing_device = backing_data.get('blockdev')
685+ cache_device = _find_cache_device(backing_data, self.caching)
686+ cache_mode = _cache_mode(backing_data)
687+ bcache_name = os.path.basename(
688+ _find_bcache_devname(backing_uuid, backing_data,
689+ self.blockdev_data))
690+ bcache_entry = {'type': 'bcache', 'id': 'disk-%s' % bcache_name,
691+ 'name': bcache_name}
692+
693+ if cache_mode:
694+ bcache_entry['cache_mode'] = cache_mode
695+ if backing_device:
696+ bcache_entry['backing_device'] = self.blockdev_to_id(
697+ self.blockdev_data[backing_device])
698+
699+ if cache_device:
700+ bcache_entry['cache_device'] = self.blockdev_to_id(
701+ self.blockdev_data[cache_device])
702+
703+ return bcache_entry
704+
705+
706+class BlockdevParser(ProbertParser):
707+
708+ probe_data_key = 'blockdev'
709+
710+ def parse(self):
711+ """ parse probert 'blockdev' data format.
712+
713+ returns tuple with list of blockdev entries converted to
714+ storage config and any validation errors.
715+ """
716+ configs = []
717+ errors = []
718+
719+ for devname, data in self.blockdev_data.items():
720+ # skip composed devices here
721+ if data.get('DEVPATH', '').startswith('/devices/virtual'):
722+ continue
723+ entry = self.asdict(data)
724+ if entry:
725+ try:
726+ validate_config(entry)
727+ except ValueError as e:
728+ errors.append(e)
729+ continue
730+ configs.append(entry)
731+ return (configs, errors)
732+
733+ def ptable_uuid_to_flag_entry(self, guid):
734+ # map
735+ # https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs
736+ # to
737+ # curtin/commands/block_meta.py:partition_handler()sgdisk_flags/types
738+ guid_map = {
739+ 'C12A7328-F81F-11D2-BA4B-00A0C93EC93B': ('boot', 'EF00'),
740+ '21686148-6449-6E6F-744E-656564454649': ('bios_grub', 'EF02'),
741+ '933AC7E1-2EB4-4F13-B844-0E14E2AEF915': ('home', '8302'),
742+ '0FC63DAF-8483-4772-8E79-3D69D8477DE4': ('linux', '8300'),
743+ 'E6D6D379-F507-44C2-A23C-238F2A3DF928': ('lvm', '8e00'),
744+ '024DEE41-33E7-11D3-9D69-0008C781F39F': ('mbr', ''),
745+ '9E1A2D38-C612-4316-AA26-8B49521E5A8B': ('prep', '4200'),
746+ 'A19D880F-05FC-4D3B-A006-743F0F84911E': ('raid', 'fd00'),
747+ '0657FD6D-A4AB-43C4-84E5-0933C84B4F4F': ('swap', '8200'),
748+ '0X83': ('linux', '83'),
749+ '0XF': ('extended', 'f'),
750+ }
751+ name = code = None
752+ if guid and guid.upper() in guid_map:
753+ name, code = guid_map[guid.upper()]
754+
755+ return (name, code)
756+
757+ def get_unique_ids(self, blockdev):
758+ """ extract preferred ID_* keys for www and serial values.
759+
760+ In some cases, ID_ values have duplicate values, this
761+ method returns the preferred value for a specific
762+ blockdev attribute.
763+ """
764+ uniq = {}
765+ source_keys = {
766+ 'wwn': ['ID_WWN_WITH_EXTENSION', 'ID_WWN'],
767+ 'serial': ['ID_SERIAL', 'ID_SERIAL_SHORT'],
768+ }
769+ for skey, id_keys in source_keys.items():
770+ for id_key in id_keys:
771+ if id_key in blockdev and skey not in uniq:
772+ uniq[skey] = blockdev[id_key]
773+
774+ return uniq
775+
776+ def partition_parent_devname(self, blockdev):
777+ """ Return the devname of a partition's parent.
778+ md0p1 -> /dev/md0
779+ vda1 -> /dev/vda
780+ nvme0n1p3 -> /dev/nvme0n1
781+ """
782+ if blockdev['DEVTYPE'] != "partition":
783+ raise ValueError('Invalid blockdev, DEVTYPE is not partition')
784+
785+ pdevpath = blockdev.get('DEVPATH')
786+ if pdevpath:
787+ return '/dev/' + os.path.basename(os.path.dirname(pdevpath))
788+
789+ def asdict(self, blockdev_data):
790+ """ process blockdev_data and return a curtin
791+ storage config dictionary. This method
792+ will return curtin storage types: disk, partition.
793+ """
794+ # just disks and partitions
795+ if blockdev_data['DEVTYPE'] not in ["disk", "partition"]:
796+ return None
797+
798+ # https://www.kernel.org/doc/Documentation/admin-guide/devices.txt
799+ # Ignore Floppy (block MAJOR=2), CDROM (block MAJOR=11)
800+ # XXX: Possible expansion on this in the future.
801+ if blockdev_data['MAJOR'] in ["11", "2"]:
802+ return None
803+
804+ devname = blockdev_data.get('DEVNAME')
805+ entry = {
806+ 'type': blockdev_data['DEVTYPE'],
807+ 'id': self.blockdev_to_id(blockdev_data),
808+ }
809+
810+ # default disks to gpt
811+ if entry['type'] == 'disk':
812+ uniq_ids = self.get_unique_ids(blockdev_data)
813+ # always include path, block_meta will prefer wwn/serial over path
814+ uniq_ids.update({'path': devname})
815+ # set wwn, serial, and path
816+ entry.update(uniq_ids)
817+
818+ # default to gpt if not present
819+ entry['ptable'] = blockdev_data.get('ID_PART_TABLE_TYPE', 'gpt')
820+ return entry
821+
822+ if entry['type'] == 'partition':
823+ attrs = blockdev_data['attrs']
824+ entry['number'] = int(attrs['partition'])
825+ parent_devname = self.partition_parent_devname(blockdev_data)
826+ parent_blockdev = self.blockdev_data[parent_devname]
827+ ptable = parent_blockdev.get('partitiontable')
828+ if ptable:
829+ part = None
830+ for pentry in ptable['partitions']:
831+ node = pentry['node']
832+ if node.lstrip(parent_devname) == attrs['partition']:
833+ part = pentry
834+ break
835+
836+ if part is None:
837+ raise RuntimeError(
838+ "Couldn't find partition entry in table")
839+ else:
840+ part = attrs
841+
842+ # sectors 512B sector units in both attrs and ptable
843+ offset_val = int(part['start']) * 512
844+ if offset_val > 0:
845+ entry['offset'] = offset_val
846+
847+ # ptable size field is in sectors
848+ entry['size'] = int(part['size'])
849+ if ptable:
850+ entry['size'] *= 512
851+
852+ ptype = blockdev_data.get('ID_PART_ENTRY_TYPE')
853+ flag_name, _flag_code = self.ptable_uuid_to_flag_entry(ptype)
854+
855+ # logical partitions are not tagged in data, however
856+ # the partition number > 4 (ie, not primary nor extended)
857+ if ptable and ptable.get('label') == 'dos' and entry['number'] > 4:
858+ flag_name = 'logical'
859+
860+ if flag_name:
861+ entry['flag'] = flag_name
862+
863+ # determine parent blockdev and calculate the device id
864+ if parent_blockdev:
865+ device_id = self.blockdev_to_id(parent_blockdev)
866+ if device_id:
867+ entry['device'] = device_id
868+
869+ return entry
870+
871+
872+class FilesystemParser(ProbertParser):
873+
874+ probe_data_key = 'filesystem'
875+
876+ def parse(self):
877+ """parse probert 'filesystem' data format.
878+
879+ returns tuple with list entries converted to
880+ storage config type:format and any validation errors.
881+ """
882+ configs = []
883+ errors = []
884+ for devname, data in self.class_data.items():
885+ blockdev_data = self.blockdev_data.get(devname)
886+ if not blockdev_data:
887+ err = ('No probe data found for blockdev '
888+ '%s for fs: %s' % (devname, data))
889+ errors.append(err)
890+ continue
891+
892+ # no floppy, no cdrom
893+ if blockdev_data['MAJOR'] in ["11", "2"]:
894+ continue
895+
896+ volume_id = self.blockdev_to_id(blockdev_data)
897+
898+ # don't capture non-filesystem usage
899+ if data['USAGE'] != "filesystem":
900+ continue
901+
902+ # ignore types that we cannot create
903+ if data['TYPE'] not in schemas._fstypes:
904+ continue
905+
906+ entry = self.asdict(volume_id, data)
907+ if entry:
908+ try:
909+ validate_config(entry)
910+ except ValueError as e:
911+ errors.append(e)
912+ continue
913+ configs.append(entry)
914+ return (configs, errors)
915+
916+ def asdict(self, volume_id, fs_data):
917+ """ process fs_data and return a curtin storage config dict.
918+ This method will return curtin storage type: format.
919+ {
920+ 'LABEL': xxxx,
921+ 'TYPE': ext2,
922+ 'UUID': .....,
923+ }
924+ """
925+ entry = {
926+ 'id': 'format-' + volume_id,
927+ 'type': 'format',
928+ 'volume': volume_id,
929+ 'fstype': fs_data.get('TYPE'),
930+ }
931+ uuid = fs_data.get('UUID')
932+ if uuid:
933+ valid_uuid = re.match(schemas._uuid_pattern, uuid)
934+ if valid_uuid:
935+ entry['uuid'] = uuid
936+
937+ return entry
938+
939+
940+class LvmParser(ProbertParser):
941+
942+ probe_data_key = 'lvm'
943+
944+ def lvm_partition_asdict(self, lv_name, lv_config):
945+ return {'type': 'lvm_partition',
946+ 'id': 'lvm-partition-%s' % lv_config['name'],
947+ 'name': lv_config['name'],
948+ 'size': lv_config['size'],
949+ 'volgroup': 'lvm-volgroup-%s' % lv_config['volgroup']}
950+
951+ def lvm_volgroup_asdict(self, vg_name, vg_config):
952+ """ process volgroup probe structure into storage config dict."""
953+ blockdev_ids = []
954+ for pvol in vg_config.get('devices', []):
955+ pvol_bdev = self.lookup_devname(pvol)
956+ blockdev_data = self.blockdev_data[pvol_bdev]
957+ if blockdev_data:
958+ blockdev_ids.append(self.blockdev_to_id(blockdev_data))
959+
960+ return {'type': 'lvm_volgroup',
961+ 'id': 'lvm-volgroup-%s' % vg_name,
962+ 'name': vg_name,
963+ 'devices': sorted(blockdev_ids)}
964+
965+ def parse(self):
966+ """parse probert 'lvm' data format.
967+
968+ returns tuple with list entries converted to
969+ storage config type:lvm_partition, type:lvm_volgroup
970+ and any validation errors.
971+ """
972+ # exit early if lvm_data is empty
973+ if 'volume_groups' not in self.class_data:
974+ return ([], [])
975+
976+ configs = []
977+ errors = []
978+ for vg_name, vg_config in self.class_data['volume_groups'].items():
979+ entry = self.lvm_volgroup_asdict(vg_name, vg_config)
980+ if entry:
981+ try:
982+ validate_config(entry)
983+ except ValueError as e:
984+ errors.append(e)
985+ continue
986+ configs.append(entry)
987+ for lv_name, lv_config in self.class_data['logical_volumes'].items():
988+ entry = self.lvm_partition_asdict(lv_name, lv_config)
989+ if entry:
990+ try:
991+ validate_config(entry)
992+ except ValueError as e:
993+ errors.append(e)
994+ continue
995+ configs.append(entry)
996+
997+ return (configs, errors)
998+
999+
1000+class DmcryptParser(ProbertParser):
1001+
1002+ probe_data_key = 'dmcrypt'
1003+
1004+ def asdict(self, crypt_config):
1005+ crypt_name = crypt_config['name']
1006+ backing_dev = crypt_config['blkdevs_used']
1007+ if not backing_dev.startswith('/dev/'):
1008+ backing_dev = os.path.join('/dev', backing_dev)
1009+
1010+ bdev = self.lookup_devname(backing_dev)
1011+ bdev_data = self.blockdev_data[bdev]
1012+ bdev_id = self.blockdev_to_id(bdev_data) if bdev_data else None
1013+ if not bdev_id:
1014+ raise ValueError('Cannot find blockdev id for %s' % bdev)
1015+
1016+ return {'type': 'dm_crypt',
1017+ 'id': 'dmcrypt-%s' % crypt_name,
1018+ 'volume': bdev_id,
1019+ 'key': '',
1020+ 'dm_name': crypt_name}
1021+
1022+ def parse(self):
1023+ """parse probert 'dmcrypt' data format.
1024+
1025+ returns tuple of lists: (configs, errors)
1026+ contain configs of type:dmcrypt and any errors.
1027+ """
1028+ configs = []
1029+ errors = []
1030+ for crypt_name, crypt_config in self.class_data.items():
1031+ entry = self.asdict(crypt_config)
1032+ if entry:
1033+ try:
1034+ validate_config(entry)
1035+ except ValueError as e:
1036+ errors.append(e)
1037+ continue
1038+ configs.append(entry)
1039+ return (configs, errors)
1040+
1041+
1042+class RaidParser(ProbertParser):
1043+
1044+ probe_data_key = 'raid'
1045+
1046+ def asdict(self, raid_data):
1047+ devname = raid_data.get('DEVNAME', 'NODEVNAMEKEY')
1048+ # FIXME, need to handle rich md_name values, rather than mdX
1049+ # LP: #1803933
1050+ raidname = os.path.basename(devname)
1051+ return {'type': 'raid',
1052+ 'id': 'raid-%s' % raidname,
1053+ 'name': raidname,
1054+ 'raidlevel': raid_data.get('raidlevel'),
1055+ 'devices': sorted([
1056+ self.blockdev_to_id(self.blockdev_data[dev])
1057+ for dev in raid_data.get('devices')]),
1058+ 'spare_devices': sorted([
1059+ self.blockdev_to_id(self.blockdev_data[dev])
1060+ for dev in raid_data.get('spare_devices')])}
1061+
1062+ def parse(self):
1063+ """parse probert 'raid' data format.
1064+
1065+ Collects storage config type: raid for valid
1066+ data and returns tuple of lists, configs, errors.
1067+ """
1068+
1069+ configs = []
1070+ errors = []
1071+ for devname, data in self.class_data.items():
1072+ entry = self.asdict(data)
1073+ if entry:
1074+ try:
1075+ validate_config(entry)
1076+ except ValueError as e:
1077+ errors.append(e)
1078+ continue
1079+ configs.append(entry)
1080+ return (configs, errors)
1081+
1082+
1083+class MountParser(ProbertParser):
1084+
1085+ probe_data_key = 'mount'
1086+
1087+ def asdict(self, mdata):
1088+ # the source value may be a devlink alias, look it up
1089+ source = self.lookup_devname(mdata.get('source'))
1090+
1091+ # we can filter mounts for block devices only
1092+ # this excludes lots of sys/proc/dev/cgroup
1093+ # mounts that are found but not related to
1094+ # storage config
1095+ # XXX: bind mounts might need some work here
1096+ if not source:
1097+ return {}
1098+
1099+ # no floppy, no cdrom
1100+ if self.blockdev_data[source]['MAJOR'] in ["11", "2"]:
1101+ return {}
1102+
1103+ source_id = self.blockdev_to_id(self.blockdev_data[source])
1104+ return {'type': 'mount',
1105+ 'id': 'mount-%s' % source_id,
1106+ 'path': mdata.get('target'),
1107+ 'device': 'format-%s' % source_id}
1108+
1109+ def parse(self):
1110+ """parse probert 'mount' data format
1111+
1112+ mount : [{.. 'children': [..]}]
1113+
1114+ Collects storage config type: mount for valid
1115+ data and returns tuple of lists: (configs, errors)
1116+ """
1117+ def collect_mounts(mdata):
1118+ mounts = [self.asdict(mdata)]
1119+ for child in mdata.get('children', []):
1120+ mounts.extend(collect_mounts(child))
1121+ return [mnt for mnt in mounts if mnt]
1122+
1123+ configs = []
1124+ errors = []
1125+ for mdata in self.class_data:
1126+ collected_mounts = collect_mounts(mdata)
1127+ for entry in collected_mounts:
1128+ try:
1129+ validate_config(entry)
1130+ except ValueError as e:
1131+ errors.append(e)
1132+ continue
1133+ configs.append(entry)
1134+ return (configs, errors)
1135+
1136+
1137+class ZfsParser(ProbertParser):
1138+
1139+ probe_data_key = 'zfs'
1140+
1141+ def get_local_ds_properties(self, dataset):
1142+ """ extract a dictionary of propertyname: value
1143+ for any property that has a source of 'local'
1144+ which means it's been set by configuration.
1145+ """
1146+ if 'properties' not in dataset:
1147+ return {}
1148+
1149+ set_props = {}
1150+ for prop_name, setting in dataset['properties'].items():
1151+ if setting['source'] == 'local':
1152+ set_props[prop_name] = setting['value']
1153+
1154+ return set_props
1155+
1156+ def zpool_asdict(self, name, zpool_data):
1157+ """ convert zpool data and convert to curtin storage_config dict.
1158+ """
1159+ vdevs = []
1160+ zdb = zpool_data.get('zdb', {})
1161+ for child_name, child_config in zdb.get('vdev_tree', {}).items():
1162+ if not child_name.startswith('children'):
1163+ continue
1164+ path = child_config.get('path')
1165+ devname = self.blockdev_byid_to_devname(path)
1166+ # skip any zpools not backed by blockdevices
1167+ if not devname:
1168+ continue
1169+ vdevs.append(devname)
1170+
1171+ if len(vdevs) == 0:
1172+ return None
1173+
1174+ id_name = 'zpool-%s-%s' % (os.path.basename(vdevs[0]), name)
1175+ return {'type': 'zpool',
1176+ 'id': id_name,
1177+ 'pool': name,
1178+ 'vdevs': sorted(vdevs)}
1179+
1180+ def zfs_asdict(self, ds_name, ds_properties, zpool_data):
1181+ # ignore the base pool name (rpool) vs (rpool/ROOT/zfsroot)
1182+ if '/' not in ds_name or not zpool_data:
1183+ return
1184+
1185+ id_name = 'zfs-%s' % ds_name.replace('/', '-')
1186+ parent_zpool_name = zpool_data.get('pool')
1187+ return {'type': 'zfs',
1188+ 'id': id_name,
1189+ 'pool': zpool_data.get('id'),
1190+ 'volume': ds_name.split(parent_zpool_name)[-1],
1191+ 'properties': ds_properties}
1192+
1193+ def parse(self):
1194+ """ parse probert 'zfs' data format
1195+
1196+ zfs: {
1197+ 'zpools': {
1198+ '<pool1>': {
1199+ 'datasets': {
1200+ <dataset1>: {
1201+ "properties": {
1202+ "propname": {'source': "default",
1203+ 'value': "<value>"},
1204+ }
1205+ }
1206+ }
1207+ 'zdb': {
1208+ ...
1209+ vdev_tree: {
1210+ childrens[N]: {
1211+ 'path': '/dev/disk/by-id/foo',
1212+ }
1213+ }
1214+ version: 28,
1215+ }
1216+ }
1217+ }
1218+ }
1219+ """
1220+
1221+ errors = []
1222+ zpool_configs = []
1223+ zfs_configs = []
1224+
1225+ for zp_name, zp_data in self.class_data.get('zpools', {}).items():
1226+ zpool_entry = self.zpool_asdict(zp_name, zp_data)
1227+ if zpool_entry:
1228+ try:
1229+ validate_config(zpool_entry)
1230+ except ValueError as e:
1231+ errors.append(e)
1232+ zpool_entry = None
1233+
1234+ datasets = zp_data.get('datasets')
1235+ for ds in datasets.keys():
1236+ ds_props = self.get_local_ds_properties(datasets[ds])
1237+ zfs_entry = self.zfs_asdict(ds, ds_props, zpool_entry)
1238+ if zfs_entry:
1239+ try:
1240+ validate_config(zfs_entry)
1241+ except ValueError as e:
1242+ errors.append(e)
1243+ continue
1244+ zfs_configs.append(zfs_entry)
1245+
1246+ if zpool_entry:
1247+ zpool_configs.append(zpool_entry)
1248+
1249+ return (zpool_configs + zfs_configs, errors)
1250+
1251+
1252+def extract_storage_config(probe_data):
1253+ """ Examine a probert storage dictionary and extract a curtin
1254+ storage configuration that would recreate all of the
1255+ storage devices present in the provided data.
1256+
1257+ Returns a storage config dictionary
1258+ """
1259+ convert_map = {
1260+ 'bcache': BcacheParser,
1261+ 'blockdev': BlockdevParser,
1262+ 'dmcrypt': DmcryptParser,
1263+ 'filesystem': FilesystemParser,
1264+ 'lvm': LvmParser,
1265+ 'raid': RaidParser,
1266+ 'mount': MountParser,
1267+ 'zfs': ZfsParser,
1268+ }
1269+ configs = []
1270+ errors = []
1271+ LOG.debug('Extracting storage config from probe data')
1272+ for ptype, pname in convert_map.items():
1273+ parser = pname(probe_data)
1274+ found_cfgs, found_errs = parser.parse()
1275+ configs.extend(found_cfgs)
1276+ errors.extend(found_errs)
1277+
1278+ LOG.debug('Sorting extracted configurations')
1279+ disk = [cfg for cfg in configs if cfg.get('type') == 'disk']
1280+ part = [cfg for cfg in configs if cfg.get('type') == 'partition']
1281+ format = [cfg for cfg in configs if cfg.get('type') == 'format']
1282+ lvols = [cfg for cfg in configs if cfg.get('type') == 'lvm_volgroup']
1283+ lparts = [cfg for cfg in configs if cfg.get('type') == 'lvm_partition']
1284+ raids = [cfg for cfg in configs if cfg.get('type') == 'raid']
1285+ dmcrypts = [cfg for cfg in configs if cfg.get('type') == 'dm_crypt']
1286+ mounts = [cfg for cfg in configs if cfg.get('type') == 'mount']
1287+ bcache = [cfg for cfg in configs if cfg.get('type') == 'bcache']
1288+ zpool = [cfg for cfg in configs if cfg.get('type') == 'zpool']
1289+ zfs = [cfg for cfg in configs if cfg.get('type') == 'zfs']
1290+
1291+ ordered = (disk + part + format + lvols + lparts + raids + dmcrypts +
1292+ mounts + bcache + zpool + zfs)
1293+
1294+ final_config = {'storage': {'version': 1, 'config': ordered}}
1295+ try:
1296+ LOG.info('Validating extracted storage config components')
1297+ validate_config(final_config['storage'])
1298+ except ValueError as e:
1299+ errors.append(e)
1300+
1301+ for e in errors:
1302+ LOG.exception('Validation error: %s\n' % e)
1303+ if len(errors) > 0:
1304+ raise RuntimeError("Extract storage config does not validate.")
1305+
1306+ # build and merge probed data into a valid storage config by
1307+ # generating a config tree for each item in the probed data
1308+ # and then merging the trees, which resolves dependencies
1309+ # and produced a dependency ordered storage config
1310+ LOG.debug("Extracted (unmerged) storage config:\n%s",
1311+ yaml.dump({'storage': ordered},
1312+ indent=4, default_flow_style=False))
1313+
1314+ LOG.debug("Generating storage config dependencies")
1315+ ctrees = []
1316+ for cfg in ordered:
1317+ tree = get_config_tree(cfg.get('id'), final_config)
1318+ ctrees.append(tree)
1319+
1320+ LOG.debug("Merging storage config dependencies")
1321+ merged_config = {
1322+ 'version': 1,
1323+ 'config': merge_config_trees_to_list(ctrees)
1324+ }
1325+ LOG.debug("Merged storage config:\n%s",
1326+ yaml.dump({'storage': merged_config},
1327+ indent=4, default_flow_style=False))
1328+ return {'storage': merged_config}
1329+
1330+
1331 # vi: ts=4 expandtab syntax=python
1332diff --git a/debian/control b/debian/control
1333index 305bbd7..c2de623 100644
1334--- a/debian/control
1335+++ b/debian/control
1336@@ -36,6 +36,7 @@ Depends: bcache-tools,
1337 lvm2,
1338 mdadm,
1339 parted,
1340+ probert,
1341 python3-curtin (= ${binary:Version}),
1342 udev,
1343 xfsprogs,
1344diff --git a/examples/tests/vmtest_defaults.yaml b/examples/tests/vmtest_defaults.yaml
1345index b1512a8..797fe6c 100644
1346--- a/examples/tests/vmtest_defaults.yaml
1347+++ b/examples/tests/vmtest_defaults.yaml
1348@@ -19,6 +19,39 @@ _persist_journal:
1349 }
1350 exit 0
1351
1352+# this runs curtin block-discover and stores the result
1353+# in the target system root dir
1354+_block_discover:
1355+ - &block_discover |
1356+ j='import sys\ntry:\n import jsonschema\nexcept ImportError:\n sys.exit(1)'
1357+ has_jschema() {
1358+ /bin/echo -e $j | python2.7
1359+ py2_rc=$?
1360+ /bin/echo -e $j | python3
1361+ py3_rc=$?
1362+ if [ $py2_rc = "0" -o $py3_rc = "0" ]; then
1363+ return 0
1364+ fi
1365+ return 1
1366+ }
1367+ # if ubuntu/debian
1368+ if [ -e "$TARGET_MOUNT_POINT/usr/bin/apt-get" ]; then
1369+ # xenial and lower don't have jsonschema
1370+ if has_jschema; then
1371+ outfile="${TARGET_MOUNT_POINT}/root/curtin-block-discover.json"
1372+ echo "discovering block devices"
1373+ curtin -vv block-discover > $outfile
1374+ which curtin > $TARGET_MOUNT_POINT/root/which-curtin
1375+ cdir=$(realpath -m "$(dirname `which curtin`)/../")
1376+ echo $cdir >> $TARGET_MOUNT_POINT/root/which-curtin
1377+ cp -a $cdir $TARGET_MOUNT_POINT/root/curtin
1378+ curtin in-target -- apt-get install python3-pyudev;
1379+ fi
1380+ fi
1381+ exit 0
1382+
1383+
1384 late_commands:
1385 01_vmtest_pollinate: ['curtin', 'in-target', '--', 'sh', '-c', *pvmtest]
1386 02_persist_journal: ['curtin', 'in-target', '--', 'sh', '-c', *persist_journal]
1387+ 03_block_disc: ['sh', '-c', *block_discover]
1388diff --git a/pylintrc b/pylintrc
1389index d027f48..167cff0 100644
1390--- a/pylintrc
1391+++ b/pylintrc
1392@@ -7,4 +7,16 @@ jobs=0
1393 # List of members which are set dynamically and missed by pylint inference
1394 # system, and so shouldn't trigger E1101 when accessed. Python regular
1395 # expressions are accepted.
1396-generated-members=DISTROS.*
1397+generated-members=DISTROS.*,parse_*,*_data
1398+
1399+# List of module names for which member attributes should not be checked
1400+# (useful for modules/projects where namespaces are manipulated during runtime
1401+# and thus existing member attributes cannot be deduced by static analysis. It
1402+# supports qualified module names, as well as Unix pattern matching.
1403+ignored-modules=probert
1404+
1405+# List of class names for which member attributes should not be checked (useful
1406+# for classes with dynamically set attributes). This supports the use of
1407+# qualified names.
1408+# argparse.Namespace from https://github.com/PyCQA/pylint/issues/2413
1409+ignored-classes=ProbertParser,BcacheParser,BlockdevParser,LvmParser,RaidParser,MountParser,ZfsParser
1410diff --git a/tests/data/live-iso.json b/tests/data/live-iso.json
1411new file mode 100644
1412index 0000000..d0e9afe
1413--- /dev/null
1414+++ b/tests/data/live-iso.json
1415@@ -0,0 +1,811 @@
1416+{
1417+ "network": {
1418+ "links": [
1419+ {
1420+ "addresses": [
1421+ {
1422+ "address": "10.0.2.15/24",
1423+ "family": 2,
1424+ "scope": "global",
1425+ "source": "dhcp"
1426+ },
1427+ {
1428+ "address": "fec0::5054:ff:fe12:3456/64",
1429+ "family": 10,
1430+ "scope": "site",
1431+ "source": "dhcp"
1432+ },
1433+ {
1434+ "address": "fe80::5054:ff:fe12:3456/64",
1435+ "family": 10,
1436+ "scope": "link",
1437+ "source": "static"
1438+ }
1439+ ],
1440+ "bond": {
1441+ "is_master": false,
1442+ "is_slave": false,
1443+ "lacp_rate": null,
1444+ "master": null,
1445+ "mode": null,
1446+ "slaves": [],
1447+ "xmit_hash_policy": null
1448+ },
1449+ "bridge": {
1450+ "interfaces": [],
1451+ "is_bridge": false,
1452+ "is_port": false,
1453+ "options": {}
1454+ },
1455+ "netlink_data": {
1456+ "arptype": 1,
1457+ "family": 0,
1458+ "flags": 69699,
1459+ "ifindex": 2,
1460+ "is_vlan": false,
1461+ "name": "ens3"
1462+ },
1463+ "type": "eth",
1464+ "udev_data": {
1465+ "DEVPATH": "/devices/pci0000:00/0000:00:03.0/net/ens3",
1466+ "ID_BUS": "pci",
1467+ "ID_MM_CANDIDATE": "1",
1468+ "ID_MODEL_FROM_DATABASE": "82540EM Gigabit Ethernet Controller (QEMU Virtual Machine)",
1469+ "ID_MODEL_ID": "0x100e",
1470+ "ID_NET_NAME_MAC": "enx525400123456",
1471+ "ID_NET_NAME_PATH": "enp0s3",
1472+ "ID_NET_NAME_SLOT": "ens3",
1473+ "ID_NET_NAMING_SCHEME": "v240",
1474+ "ID_PATH": "pci-0000:00:03.0",
1475+ "ID_PATH_TAG": "pci-0000_00_03_0",
1476+ "ID_PCI_CLASS_FROM_DATABASE": "Network controller",
1477+ "ID_PCI_SUBCLASS_FROM_DATABASE": "Ethernet controller",
1478+ "ID_VENDOR_FROM_DATABASE": "Intel Corporation",
1479+ "ID_VENDOR_ID": "0x8086",
1480+ "IFINDEX": "2",
1481+ "INTERFACE": "ens3",
1482+ "SUBSYSTEM": "net",
1483+ "SYSTEMD_ALIAS": "/sys/subsystem/net/devices/ens3",
1484+ "TAGS": ":systemd:",
1485+ "USEC_INITIALIZED": "82651806",
1486+ "attrs": {
1487+ "addr_assign_type": "0",
1488+ "addr_len": "6",
1489+ "address": "52:54:00:12:34:56",
1490+ "broadcast": "ff:ff:ff:ff:ff:ff",
1491+ "carrier": "1",
1492+ "carrier_changes": "2",
1493+ "carrier_down_count": "1",
1494+ "carrier_up_count": "1",
1495+ "dev_id": "0x0",
1496+ "dev_port": "0",
1497+ "device": null,
1498+ "dormant": "0",
1499+ "duplex": "full",
1500+ "flags": "0x1003",
1501+ "gro_flush_timeout": "0",
1502+ "ifalias": "",
1503+ "ifindex": "2",
1504+ "iflink": "2",
1505+ "link_mode": "0",
1506+ "mtu": "1500",
1507+ "name_assign_type": "4",
1508+ "netdev_group": "0",
1509+ "operstate": "up",
1510+ "phys_port_id": null,
1511+ "phys_port_name": null,
1512+ "phys_switch_id": null,
1513+ "proto_down": "0",
1514+ "speed": "1000",
1515+ "subsystem": "net",
1516+ "tx_queue_len": "1000",
1517+ "type": "1",
1518+ "uevent": "INTERFACE=ens3\nIFINDEX=2"
1519+ }
1520+ }
1521+ },
1522+ {
1523+ "addresses": [
1524+ {
1525+ "address": "127.0.0.1/8",
1526+ "family": 2,
1527+ "scope": "host",
1528+ "source": "static"
1529+ },
1530+ {
1531+ "address": "::1/128",
1532+ "family": 10,
1533+ "scope": "host",
1534+ "source": "static"
1535+ }
1536+ ],
1537+ "bond": {
1538+ "is_master": false,
1539+ "is_slave": false,
1540+ "lacp_rate": null,
1541+ "master": null,
1542+ "mode": null,
1543+ "slaves": [],
1544+ "xmit_hash_policy": null
1545+ },
1546+ "bridge": {
1547+ "interfaces": [],
1548+ "is_bridge": false,
1549+ "is_port": false,
1550+ "options": {}
1551+ },
1552+ "netlink_data": {
1553+ "arptype": 772,
1554+ "family": 0,
1555+ "flags": 65609,
1556+ "ifindex": 1,
1557+ "is_vlan": false,
1558+ "name": "lo"
1559+ },
1560+ "type": "lo",
1561+ "udev_data": {
1562+ "DEVPATH": "/devices/virtual/net/lo",
1563+ "ID_MM_CANDIDATE": "1",
1564+ "IFINDEX": "1",
1565+ "INTERFACE": "lo",
1566+ "SUBSYSTEM": "net",
1567+ "USEC_INITIALIZED": "89206115",
1568+ "attrs": {
1569+ "addr_assign_type": "0",
1570+ "addr_len": "6",
1571+ "address": "00:00:00:00:00:00",
1572+ "broadcast": "00:00:00:00:00:00",
1573+ "carrier": "1",
1574+ "carrier_changes": "0",
1575+ "carrier_down_count": "0",
1576+ "carrier_up_count": "0",
1577+ "dev_id": "0x0",
1578+ "dev_port": "0",
1579+ "dormant": "0",
1580+ "duplex": null,
1581+ "flags": "0x9",
1582+ "gro_flush_timeout": "0",
1583+ "ifalias": "",
1584+ "ifindex": "1",
1585+ "iflink": "1",
1586+ "link_mode": "0",
1587+ "mtu": "65536",
1588+ "name_assign_type": null,
1589+ "netdev_group": "0",
1590+ "operstate": "unknown",
1591+ "phys_port_id": null,
1592+ "phys_port_name": null,
1593+ "phys_switch_id": null,
1594+ "proto_down": "0",
1595+ "speed": null,
1596+ "subsystem": "net",
1597+ "tx_queue_len": "1000",
1598+ "type": "772",
1599+ "uevent": "INTERFACE=lo\nIFINDEX=1"
1600+ }
1601+ }
1602+ }
1603+ ],
1604+ "routes": [
1605+ {
1606+ "dst": "default",
1607+ "family": 2,
1608+ "ifindex": 2,
1609+ "table": 254,
1610+ "type": 1
1611+ },
1612+ {
1613+ "dst": "10.0.2.0/24",
1614+ "family": 2,
1615+ "ifindex": 2,
1616+ "table": 254,
1617+ "type": 1
1618+ },
1619+ {
1620+ "dst": "10.0.2.2",
1621+ "family": 2,
1622+ "ifindex": 2,
1623+ "table": 254,
1624+ "type": 1
1625+ },
1626+ {
1627+ "dst": "10.0.2.0",
1628+ "family": 2,
1629+ "ifindex": 2,
1630+ "table": 255,
1631+ "type": 3
1632+ },
1633+ {
1634+ "dst": "10.0.2.15",
1635+ "family": 2,
1636+ "ifindex": 2,
1637+ "table": 255,
1638+ "type": 2
1639+ },
1640+ {
1641+ "dst": "10.0.2.255",
1642+ "family": 2,
1643+ "ifindex": 2,
1644+ "table": 255,
1645+ "type": 3
1646+ },
1647+ {
1648+ "dst": "127.0.0.0",
1649+ "family": 2,
1650+ "ifindex": 1,
1651+ "table": 255,
1652+ "type": 3
1653+ },
1654+ {
1655+ "dst": "127.0.0.0/8",
1656+ "family": 2,
1657+ "ifindex": 1,
1658+ "table": 255,
1659+ "type": 2
1660+ },
1661+ {
1662+ "dst": "127.0.0.1",
1663+ "family": 2,
1664+ "ifindex": 1,
1665+ "table": 255,
1666+ "type": 2
1667+ },
1668+ {
1669+ "dst": "127.255.255.255",
1670+ "family": 2,
1671+ "ifindex": 1,
1672+ "table": 255,
1673+ "type": 3
1674+ },
1675+ {
1676+ "dst": "::1",
1677+ "family": 10,
1678+ "ifindex": 1,
1679+ "table": 254,
1680+ "type": 1
1681+ },
1682+ {
1683+ "dst": "fe80::/64",
1684+ "family": 10,
1685+ "ifindex": 2,
1686+ "table": 254,
1687+ "type": 1
1688+ },
1689+ {
1690+ "dst": "fec0::/64",
1691+ "family": 10,
1692+ "ifindex": 2,
1693+ "table": 254,
1694+ "type": 1
1695+ },
1696+ {
1697+ "dst": "default",
1698+ "family": 10,
1699+ "ifindex": 2,
1700+ "table": 254,
1701+ "type": 1
1702+ },
1703+ {
1704+ "dst": "::1",
1705+ "family": 10,
1706+ "ifindex": 1,
1707+ "table": 255,
1708+ "type": 2
1709+ },
1710+ {
1711+ "dst": "fe80::5054:ff:fe12:3456",
1712+ "family": 10,
1713+ "ifindex": 2,
1714+ "table": 255,
1715+ "type": 2
1716+ },
1717+ {
1718+ "dst": "fec0::5054:ff:fe12:3456",
1719+ "family": 10,
1720+ "ifindex": 2,
1721+ "table": 255,
1722+ "type": 2
1723+ },
1724+ {
1725+ "dst": "ff00::/8",
1726+ "family": 10,
1727+ "ifindex": 2,
1728+ "table": 255,
1729+ "type": 1
1730+ }
1731+ ]
1732+ },
1733+ "storage": {
1734+ "bcache": {
1735+ "backing": {},
1736+ "caching": {}
1737+ },
1738+ "blockdev": {
1739+ "/dev/fd0": {
1740+ "DEVNAME": "/dev/fd0",
1741+ "DEVPATH": "/devices/platform/floppy.0/block/fd0",
1742+ "DEVTYPE": "disk",
1743+ "MAJOR": "2",
1744+ "MINOR": "0",
1745+ "SUBSYSTEM": "block",
1746+ "TAGS": ":systemd:",
1747+ "USEC_INITIALIZED": "82216378",
1748+ "attrs": {
1749+ "alignment_offset": "0",
1750+ "bdi": null,
1751+ "capability": "11",
1752+ "dev": "2:0",
1753+ "device": null,
1754+ "discard_alignment": "0",
1755+ "events": "",
1756+ "events_async": "",
1757+ "events_poll_msecs": "-1",
1758+ "ext_range": "1",
1759+ "hidden": "0",
1760+ "inflight": " 0 0",
1761+ "range": "1",
1762+ "removable": "1",
1763+ "ro": "0",
1764+ "size": "4096",
1765+ "stat": " 1 0 8 68 0 0 0 0 0 8 68 0 0 0 0",
1766+ "subsystem": "block",
1767+ "uevent": "MAJOR=2\nMINOR=0\nDEVNAME=fd0\nDEVTYPE=disk"
1768+ }
1769+ },
1770+ "/dev/sda": {
1771+ "DEVLINKS": "/dev/disk/by-id/scsi-0ATA_QEMU_HARDDISK_QM00001 /dev/disk/by-id/ata-QEMU_HARDDISK_QM00001 /dev/disk/by-id/scsi-1ATA_QEMU_HARDDISK_QM00001 /dev/disk/by-id/scsi-SATA_QEMU_HARDDISK_QM00001 /dev/disk/by-path/pci-0000:00:01.1-ata-1",
1772+ "DEVNAME": "/dev/sda",
1773+ "DEVPATH": "/devices/pci0000:00/0000:00:01.1/ata1/host0/target0:0:0/0:0:0:0/block/sda",
1774+ "DEVTYPE": "disk",
1775+ "ID_ATA": "1",
1776+ "ID_BUS": "ata",
1777+ "ID_MODEL": "QEMU_HARDDISK",
1778+ "ID_MODEL_ENC": "QEMU\\x20HARDDISK\\x20\\x20\\x20",
1779+ "ID_PATH": "pci-0000:00:01.1-ata-1",
1780+ "ID_PATH_TAG": "pci-0000_00_01_1-ata-1",
1781+ "ID_REVISION": "2.5+",
1782+ "ID_SCSI": "1",
1783+ "ID_SCSI_DI": "1",
1784+ "ID_SCSI_SN": "1",
1785+ "ID_SERIAL": "QEMU_HARDDISK_QM00001",
1786+ "ID_SERIAL_SHORT": "QM00001",
1787+ "ID_TYPE": "disk",
1788+ "ID_VENDOR": "ATA",
1789+ "ID_VENDOR_ENC": "ATA\\x20\\x20\\x20\\x20\\x20",
1790+ "MAJOR": "8",
1791+ "MINOR": "0",
1792+ "MPATH_SBIN_PATH": "/sbin",
1793+ "SCSI_IDENT_LUN_ATA": "QEMU_HARDDISK_QM00001",
1794+ "SCSI_IDENT_LUN_T10": "ATA_QEMU_HARDDISK_QM00001",
1795+ "SCSI_IDENT_LUN_VENDOR": "QM00001",
1796+ "SCSI_IDENT_SERIAL": "QM00001",
1797+ "SCSI_MODEL": "QEMU_HARDDISK",
1798+ "SCSI_MODEL_ENC": "QEMU\\x20HARDDISK\\x20\\x20\\x20",
1799+ "SCSI_REVISION": "2.5+",
1800+ "SCSI_TPGS": "0",
1801+ "SCSI_TYPE": "disk",
1802+ "SCSI_VENDOR": "ATA",
1803+ "SCSI_VENDOR_ENC": "ATA\\x20\\x20\\x20\\x20\\x20",
1804+ "SUBSYSTEM": "block",
1805+ "TAGS": ":systemd:",
1806+ "USEC_INITIALIZED": "82301144",
1807+ "attrs": {
1808+ "alignment_offset": "0",
1809+ "bdi": null,
1810+ "capability": "50",
1811+ "dev": "8:0",
1812+ "device": null,
1813+ "discard_alignment": "0",
1814+ "events": "",
1815+ "events_async": "",
1816+ "events_poll_msecs": "-1",
1817+ "ext_range": "256",
1818+ "hidden": "0",
1819+ "inflight": " 0 0",
1820+ "range": "16",
1821+ "removable": "0",
1822+ "ro": "0",
1823+ "size": "10737418240",
1824+ "stat": " 411 0 16968 119 0 0 0 0 0 264 0 0 0 0 0",
1825+ "subsystem": "block",
1826+ "uevent": "MAJOR=8\nMINOR=0\nDEVNAME=sda\nDEVTYPE=disk"
1827+ }
1828+ },
1829+ "/dev/sr0": {
1830+ "DEVLINKS": "/dev/cdrom /dev/disk/by-uuid/2019-05-29-11-26-40-00 /dev/dvd /dev/disk/by-id/ata-QEMU_DVD-ROM_QM00003 /dev/disk/by-path/pci-0000:00:01.1-ata-2 /dev/disk/by-id/scsi-0QEMU_QEMU_DVD-ROM_QM00003 /dev/disk/by-label/Ubuntu\\x20custom\\x20amd64 /dev/disk/by-id/scsi-1ATA_QEMU_DVD-ROM_QM00003",
1831+ "DEVNAME": "/dev/sr0",
1832+ "DEVPATH": "/devices/pci0000:00/0000:00:01.1/ata2/host1/target1:0:0/1:0:0:0/block/sr0",
1833+ "DEVTYPE": "disk",
1834+ "ID_ATA": "1",
1835+ "ID_BUS": "ata",
1836+ "ID_CDROM": "1",
1837+ "ID_CDROM_DVD": "1",
1838+ "ID_CDROM_MEDIA": "1",
1839+ "ID_CDROM_MEDIA_DVD": "1",
1840+ "ID_CDROM_MEDIA_SESSION_COUNT": "1",
1841+ "ID_CDROM_MEDIA_STATE": "complete",
1842+ "ID_CDROM_MEDIA_TRACK_COUNT": "1",
1843+ "ID_CDROM_MEDIA_TRACK_COUNT_DATA": "1",
1844+ "ID_CDROM_MRW": "1",
1845+ "ID_CDROM_MRW_W": "1",
1846+ "ID_FOR_SEAT": "block-pci-0000_00_01_1-ata-2",
1847+ "ID_FS_BOOT_SYSTEM_ID": "EL\\x20TORITO\\x20SPECIFICATION",
1848+ "ID_FS_LABEL": "Ubuntu_custom_amd64",
1849+ "ID_FS_LABEL_ENC": "Ubuntu\\x20custom\\x20amd64",
1850+ "ID_FS_TYPE": "iso9660",
1851+ "ID_FS_USAGE": "filesystem",
1852+ "ID_FS_UUID": "2019-05-29-11-26-40-00",
1853+ "ID_FS_UUID_ENC": "2019-05-29-11-26-40-00",
1854+ "ID_FS_VERSION": "Joliet Extension",
1855+ "ID_MODEL": "QEMU_DVD-ROM",
1856+ "ID_MODEL_ENC": "QEMU\\x20DVD-ROM\\x20\\x20\\x20\\x20",
1857+ "ID_PART_TABLE_TYPE": "dos",
1858+ "ID_PART_TABLE_UUID": "43306950",
1859+ "ID_PATH": "pci-0000:00:01.1-ata-2",
1860+ "ID_PATH_TAG": "pci-0000_00_01_1-ata-2",
1861+ "ID_REVISION": "2.5+",
1862+ "ID_SCSI": "1",
1863+ "ID_SCSI_DI": "1",
1864+ "ID_SERIAL": "QEMU_DVD-ROM_QM00003",
1865+ "ID_TYPE": "cd/dvd",
1866+ "ID_VENDOR": "QEMU",
1867+ "ID_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20",
1868+ "MAJOR": "11",
1869+ "MINOR": "0",
1870+ "SCSI_IDENT_LUN_ATA": "QEMU_DVD-ROM_QM00003",
1871+ "SCSI_IDENT_LUN_T10": "ATA_QEMU_DVD-ROM_QM00003",
1872+ "SCSI_IDENT_LUN_VENDOR": "QM00003",
1873+ "SCSI_MODEL": "QEMU_DVD-ROM",
1874+ "SCSI_MODEL_ENC": "QEMU\\x20DVD-ROM\\x20\\x20\\x20\\x20",
1875+ "SCSI_REVISION": "2.5+",
1876+ "SCSI_TPGS": "0",
1877+ "SCSI_TYPE": "cd/dvd",
1878+ "SCSI_VENDOR": "QEMU",
1879+ "SCSI_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20",
1880+ "SUBSYSTEM": "block",
1881+ "SYSTEMD_MOUNT_DEVICE_BOUND": "1",
1882+ "TAGS": ":seat:systemd:uaccess:",
1883+ "USEC_INITIALIZED": "82293809",
1884+ "attrs": {
1885+ "alignment_offset": "0",
1886+ "bdi": null,
1887+ "capability": "119",
1888+ "dev": "11:0",
1889+ "device": null,
1890+ "discard_alignment": "0",
1891+ "events": "media_change eject_request",
1892+ "events_async": "",
1893+ "events_poll_msecs": "-1",
1894+ "ext_range": "1",
1895+ "hidden": "0",
1896+ "inflight": " 0 0",
1897+ "range": "1",
1898+ "removable": "1",
1899+ "ro": "0",
1900+ "size": "3141533696",
1901+ "stat": " 3269 18 433168 66172 0 0 0 0 0 6440 63912 0 0 0 0",
1902+ "subsystem": "block",
1903+ "uevent": "MAJOR=11\nMINOR=0\nDEVNAME=sr0\nDEVTYPE=disk"
1904+ },
1905+ "partitiontable": {
1906+ "device": "/dev/sr0",
1907+ "id": "0x43306950",
1908+ "label": "dos",
1909+ "partitions": [
1910+ {
1911+ "bootable": true,
1912+ "node": "/dev/sr0p1",
1913+ "size": 1533952,
1914+ "start": 0,
1915+ "type": "0"
1916+ },
1917+ {
1918+ "node": "/dev/sr0p2",
1919+ "size": 7488,
1920+ "start": 996,
1921+ "type": "ef"
1922+ }
1923+ ],
1924+ "unit": "sectors"
1925+ }
1926+ }
1927+ },
1928+ "dmcrypt": {},
1929+ "filesystem": {
1930+ "/dev/sr0": {
1931+ "BOOT_SYSTEM_ID": "EL\\x20TORITO\\x20SPECIFICATION",
1932+ "LABEL": "Ubuntu_custom_amd64",
1933+ "LABEL_ENC": "Ubuntu\\x20custom\\x20amd64",
1934+ "TYPE": "iso9660",
1935+ "USAGE": "filesystem",
1936+ "UUID": "2019-05-29-11-26-40-00",
1937+ "UUID_ENC": "2019-05-29-11-26-40-00",
1938+ "VERSION": "Joliet Extension"
1939+ }
1940+ },
1941+ "lvm": {},
1942+ "mount": [
1943+ {
1944+ "children": [
1945+ {
1946+ "children": [
1947+ {
1948+ "fstype": "securityfs",
1949+ "options": "rw,nosuid,nodev,noexec,relatime",
1950+ "source": "securityfs",
1951+ "target": "/sys/kernel/security"
1952+ },
1953+ {
1954+ "children": [
1955+ {
1956+ "fstype": "cgroup2",
1957+ "options": "rw,nosuid,nodev,noexec,relatime,nsdelegate",
1958+ "source": "cgroup2",
1959+ "target": "/sys/fs/cgroup/unified"
1960+ },
1961+ {
1962+ "fstype": "cgroup",
1963+ "options": "rw,nosuid,nodev,noexec,relatime,xattr,name=systemd",
1964+ "source": "cgroup",
1965+ "target": "/sys/fs/cgroup/systemd"
1966+ },
1967+ {
1968+ "fstype": "cgroup",
1969+ "options": "rw,nosuid,nodev,noexec,relatime,rdma",
1970+ "source": "cgroup",
1971+ "target": "/sys/fs/cgroup/rdma"
1972+ },
1973+ {
1974+ "fstype": "cgroup",
1975+ "options": "rw,nosuid,nodev,noexec,relatime,hugetlb",
1976+ "source": "cgroup",
1977+ "target": "/sys/fs/cgroup/hugetlb"
1978+ },
1979+ {
1980+ "fstype": "cgroup",
1981+ "options": "rw,nosuid,nodev,noexec,relatime,pids",
1982+ "source": "cgroup",
1983+ "target": "/sys/fs/cgroup/pids"
1984+ },
1985+ {
1986+ "fstype": "cgroup",
1987+ "options": "rw,nosuid,nodev,noexec,relatime,freezer",
1988+ "source": "cgroup",
1989+ "target": "/sys/fs/cgroup/freezer"
1990+ },
1991+ {
1992+ "fstype": "cgroup",
1993+ "options": "rw,nosuid,nodev,noexec,relatime,memory",
1994+ "source": "cgroup",
1995+ "target": "/sys/fs/cgroup/memory"
1996+ },
1997+ {
1998+ "fstype": "cgroup",
1999+ "options": "rw,nosuid,nodev,noexec,relatime,cpu,cpuacct",
2000+ "source": "cgroup",
2001+ "target": "/sys/fs/cgroup/cpu,cpuacct"
2002+ },
2003+ {
2004+ "fstype": "cgroup",
2005+ "options": "rw,nosuid,nodev,noexec,relatime,cpuset",
2006+ "source": "cgroup",
2007+ "target": "/sys/fs/cgroup/cpuset"
2008+ },
2009+ {
2010+ "fstype": "cgroup",
2011+ "options": "rw,nosuid,nodev,noexec,relatime,blkio",
2012+ "source": "cgroup",
2013+ "target": "/sys/fs/cgroup/blkio"
2014+ },
2015+ {
2016+ "fstype": "cgroup",
2017+ "options": "rw,nosuid,nodev,noexec,relatime,perf_event",
2018+ "source": "cgroup",
2019+ "target": "/sys/fs/cgroup/perf_event"
2020+ },
2021+ {
2022+ "fstype": "cgroup",
2023+ "options": "rw,nosuid,nodev,noexec,relatime,devices",
2024+ "source": "cgroup",
2025+ "target": "/sys/fs/cgroup/devices"
2026+ },
2027+ {
2028+ "fstype": "cgroup",
2029+ "options": "rw,nosuid,nodev,noexec,relatime,net_cls,net_prio",
2030+ "source": "cgroup",
2031+ "target": "/sys/fs/cgroup/net_cls,net_prio"
2032+ }
2033+ ],
2034+ "fstype": "tmpfs",
2035+ "options": "ro,nosuid,nodev,noexec,mode=755",
2036+ "source": "tmpfs",
2037+ "target": "/sys/fs/cgroup"
2038+ },
2039+ {
2040+ "fstype": "pstore",
2041+ "options": "rw,nosuid,nodev,noexec,relatime",
2042+ "source": "pstore",
2043+ "target": "/sys/fs/pstore"
2044+ },
2045+ {
2046+ "fstype": "efivarfs",
2047+ "options": "rw,nosuid,nodev,noexec,relatime",
2048+ "source": "efivarfs",
2049+ "target": "/sys/firmware/efi/efivars"
2050+ },
2051+ {
2052+ "fstype": "bpf",
2053+ "options": "rw,nosuid,nodev,noexec,relatime,mode=700",
2054+ "source": "bpf",
2055+ "target": "/sys/fs/bpf"
2056+ },
2057+ {
2058+ "fstype": "debugfs",
2059+ "options": "rw,relatime",
2060+ "source": "debugfs",
2061+ "target": "/sys/kernel/debug"
2062+ },
2063+ {
2064+ "fstype": "fusectl",
2065+ "options": "rw,relatime",
2066+ "source": "fusectl",
2067+ "target": "/sys/fs/fuse/connections"
2068+ },
2069+ {
2070+ "fstype": "configfs",
2071+ "options": "rw,relatime",
2072+ "source": "configfs",
2073+ "target": "/sys/kernel/config"
2074+ }
2075+ ],
2076+ "fstype": "sysfs",
2077+ "options": "rw,nosuid,nodev,noexec,relatime",
2078+ "source": "sysfs",
2079+ "target": "/sys"
2080+ },
2081+ {
2082+ "children": [
2083+ {
2084+ "fstype": "autofs",
2085+ "options": "rw,relatime,fd=44,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=14037",
2086+ "source": "systemd-1",
2087+ "target": "/proc/sys/fs/binfmt_misc"
2088+ }
2089+ ],
2090+ "fstype": "proc",
2091+ "options": "rw,nosuid,nodev,noexec,relatime",
2092+ "source": "proc",
2093+ "target": "/proc"
2094+ },
2095+ {
2096+ "children": [
2097+ {
2098+ "fstype": "devpts",
2099+ "options": "rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000",
2100+ "source": "devpts",
2101+ "target": "/dev/pts"
2102+ },
2103+ {
2104+ "fstype": "tmpfs",
2105+ "options": "rw,nosuid,nodev",
2106+ "source": "tmpfs",
2107+ "target": "/dev/shm"
2108+ },
2109+ {
2110+ "fstype": "mqueue",
2111+ "options": "rw,relatime",
2112+ "source": "mqueue",
2113+ "target": "/dev/mqueue"
2114+ },
2115+ {
2116+ "fstype": "hugetlbfs",
2117+ "options": "rw,relatime,pagesize=2M",
2118+ "source": "hugetlbfs",
2119+ "target": "/dev/hugepages"
2120+ }
2121+ ],
2122+ "fstype": "devtmpfs",
2123+ "options": "rw,nosuid,relatime,size=465256k,nr_inodes=116314,mode=755",
2124+ "source": "udev",
2125+ "target": "/dev"
2126+ },
2127+ {
2128+ "children": [
2129+ {
2130+ "fstype": "tmpfs",
2131+ "options": "rw,nosuid,nodev,noexec,relatime,size=5120k",
2132+ "source": "tmpfs",
2133+ "target": "/run/lock"
2134+ },
2135+ {
2136+ "fstype": "tmpfs",
2137+ "options": "rw,nosuid,nodev,relatime,size=100148k,mode=700,uid=999,gid=999",
2138+ "source": "tmpfs",
2139+ "target": "/run/user/999"
2140+ }
2141+ ],
2142+ "fstype": "tmpfs",
2143+ "options": "rw,nosuid,noexec,relatime,size=100152k,mode=755",
2144+ "source": "tmpfs",
2145+ "target": "/run"
2146+ },
2147+ {
2148+ "fstype": "iso9660",
2149+ "options": "ro,noatime,nojoliet,check=s,map=n,blocksize=2048",
2150+ "source": "/dev/sr0",
2151+ "target": "/cdrom"
2152+ },
2153+ {
2154+ "fstype": "squashfs",
2155+ "options": "ro,noatime",
2156+ "source": "/dev/loop0",
2157+ "target": "/rofs"
2158+ },
2159+ {
2160+ "fstype": "squashfs",
2161+ "options": "ro,relatime",
2162+ "source": "/dev/loop2",
2163+ "target": "/usr/lib/modules"
2164+ },
2165+ {
2166+ "fstype": "tmpfs",
2167+ "options": "rw,nosuid,nodev,relatime",
2168+ "source": "tmpfs",
2169+ "target": "/tmp"
2170+ },
2171+ {
2172+ "fstype": "squashfs",
2173+ "options": "ro,relatime",
2174+ "source": "/dev/loop3",
2175+ "target": "/media/rack.lower"
2176+ },
2177+ {
2178+ "fstype": "squashfs",
2179+ "options": "ro,relatime",
2180+ "source": "/dev/loop4",
2181+ "target": "/media/region.lower"
2182+ },
2183+ {
2184+ "fstype": "squashfs",
2185+ "options": "ro,relatime",
2186+ "source": "/dev/loop0",
2187+ "target": "/media/filesystem"
2188+ },
2189+ {
2190+ "fstype": "overlay",
2191+ "options": "ro,relatime,lowerdir=/media/region.lower:/media/rack.lower:/media/filesystem",
2192+ "source": "overlay",
2193+ "target": "/media/region"
2194+ },
2195+ {
2196+ "fstype": "overlay",
2197+ "options": "ro,relatime,lowerdir=/media/rack.lower:/media/filesystem",
2198+ "source": "overlay",
2199+ "target": "/media/rack"
2200+ },
2201+ {
2202+ "fstype": "squashfs",
2203+ "options": "ro,nodev,relatime",
2204+ "source": "/dev/loop5",
2205+ "target": "/snap/core/6673"
2206+ },
2207+ {
2208+ "fstype": "squashfs",
2209+ "options": "ro,nodev,relatime",
2210+ "source": "/dev/loop6",
2211+ "target": "/snap/subiquity/1012"
2212+ }
2213+ ],
2214+ "fstype": "overlay",
2215+ "options": "rw,relatime,lowerdir=//installer.squashfs://filesystem.squashfs,upperdir=/cow/upper,workdir=/cow/work",
2216+ "source": "/cow",
2217+ "target": "/"
2218+ }
2219+ ],
2220+ "multipath": {},
2221+ "raid": {},
2222+ "zfs": {
2223+ "zpools": {}
2224+ }
2225+ }
2226+}
2227diff --git a/tests/data/probert_storage_diglett.json b/tests/data/probert_storage_diglett.json
2228new file mode 100644
2229index 0000000..17f6e47
2230--- /dev/null
2231+++ b/tests/data/probert_storage_diglett.json
2232@@ -0,0 +1,14624 @@
2233+{
2234+ "storage": {
2235+ "bcache": {
2236+ "backing": {
2237+ "f36394c0-3cc0-4423-8d6f-ffac130f171a": {
2238+ "blockdev": "/dev/sda3",
2239+ "superblock": {
2240+ "cset.uuid": "01da3829-ea92-4600-bd40-7f95974f3087",
2241+ "dev.data.cache_mode": "1 [writeback]",
2242+ "dev.data.cache_state": "2 [dirty]",
2243+ "dev.data.first_sector": "16",
2244+ "dev.label": "(empty)",
2245+ "dev.sectors_per_block": "1",
2246+ "dev.sectors_per_bucket": "1024",
2247+ "dev.uuid": "f36394c0-3cc0-4423-8d6f-ffac130f171a",
2248+ "sb.csum": "B92908820E241EDD [match]",
2249+ "sb.first_sector": "8 [match]",
2250+ "sb.magic": "ok",
2251+ "sb.version": "1 [backing device]"
2252+ }
2253+ }
2254+ },
2255+ "caching": {
2256+ "ff51a56d-eddc-41b3-867d-8744277c5281": {
2257+ "blockdev": "/dev/nvme0n1p1",
2258+ "superblock": {
2259+ "cset.uuid": "01da3829-ea92-4600-bd40-7f95974f3087",
2260+ "dev.cache.cache_sectors": "234372096",
2261+ "dev.cache.discard": "no",
2262+ "dev.cache.first_sector": "1024",
2263+ "dev.cache.ordered": "yes",
2264+ "dev.cache.pos": "0",
2265+ "dev.cache.replacement": "0 [lru]",
2266+ "dev.cache.total_sectors": "234373120",
2267+ "dev.label": "(empty)",
2268+ "dev.sectors_per_block": "1",
2269+ "dev.sectors_per_bucket": "1024",
2270+ "dev.uuid": "ff51a56d-eddc-41b3-867d-8744277c5281",
2271+ "sb.csum": "2F8BB7E8DC53E0B6 [match]",
2272+ "sb.first_sector": "8 [match]",
2273+ "sb.magic": "ok",
2274+ "sb.version": "3 [cache device]"
2275+ }
2276+ }
2277+ }
2278+ },
2279+ "blockdev": {
2280+ "/dev/bcache0": {
2281+ "DEVLINKS": "/dev/bcache/by-uuid/f36394c0-3cc0-4423-8d6f-ffac130f171a /dev/disk/by-uuid/45354276-e0c0-4bf6-9083-f130b89411cc /dev/disk/by-dname/bcache0",
2282+ "DEVNAME": "/dev/bcache0",
2283+ "DEVPATH": "/devices/virtual/block/bcache0",
2284+ "DEVTYPE": "disk",
2285+ "ID_FS_TYPE": "ext4",
2286+ "ID_FS_USAGE": "filesystem",
2287+ "ID_FS_UUID": "45354276-e0c0-4bf6-9083-f130b89411cc",
2288+ "ID_FS_UUID_ENC": "45354276-e0c0-4bf6-9083-f130b89411cc",
2289+ "ID_FS_VERSION": "1.0",
2290+ "MAJOR": "252",
2291+ "MINOR": "0",
2292+ "SUBSYSTEM": "block",
2293+ "TAGS": ":systemd:",
2294+ "USEC_INITIALIZED": "41032154",
2295+ "attrs": {
2296+ "alignment_offset": "0",
2297+ "bcache": null,
2298+ "bdi": null,
2299+ "capability": "10",
2300+ "dev": "252:0",
2301+ "discard_alignment": "0",
2302+ "ext_range": "128",
2303+ "hidden": "0",
2304+ "inflight": " 0 0",
2305+ "range": "128",
2306+ "removable": "0",
2307+ "ro": "0",
2308+ "size": "900202487808",
2309+ "stat": " 7791002 0 236676214 14036404 11259210 0 1602715032 150396400 0 11388848 164434000 259911 0 1820167136 1196",
2310+ "subsystem": "block",
2311+ "uevent": "MAJOR=252\nMINOR=0\nDEVNAME=bcache0\nDEVTYPE=disk"
2312+ }
2313+ },
2314+ "/dev/nbd0": {
2315+ "DEVNAME": "/dev/nbd0",
2316+ "DEVPATH": "/devices/virtual/block/nbd0",
2317+ "DEVTYPE": "disk",
2318+ "MAJOR": "43",
2319+ "MINOR": "0",
2320+ "SUBSYSTEM": "block",
2321+ "SYSTEMD_READY": "0",
2322+ "TAGS": ":systemd:",
2323+ "USEC_INITIALIZED": "3043416610530",
2324+ "attrs": {
2325+ "alignment_offset": "0",
2326+ "bdi": null,
2327+ "capability": "10",
2328+ "dev": "43:0",
2329+ "discard_alignment": "0",
2330+ "ext_range": "32",
2331+ "hidden": "0",
2332+ "inflight": " 0 0",
2333+ "range": "32",
2334+ "removable": "0",
2335+ "ro": "0",
2336+ "size": "0",
2337+ "stat": " 2276 0 74612 507 185 117 2296 59 0 264 0 0 0 0 0",
2338+ "subsystem": "block",
2339+ "uevent": "MAJOR=43\nMINOR=0\nDEVNAME=nbd0\nDEVTYPE=disk"
2340+ }
2341+ },
2342+ "/dev/nbd1": {
2343+ "DEVNAME": "/dev/nbd1",
2344+ "DEVPATH": "/devices/virtual/block/nbd1",
2345+ "DEVTYPE": "disk",
2346+ "MAJOR": "43",
2347+ "MINOR": "32",
2348+ "SUBSYSTEM": "block",
2349+ "SYSTEMD_READY": "0",
2350+ "TAGS": ":systemd:",
2351+ "USEC_INITIALIZED": "3043416608225",
2352+ "attrs": {
2353+ "alignment_offset": "0",
2354+ "bdi": null,
2355+ "capability": "10",
2356+ "dev": "43:32",
2357+ "discard_alignment": "0",
2358+ "ext_range": "32",
2359+ "hidden": "0",
2360+ "inflight": " 0 0",
2361+ "range": "32",
2362+ "removable": "0",
2363+ "ro": "0",
2364+ "size": "0",
2365+ "stat": " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0",
2366+ "subsystem": "block",
2367+ "uevent": "MAJOR=43\nMINOR=32\nDEVNAME=nbd1\nDEVTYPE=disk"
2368+ }
2369+ },
2370+ "/dev/nbd10": {
2371+ "DEVNAME": "/dev/nbd10",
2372+ "DEVPATH": "/devices/virtual/block/nbd10",
2373+ "DEVTYPE": "disk",
2374+ "MAJOR": "43",
2375+ "MINOR": "320",
2376+ "SUBSYSTEM": "block",
2377+ "SYSTEMD_READY": "0",
2378+ "TAGS": ":systemd:",
2379+ "USEC_INITIALIZED": "3043416612159",
2380+ "attrs": {
2381+ "alignment_offset": "0",
2382+ "bdi": null,
2383+ "capability": "10",
2384+ "dev": "43:320",
2385+ "discard_alignment": "0",
2386+ "ext_range": "32",
2387+ "hidden": "0",
2388+ "inflight": " 0 0",
2389+ "range": "32",
2390+ "removable": "0",
2391+ "ro": "0",
2392+ "size": "0",
2393+ "stat": " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0",
2394+ "subsystem": "block",
2395+ "uevent": "MAJOR=43\nMINOR=320\nDEVNAME=nbd10\nDEVTYPE=disk"
2396+ }
2397+ },
2398+ "/dev/nbd11": {
2399+ "DEVNAME": "/dev/nbd11",
2400+ "DEVPATH": "/devices/virtual/block/nbd11",
2401+ "DEVTYPE": "disk",
2402+ "MAJOR": "43",
2403+ "MINOR": "352",
2404+ "SUBSYSTEM": "block",
2405+ "SYSTEMD_READY": "0",
2406+ "TAGS": ":systemd:",
2407+ "USEC_INITIALIZED": "3043416612517",
2408+ "attrs": {
2409+ "alignment_offset": "0",
2410+ "bdi": null,
2411+ "capability": "10",
2412+ "dev": "43:352",
2413+ "discard_alignment": "0",
2414+ "ext_range": "32",
2415+ "hidden": "0",
2416+ "inflight": " 0 0",
2417+ "range": "32",
2418+ "removable": "0",
2419+ "ro": "0",
2420+ "size": "0",
2421+ "stat": " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0",
2422+ "subsystem": "block",
2423+ "uevent": "MAJOR=43\nMINOR=352\nDEVNAME=nbd11\nDEVTYPE=disk"
2424+ }
2425+ },
2426+ "/dev/nbd12": {
2427+ "DEVNAME": "/dev/nbd12",
2428+ "DEVPATH": "/devices/virtual/block/nbd12",
2429+ "DEVTYPE": "disk",
2430+ "MAJOR": "43",
2431+ "MINOR": "384",
2432+ "SUBSYSTEM": "block",
2433+ "SYSTEMD_READY": "0",
2434+ "TAGS": ":systemd:",
2435+ "USEC_INITIALIZED": "3043416610687",
2436+ "attrs": {
2437+ "alignment_offset": "0",
2438+ "bdi": null,
2439+ "capability": "10",
2440+ "dev": "43:384",
2441+ "discard_alignment": "0",
2442+ "ext_range": "32",
2443+ "hidden": "0",
2444+ "inflight": " 0 0",
2445+ "range": "32",
2446+ "removable": "0",
2447+ "ro": "0",
2448+ "size": "0",
2449+ "stat": " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0",
2450+ "subsystem": "block",
2451+ "uevent": "MAJOR=43\nMINOR=384\nDEVNAME=nbd12\nDEVTYPE=disk"
2452+ }
2453+ },
2454+ "/dev/nbd13": {
2455+ "DEVNAME": "/dev/nbd13",
2456+ "DEVPATH": "/devices/virtual/block/nbd13",
2457+ "DEVTYPE": "disk",
2458+ "MAJOR": "43",
2459+ "MINOR": "416",
2460+ "SUBSYSTEM": "block",
2461+ "SYSTEMD_READY": "0",
2462+ "TAGS": ":systemd:",
2463+ "USEC_INITIALIZED": "3043416613964",
2464+ "attrs": {
2465+ "alignment_offset": "0",
2466+ "bdi": null,
2467+ "capability": "10",
2468+ "dev": "43:416",
2469+ "discard_alignment": "0",
2470+ "ext_range": "32",
2471+ "hidden": "0",
2472+ "inflight": " 0 0",
2473+ "range": "32",
2474+ "removable": "0",
2475+ "ro": "0",
2476+ "size": "0",
2477+ "stat": " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0",
2478+ "subsystem": "block",
2479+ "uevent": "MAJOR=43\nMINOR=416\nDEVNAME=nbd13\nDEVTYPE=disk"
2480+ }
2481+ },
2482+ "/dev/nbd14": {
2483+ "DEVNAME": "/dev/nbd14",
2484+ "DEVPATH": "/devices/virtual/block/nbd14",
2485+ "DEVTYPE": "disk",
2486+ "MAJOR": "43",
2487+ "MINOR": "448",
2488+ "SUBSYSTEM": "block",
2489+ "SYSTEMD_READY": "0",
2490+ "TAGS": ":systemd:",
2491+ "USEC_INITIALIZED": "3043416614463",
2492+ "attrs": {
2493+ "alignment_offset": "0",
2494+ "bdi": null,
2495+ "capability": "10",
2496+ "dev": "43:448",
2497+ "discard_alignment": "0",
2498+ "ext_range": "32",
2499+ "hidden": "0",
2500+ "inflight": " 0 0",
2501+ "range": "32",
2502+ "removable": "0",
2503+ "ro": "0",
2504+ "size": "0",
2505+ "stat": " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0",
2506+ "subsystem": "block",
2507+ "uevent": "MAJOR=43\nMINOR=448\nDEVNAME=nbd14\nDEVTYPE=disk"
2508+ }
2509+ },
2510+ "/dev/nbd15": {
2511+ "DEVNAME": "/dev/nbd15",
2512+ "DEVPATH": "/devices/virtual/block/nbd15",
2513+ "DEVTYPE": "disk",
2514+ "MAJOR": "43",
2515+ "MINOR": "480",
2516+ "SUBSYSTEM": "block",
2517+ "SYSTEMD_READY": "0",
2518+ "TAGS": ":systemd:",
2519+ "USEC_INITIALIZED": "3043416615067",
2520+ "attrs": {
2521+ "alignment_offset": "0",
2522+ "bdi": null,
2523+ "capability": "10",
2524+ "dev": "43:480",
2525+ "discard_alignment": "0",
2526+ "ext_range": "32",
2527+ "hidden": "0",
2528+ "inflight": " 0 0",
2529+ "range": "32",
2530+ "removable": "0",
2531+ "ro": "0",
2532+ "size": "0",
2533+ "stat": " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0",
2534+ "subsystem": "block",
2535+ "uevent": "MAJOR=43\nMINOR=480\nDEVNAME=nbd15\nDEVTYPE=disk"
2536+ }
2537+ },
2538+ "/dev/nbd2": {
2539+ "DEVNAME": "/dev/nbd2",
2540+ "DEVPATH": "/devices/virtual/block/nbd2",
2541+ "DEVTYPE": "disk",
2542+ "MAJOR": "43",
2543+ "MINOR": "64",
2544+ "SUBSYSTEM": "block",
2545+ "SYSTEMD_READY": "0",
2546+ "TAGS": ":systemd:",
2547+ "USEC_INITIALIZED": "3043416607048",
2548+ "attrs": {
2549+ "alignment_offset": "0",
2550+ "bdi": null,
2551+ "capability": "10",
2552+ "dev": "43:64",
2553+ "discard_alignment": "0",
2554+ "ext_range": "32",
2555+ "hidden": "0",
2556+ "inflight": " 0 0",
2557+ "range": "32",
2558+ "removable": "0",
2559+ "ro": "0",
2560+ "size": "0",
2561+ "stat": " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0",
2562+ "subsystem": "block",
2563+ "uevent": "MAJOR=43\nMINOR=64\nDEVNAME=nbd2\nDEVTYPE=disk"
2564+ }
2565+ },
2566+ "/dev/nbd3": {
2567+ "DEVNAME": "/dev/nbd3",
2568+ "DEVPATH": "/devices/virtual/block/nbd3",
2569+ "DEVTYPE": "disk",
2570+ "MAJOR": "43",
2571+ "MINOR": "96",
2572+ "SUBSYSTEM": "block",
2573+ "SYSTEMD_READY": "0",
2574+ "TAGS": ":systemd:",
2575+ "USEC_INITIALIZED": "3043416607356",
2576+ "attrs": {
2577+ "alignment_offset": "0",
2578+ "bdi": null,
2579+ "capability": "10",
2580+ "dev": "43:96",
2581+ "discard_alignment": "0",
2582+ "ext_range": "32",
2583+ "hidden": "0",
2584+ "inflight": " 0 0",
2585+ "range": "32",
2586+ "removable": "0",
2587+ "ro": "0",
2588+ "size": "0",
2589+ "stat": " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0",
2590+ "subsystem": "block",
2591+ "uevent": "MAJOR=43\nMINOR=96\nDEVNAME=nbd3\nDEVTYPE=disk"
2592+ }
2593+ },
2594+ "/dev/nbd4": {
2595+ "DEVNAME": "/dev/nbd4",
2596+ "DEVPATH": "/devices/virtual/block/nbd4",
2597+ "DEVTYPE": "disk",
2598+ "MAJOR": "43",
2599+ "MINOR": "128",
2600+ "SUBSYSTEM": "block",
2601+ "SYSTEMD_READY": "0",
2602+ "TAGS": ":systemd:",
2603+ "USEC_INITIALIZED": "3043416611304",
2604+ "attrs": {
2605+ "alignment_offset": "0",
2606+ "bdi": null,
2607+ "capability": "10",
2608+ "dev": "43:128",
2609+ "discard_alignment": "0",
2610+ "ext_range": "32",
2611+ "hidden": "0",
2612+ "inflight": " 0 0",
2613+ "range": "32",
2614+ "removable": "0",
2615+ "ro": "0",
2616+ "size": "0",
2617+ "stat": " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0",
2618+ "subsystem": "block",
2619+ "uevent": "MAJOR=43\nMINOR=128\nDEVNAME=nbd4\nDEVTYPE=disk"
2620+ }
2621+ },
2622+ "/dev/nbd5": {
2623+ "DEVNAME": "/dev/nbd5",
2624+ "DEVPATH": "/devices/virtual/block/nbd5",
2625+ "DEVTYPE": "disk",
2626+ "MAJOR": "43",
2627+ "MINOR": "160",
2628+ "SUBSYSTEM": "block",
2629+ "SYSTEMD_READY": "0",
2630+ "TAGS": ":systemd:",
2631+ "USEC_INITIALIZED": "3043416607636",
2632+ "attrs": {
2633+ "alignment_offset": "0",
2634+ "bdi": null,
2635+ "capability": "10",
2636+ "dev": "43:160",
2637+ "discard_alignment": "0",
2638+ "ext_range": "32",
2639+ "hidden": "0",
2640+ "inflight": " 0 0",
2641+ "range": "32",
2642+ "removable": "0",
2643+ "ro": "0",
2644+ "size": "0",
2645+ "stat": " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0",
2646+ "subsystem": "block",
2647+ "uevent": "MAJOR=43\nMINOR=160\nDEVNAME=nbd5\nDEVTYPE=disk"
2648+ }
2649+ },
2650+ "/dev/nbd6": {
2651+ "DEVNAME": "/dev/nbd6",
2652+ "DEVPATH": "/devices/virtual/block/nbd6",
2653+ "DEVTYPE": "disk",
2654+ "MAJOR": "43",
2655+ "MINOR": "192",
2656+ "SUBSYSTEM": "block",
2657+ "SYSTEMD_READY": "0",
2658+ "TAGS": ":systemd:",
2659+ "USEC_INITIALIZED": "3043416608369",
2660+ "attrs": {
2661+ "alignment_offset": "0",
2662+ "bdi": null,
2663+ "capability": "10",
2664+ "dev": "43:192",
2665+ "discard_alignment": "0",
2666+ "ext_range": "32",
2667+ "hidden": "0",
2668+ "inflight": " 0 0",
2669+ "range": "32",
2670+ "removable": "0",
2671+ "ro": "0",
2672+ "size": "0",
2673+ "stat": " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0",
2674+ "subsystem": "block",
2675+ "uevent": "MAJOR=43\nMINOR=192\nDEVNAME=nbd6\nDEVTYPE=disk"
2676+ }
2677+ },
2678+ "/dev/nbd7": {
2679+ "DEVNAME": "/dev/nbd7",
2680+ "DEVPATH": "/devices/virtual/block/nbd7",
2681+ "DEVTYPE": "disk",
2682+ "MAJOR": "43",
2683+ "MINOR": "224",
2684+ "SUBSYSTEM": "block",
2685+ "SYSTEMD_READY": "0",
2686+ "TAGS": ":systemd:",
2687+ "USEC_INITIALIZED": "3043416608728",
2688+ "attrs": {
2689+ "alignment_offset": "0",
2690+ "bdi": null,
2691+ "capability": "10",
2692+ "dev": "43:224",
2693+ "discard_alignment": "0",
2694+ "ext_range": "32",
2695+ "hidden": "0",
2696+ "inflight": " 0 0",
2697+ "range": "32",
2698+ "removable": "0",
2699+ "ro": "0",
2700+ "size": "0",
2701+ "stat": " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0",
2702+ "subsystem": "block",
2703+ "uevent": "MAJOR=43\nMINOR=224\nDEVNAME=nbd7\nDEVTYPE=disk"
2704+ }
2705+ },
2706+ "/dev/nbd8": {
2707+ "DEVNAME": "/dev/nbd8",
2708+ "DEVPATH": "/devices/virtual/block/nbd8",
2709+ "DEVTYPE": "disk",
2710+ "MAJOR": "43",
2711+ "MINOR": "256",
2712+ "SUBSYSTEM": "block",
2713+ "SYSTEMD_READY": "0",
2714+ "TAGS": ":systemd:",
2715+ "USEC_INITIALIZED": "3043416610905",
2716+ "attrs": {
2717+ "alignment_offset": "0",
2718+ "bdi": null,
2719+ "capability": "10",
2720+ "dev": "43:256",
2721+ "discard_alignment": "0",
2722+ "ext_range": "32",
2723+ "hidden": "0",
2724+ "inflight": " 0 0",
2725+ "range": "32",
2726+ "removable": "0",
2727+ "ro": "0",
2728+ "size": "0",
2729+ "stat": " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0",
2730+ "subsystem": "block",
2731+ "uevent": "MAJOR=43\nMINOR=256\nDEVNAME=nbd8\nDEVTYPE=disk"
2732+ }
2733+ },
2734+ "/dev/nbd9": {
2735+ "DEVNAME": "/dev/nbd9",
2736+ "DEVPATH": "/devices/virtual/block/nbd9",
2737+ "DEVTYPE": "disk",
2738+ "MAJOR": "43",
2739+ "MINOR": "288",
2740+ "SUBSYSTEM": "block",
2741+ "SYSTEMD_READY": "0",
2742+ "TAGS": ":systemd:",
2743+ "USEC_INITIALIZED": "3043416609253",
2744+ "attrs": {
2745+ "alignment_offset": "0",
2746+ "bdi": null,
2747+ "capability": "10",
2748+ "dev": "43:288",
2749+ "discard_alignment": "0",
2750+ "ext_range": "32",
2751+ "hidden": "0",
2752+ "inflight": " 0 0",
2753+ "range": "32",
2754+ "removable": "0",
2755+ "ro": "0",
2756+ "size": "0",
2757+ "stat": " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0",
2758+ "subsystem": "block",
2759+ "uevent": "MAJOR=43\nMINOR=288\nDEVNAME=nbd9\nDEVTYPE=disk"
2760+ }
2761+ },
2762+ "/dev/nvme0n1": {
2763+ "DEVLINKS": "/dev/disk/by-uuid/13976804636456298589 /dev/disk/by-id/nvme-INTEL_SSDPEDME400G4_CVMD4456000M400AGN /dev/disk/by-label/zfs-lxd /dev/disk/by-path/pci-0000:05:00.0-nvme-1 /dev/disk/by-dname/nvme0n1 /dev/disk/by-id/nvme-nvme.8086-43564d44343435363030304d34303041474e-494e54454c205353445045444d453430304734-00000001",
2764+ "DEVNAME": "/dev/nvme0n1",
2765+ "DEVPATH": "/devices/pci0000:00/0000:00:02.0/0000:05:00.0/nvme/nvme0/nvme0n1",
2766+ "DEVTYPE": "disk",
2767+ "ID_FS_LABEL": "zfs-lxd",
2768+ "ID_FS_LABEL_ENC": "zfs-lxd",
2769+ "ID_FS_TYPE": "zfs_member",
2770+ "ID_FS_USAGE": "filesystem",
2771+ "ID_FS_UUID": "13976804636456298589",
2772+ "ID_FS_UUID_ENC": "13976804636456298589",
2773+ "ID_FS_UUID_SUB": "10416813983586022065",
2774+ "ID_FS_UUID_SUB_ENC": "10416813983586022065",
2775+ "ID_FS_VERSION": "5000",
2776+ "ID_MODEL": "INTEL SSDPEDME400G4",
2777+ "ID_PART_TABLE_TYPE": "gpt",
2778+ "ID_PART_TABLE_UUID": "1d73687c-0668-4680-b827-165c9d1ce0be",
2779+ "ID_PATH": "pci-0000:05:00.0-nvme-1",
2780+ "ID_PATH_TAG": "pci-0000_05_00_0-nvme-1",
2781+ "ID_REVISION": "8DV10151",
2782+ "ID_SERIAL": "INTEL SSDPEDME400G4_CVMD4456000M400AGN",
2783+ "ID_SERIAL_SHORT": "CVMD4456000M400AGN",
2784+ "ID_WWN": "nvme.8086-43564d44343435363030304d34303041474e-494e54454c205353445045444d453430304734-00000001",
2785+ "MAJOR": "259",
2786+ "MINOR": "0",
2787+ "SUBSYSTEM": "block",
2788+ "TAGS": ":systemd:",
2789+ "USEC_INITIALIZED": "6276789",
2790+ "attrs": {
2791+ "alignment_offset": "0",
2792+ "bdi": null,
2793+ "capability": "50",
2794+ "dev": "259:0",
2795+ "device": null,
2796+ "discard_alignment": "0",
2797+ "ext_range": "256",
2798+ "hidden": "0",
2799+ "inflight": " 0 0",
2800+ "nsid": "1",
2801+ "range": "0",
2802+ "removable": "0",
2803+ "ro": "0",
2804+ "size": "400088457216",
2805+ "stat": "50280626 705665 3198431464 39603860 210435613 9919031 38920382373 1179550000 0 83056004 921087080 56367 0 2058576136 67422",
2806+ "subsystem": "block",
2807+ "uevent": "MAJOR=259\nMINOR=0\nDEVNAME=nvme0n1\nDEVTYPE=disk",
2808+ "wwid": "nvme.8086-43564d44343435363030304d34303041474e-494e54454c205353445045444d453430304734-00000001"
2809+ },
2810+ "partitiontable": {
2811+ "device": "/dev/nvme0n1",
2812+ "firstlba": 34,
2813+ "id": "1D73687C-0668-4680-B827-165C9D1CE0BE",
2814+ "label": "gpt",
2815+ "lastlba": 781422734,
2816+ "partitions": [
2817+ {
2818+ "node": "/dev/nvme0n1p1",
2819+ "size": 234373120,
2820+ "start": 2048,
2821+ "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
2822+ "uuid": "2A3296F5-905C-4BD9-835F-E764F564F3F1"
2823+ },
2824+ {
2825+ "name": "Linux filesystem",
2826+ "node": "/dev/nvme0n1p2",
2827+ "size": 419430400,
2828+ "start": 234375168,
2829+ "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
2830+ "uuid": "789835F9-0CA5-451A-AF2D-D642934D83A6"
2831+ },
2832+ {
2833+ "name": "Linux filesystem",
2834+ "node": "/dev/nvme0n1p3",
2835+ "size": 127617167,
2836+ "start": 653805568,
2837+ "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
2838+ "uuid": "B4B2F32D-271D-4CA5-B88D-0AE416347F28"
2839+ }
2840+ ],
2841+ "unit": "sectors"
2842+ }
2843+ },
2844+ "/dev/nvme0n1p1": {
2845+ "DEVLINKS": "/dev/disk/by-path/pci-0000:05:00.0-nvme-1-part1 /dev/disk/by-label/zfs-lxd /dev/disk/by-uuid/ff51a56d-eddc-41b3-867d-8744277c5281 /dev/disk/by-id/nvme-INTEL_SSDPEDME400G4_CVMD4456000M400AGN-part1 /dev/disk/by-partuuid/2a3296f5-905c-4bd9-835f-e764f564f3f1 /dev/disk/by-id/nvme-nvme.8086-43564d44343435363030304d34303041474e-494e54454c205353445045444d453430304734-00000001-part1 /dev/disk/by-dname/nvme0n1-part1",
2846+ "DEVNAME": "/dev/nvme0n1p1",
2847+ "DEVPATH": "/devices/pci0000:00/0000:00:02.0/0000:05:00.0/nvme/nvme0/nvme0n1/nvme0n1p1",
2848+ "DEVTYPE": "partition",
2849+ "ID_FS_LABEL": "zfs-lxd",
2850+ "ID_FS_LABEL_ENC": "zfs-lxd",
2851+ "ID_FS_TYPE": "bcache",
2852+ "ID_FS_USAGE": "other",
2853+ "ID_FS_UUID": "ff51a56d-eddc-41b3-867d-8744277c5281",
2854+ "ID_FS_UUID_ENC": "ff51a56d-eddc-41b3-867d-8744277c5281",
2855+ "ID_FS_UUID_SUB": "10416813983586022065",
2856+ "ID_FS_UUID_SUB_ENC": "10416813983586022065",
2857+ "ID_FS_VERSION": "5000",
2858+ "ID_MODEL": "INTEL SSDPEDME400G4",
2859+ "ID_PART_ENTRY_DISK": "259:0",
2860+ "ID_PART_ENTRY_NUMBER": "1",
2861+ "ID_PART_ENTRY_OFFSET": "2048",
2862+ "ID_PART_ENTRY_SCHEME": "gpt",
2863+ "ID_PART_ENTRY_SIZE": "234373120",
2864+ "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4",
2865+ "ID_PART_ENTRY_UUID": "2a3296f5-905c-4bd9-835f-e764f564f3f1",
2866+ "ID_PART_TABLE_TYPE": "gpt",
2867+ "ID_PART_TABLE_UUID": "1d73687c-0668-4680-b827-165c9d1ce0be",
2868+ "ID_PATH": "pci-0000:05:00.0-nvme-1",
2869+ "ID_PATH_TAG": "pci-0000_05_00_0-nvme-1",
2870+ "ID_REVISION": "8DV10151",
2871+ "ID_SERIAL": "INTEL SSDPEDME400G4_CVMD4456000M400AGN",
2872+ "ID_SERIAL_SHORT": "CVMD4456000M400AGN",
2873+ "ID_WWN": "nvme.8086-43564d44343435363030304d34303041474e-494e54454c205353445045444d453430304734-00000001",
2874+ "MAJOR": "259",
2875+ "MINOR": "1",
2876+ "PARTN": "1",
2877+ "SUBSYSTEM": "block",
2878+ "TAGS": ":systemd:",
2879+ "USEC_INITIALIZED": "6287485",
2880+ "attrs": {
2881+ "alignment_offset": "0",
2882+ "dev": "259:1",
2883+ "discard_alignment": "0",
2884+ "inflight": " 0 0",
2885+ "partition": "1",
2886+ "ro": "0",
2887+ "size": "234373120",
2888+ "start": "2048",
2889+ "stat": " 9337755 562555 328925348 4455389 6325795 5531292 434894034 14122566 0 15525696 14010916 0 0 0 0",
2890+ "subsystem": "block",
2891+ "uevent": "MAJOR=259\nMINOR=1\nDEVNAME=nvme0n1p1\nDEVTYPE=partition\nPARTN=1"
2892+ }
2893+ },
2894+ "/dev/nvme0n1p2": {
2895+ "DEVLINKS": "/dev/disk/by-path/pci-0000:05:00.0-nvme-1-part2 /dev/disk/by-id/nvme-nvme.8086-43564d44343435363030304d34303041474e-494e54454c205353445045444d453430304734-00000001-part2 /dev/disk/by-partuuid/789835f9-0ca5-451a-af2d-d642934d83a6 /dev/disk/by-id/nvme-INTEL_SSDPEDME400G4_CVMD4456000M400AGN-part2 /dev/disk/by-partlabel/Linux\\x20filesystem /dev/disk/by-label/zfs-lxd /dev/disk/by-uuid/a2223601-dc79-4acb-90f3-5ecff7055873",
2896+ "DEVNAME": "/dev/nvme0n1p2",
2897+ "DEVPATH": "/devices/pci0000:00/0000:00:02.0/0000:05:00.0/nvme/nvme0/nvme0n1/nvme0n1p2",
2898+ "DEVTYPE": "partition",
2899+ "ID_FS_LABEL": "zfs-lxd",
2900+ "ID_FS_LABEL_ENC": "zfs-lxd",
2901+ "ID_FS_TYPE": "ext4",
2902+ "ID_FS_USAGE": "filesystem",
2903+ "ID_FS_UUID": "a2223601-dc79-4acb-90f3-5ecff7055873",
2904+ "ID_FS_UUID_ENC": "a2223601-dc79-4acb-90f3-5ecff7055873",
2905+ "ID_FS_UUID_SUB": "10416813983586022065",
2906+ "ID_FS_UUID_SUB_ENC": "10416813983586022065",
2907+ "ID_FS_VERSION": "1.0",
2908+ "ID_MODEL": "INTEL SSDPEDME400G4",
2909+ "ID_PART_ENTRY_DISK": "259:0",
2910+ "ID_PART_ENTRY_NAME": "Linux\\x20filesystem",
2911+ "ID_PART_ENTRY_NUMBER": "2",
2912+ "ID_PART_ENTRY_OFFSET": "234375168",
2913+ "ID_PART_ENTRY_SCHEME": "gpt",
2914+ "ID_PART_ENTRY_SIZE": "419430400",
2915+ "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4",
2916+ "ID_PART_ENTRY_UUID": "789835f9-0ca5-451a-af2d-d642934d83a6",
2917+ "ID_PART_TABLE_TYPE": "gpt",
2918+ "ID_PART_TABLE_UUID": "1d73687c-0668-4680-b827-165c9d1ce0be",
2919+ "ID_PATH": "pci-0000:05:00.0-nvme-1",
2920+ "ID_PATH_TAG": "pci-0000_05_00_0-nvme-1",
2921+ "ID_REVISION": "8DV10151",
2922+ "ID_SERIAL": "INTEL SSDPEDME400G4_CVMD4456000M400AGN",
2923+ "ID_SERIAL_SHORT": "CVMD4456000M400AGN",
2924+ "ID_WWN": "nvme.8086-43564d44343435363030304d34303041474e-494e54454c205353445045444d453430304734-00000001",
2925+ "MAJOR": "259",
2926+ "MINOR": "2",
2927+ "PARTN": "2",
2928+ "PARTNAME": "Linux filesystem",
2929+ "SUBSYSTEM": "block",
2930+ "TAGS": ":systemd:",
2931+ "USEC_INITIALIZED": "6301568",
2932+ "attrs": {
2933+ "alignment_offset": "0",
2934+ "dev": "259:2",
2935+ "discard_alignment": "0",
2936+ "inflight": " 0 0",
2937+ "partition": "2",
2938+ "ro": "0",
2939+ "size": "419430400",
2940+ "start": "234375168",
2941+ "stat": "37737247 143041 2659437243 34151530 171661257 4387365 37560192374 1154346438 0 63567088 903257364 56367 0 2058576136 67422",
2942+ "subsystem": "block",
2943+ "uevent": "MAJOR=259\nMINOR=2\nDEVNAME=nvme0n1p2\nDEVTYPE=partition\nPARTN=2\nPARTNAME=Linux filesystem"
2944+ }
2945+ },
2946+ "/dev/nvme0n1p3": {
2947+ "DEVLINKS": "/dev/disk/by-id/nvme-INTEL_SSDPEDME400G4_CVMD4456000M400AGN-part3 /dev/disk/by-partlabel/Linux\\x20filesystem /dev/disk/by-label/zfs-lxd /dev/disk/by-partuuid/b4b2f32d-271d-4ca5-b88d-0ae416347f28 /dev/disk/by-id/nvme-nvme.8086-43564d44343435363030304d34303041474e-494e54454c205353445045444d453430304734-00000001-part3 /dev/disk/by-path/pci-0000:05:00.0-nvme-1-part3 /dev/disk/by-uuid/13976804636456298589",
2948+ "DEVNAME": "/dev/nvme0n1p3",
2949+ "DEVPATH": "/devices/pci0000:00/0000:00:02.0/0000:05:00.0/nvme/nvme0/nvme0n1/nvme0n1p3",
2950+ "DEVTYPE": "partition",
2951+ "ID_FS_LABEL": "zfs-lxd",
2952+ "ID_FS_LABEL_ENC": "zfs-lxd",
2953+ "ID_FS_TYPE": "zfs_member",
2954+ "ID_FS_USAGE": "filesystem",
2955+ "ID_FS_UUID": "13976804636456298589",
2956+ "ID_FS_UUID_ENC": "13976804636456298589",
2957+ "ID_FS_UUID_SUB": "10416813983586022065",
2958+ "ID_FS_UUID_SUB_ENC": "10416813983586022065",
2959+ "ID_FS_VERSION": "5000",
2960+ "ID_MODEL": "INTEL SSDPEDME400G4",
2961+ "ID_PART_ENTRY_DISK": "259:0",
2962+ "ID_PART_ENTRY_NAME": "Linux\\x20filesystem",
2963+ "ID_PART_ENTRY_NUMBER": "3",
2964+ "ID_PART_ENTRY_OFFSET": "653805568",
2965+ "ID_PART_ENTRY_SCHEME": "gpt",
2966+ "ID_PART_ENTRY_SIZE": "127617167",
2967+ "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4",
2968+ "ID_PART_ENTRY_UUID": "b4b2f32d-271d-4ca5-b88d-0ae416347f28",
2969+ "ID_PART_TABLE_TYPE": "gpt",
2970+ "ID_PART_TABLE_UUID": "1d73687c-0668-4680-b827-165c9d1ce0be",
2971+ "ID_PATH": "pci-0000:05:00.0-nvme-1",
2972+ "ID_PATH_TAG": "pci-0000_05_00_0-nvme-1",
2973+ "ID_REVISION": "8DV10151",
2974+ "ID_SERIAL": "INTEL SSDPEDME400G4_CVMD4456000M400AGN",
2975+ "ID_SERIAL_SHORT": "CVMD4456000M400AGN",
2976+ "ID_WWN": "nvme.8086-43564d44343435363030304d34303041474e-494e54454c205353445045444d453430304734-00000001",
2977+ "MAJOR": "259",
2978+ "MINOR": "3",
2979+ "PARTN": "3",
2980+ "PARTNAME": "Linux filesystem",
2981+ "SUBSYSTEM": "block",
2982+ "TAGS": ":systemd:",
2983+ "USEC_INITIALIZED": "6282698",
2984+ "attrs": {
2985+ "alignment_offset": "0",
2986+ "dev": "259:3",
2987+ "discard_alignment": "0",
2988+ "inflight": " 0 0",
2989+ "partition": "3",
2990+ "ro": "0",
2991+ "size": "127617167",
2992+ "start": "653805568",
2993+ "stat": " 3205000 69 210062502 996903 32448561 374 925295965 11080995 0 6560644 3818800 0 0 0 0",
2994+ "subsystem": "block",
2995+ "uevent": "MAJOR=259\nMINOR=3\nDEVNAME=nvme0n1p3\nDEVTYPE=partition\nPARTN=3\nPARTNAME=Linux filesystem"
2996+ }
2997+ },
2998+ "/dev/sda": {
2999+ "DEVLINKS": "/dev/disk/by-dname/sda /dev/disk/by-id/scsi-33001438034e549a0 /dev/disk/by-path/pci-0000:03:00.0-sas-0x3001438034e549a0-lun-0 /dev/disk/by-id/wwn-0x3001438034e549a0",
3000+ "DEVNAME": "/dev/sda",
3001+ "DEVPATH": "/devices/pci0000:00/0000:00:01.0/0000:03:00.0/host0/scsi_host/host0/port-0:2/end_device-0:2/target0:0:1/0:0:1:0/block/sda",
3002+ "DEVTYPE": "disk",
3003+ "ID_BUS": "scsi",
3004+ "ID_MODEL": "MM1000GBKAL",
3005+ "ID_MODEL_ENC": "MM1000GBKAL\\x20\\x20\\x20\\x20\\x20",
3006+ "ID_PART_TABLE_TYPE": "gpt",
3007+ "ID_PART_TABLE_UUID": "a19d045b-8666-4f44-9d95-bf510f4dba68",
3008+ "ID_PATH": "pci-0000:03:00.0-sas-0x3001438034e549a0-lun-0",
3009+ "ID_PATH_TAG": "pci-0000_03_00_0-sas-0x3001438034e549a0-lun-0",
3010+ "ID_REVISION": "HPGC",
3011+ "ID_SCSI": "1",
3012+ "ID_SCSI_SERIAL": "9XG8HR8X",
3013+ "ID_SERIAL": "33001438034e549a0",
3014+ "ID_SERIAL_SHORT": "3001438034e549a0",
3015+ "ID_TYPE": "disk",
3016+ "ID_VENDOR": "ATA",
3017+ "ID_VENDOR_ENC": "ATA\\x20\\x20\\x20\\x20\\x20",
3018+ "ID_WWN": "0x3001438034e549a0",
3019+ "ID_WWN_WITH_EXTENSION": "0x3001438034e549a0",
3020+ "MAJOR": "8",
3021+ "MINOR": "0",
3022+ "SUBSYSTEM": "block",
3023+ "TAGS": ":systemd:",
3024+ "USEC_INITIALIZED": "5176541",
3025+ "attrs": {
3026+ "alignment_offset": "0",
3027+ "bdi": null,
3028+ "capability": "50",
3029+ "dev": "8:0",
3030+ "device": null,
3031+ "discard_alignment": "0",
3032+ "events": "",
3033+ "events_async": "",
3034+ "events_poll_msecs": "-1",
3035+ "ext_range": "256",
3036+ "hidden": "0",
3037+ "inflight": " 0 0",
3038+ "range": "16",
3039+ "removable": "0",
3040+ "ro": "0",
3041+ "size": "1000204886016",
3042+ "stat": " 1128321 216001 95350342 10802257 2909200 1858096 1363423473 104257149 0 17496360 107850064 0 0 0 0",
3043+ "subsystem": "block",
3044+ "uevent": "MAJOR=8\nMINOR=0\nDEVNAME=sda\nDEVTYPE=disk"
3045+ },
3046+ "partitiontable": {
3047+ "device": "/dev/sda",
3048+ "firstlba": 34,
3049+ "id": "A19D045B-8666-4F44-9D95-BF510F4DBA68",
3050+ "label": "gpt",
3051+ "lastlba": 1953525134,
3052+ "partitions": [
3053+ {
3054+ "node": "/dev/sda1",
3055+ "size": 974848,
3056+ "start": 2048,
3057+ "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
3058+ "uuid": "6347E694-3680-481F-B3B9-F13090855467"
3059+ },
3060+ {
3061+ "node": "/dev/sda2",
3062+ "size": 194330624,
3063+ "start": 976896,
3064+ "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
3065+ "uuid": "2ED7D79E-33ED-40D2-9A7D-C645B67CE661"
3066+ },
3067+ {
3068+ "node": "/dev/sda3",
3069+ "size": 1758208000,
3070+ "start": 195307520,
3071+ "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
3072+ "uuid": "F4662970-B21F-4797-9691-689784B30F04"
3073+ }
3074+ ],
3075+ "unit": "sectors"
3076+ }
3077+ },
3078+ "/dev/sda1": {
3079+ "DEVLINKS": "/dev/disk/by-uuid/5B63-D29B /dev/disk/by-path/pci-0000:03:00.0-sas-0x3001438034e549a0-lun-0-part1 /dev/disk/by-id/wwn-0x3001438034e549a0-part1 /dev/disk/by-partuuid/6347e694-3680-481f-b3b9-f13090855467 /dev/disk/by-id/scsi-33001438034e549a0-part1 /dev/disk/by-dname/sda-part1",
3080+ "DEVNAME": "/dev/sda1",
3081+ "DEVPATH": "/devices/pci0000:00/0000:00:01.0/0000:03:00.0/host0/scsi_host/host0/port-0:2/end_device-0:2/target0:0:1/0:0:1:0/block/sda/sda1",
3082+ "DEVTYPE": "partition",
3083+ "ID_BUS": "scsi",
3084+ "ID_FS_TYPE": "vfat",
3085+ "ID_FS_USAGE": "filesystem",
3086+ "ID_FS_UUID": "5B63-D29B",
3087+ "ID_FS_UUID_ENC": "5B63-D29B",
3088+ "ID_FS_VERSION": "FAT32",
3089+ "ID_MODEL": "MM1000GBKAL",
3090+ "ID_MODEL_ENC": "MM1000GBKAL\\x20\\x20\\x20\\x20\\x20",
3091+ "ID_PART_ENTRY_DISK": "8:0",
3092+ "ID_PART_ENTRY_NUMBER": "1",
3093+ "ID_PART_ENTRY_OFFSET": "2048",
3094+ "ID_PART_ENTRY_SCHEME": "gpt",
3095+ "ID_PART_ENTRY_SIZE": "974848",
3096+ "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4",
3097+ "ID_PART_ENTRY_UUID": "6347e694-3680-481f-b3b9-f13090855467",
3098+ "ID_PART_TABLE_TYPE": "gpt",
3099+ "ID_PART_TABLE_UUID": "a19d045b-8666-4f44-9d95-bf510f4dba68",
3100+ "ID_PATH": "pci-0000:03:00.0-sas-0x3001438034e549a0-lun-0",
3101+ "ID_PATH_TAG": "pci-0000_03_00_0-sas-0x3001438034e549a0-lun-0",
3102+ "ID_REVISION": "HPGC",
3103+ "ID_SCSI": "1",
3104+ "ID_SCSI_SERIAL": "9XG8HR8X",
3105+ "ID_SERIAL": "33001438034e549a0",
3106+ "ID_SERIAL_SHORT": "3001438034e549a0",
3107+ "ID_TYPE": "disk",
3108+ "ID_VENDOR": "ATA",
3109+ "ID_VENDOR_ENC": "ATA\\x20\\x20\\x20\\x20\\x20",
3110+ "ID_WWN": "0x3001438034e549a0",
3111+ "ID_WWN_WITH_EXTENSION": "0x3001438034e549a0",
3112+ "MAJOR": "8",
3113+ "MINOR": "1",
3114+ "PARTN": "1",
3115+ "SUBSYSTEM": "block",
3116+ "TAGS": ":systemd:",
3117+ "USEC_INITIALIZED": "5305033",
3118+ "attrs": {
3119+ "alignment_offset": "0",
3120+ "dev": "8:1",
3121+ "discard_alignment": "0",
3122+ "inflight": " 0 0",
3123+ "partition": "1",
3124+ "ro": "0",
3125+ "size": "499122176",
3126+ "start": "2048",
3127+ "stat": " 1076 858 29429 5864 1 0 1 21 0 1204 4868 0 0 0 0",
3128+ "subsystem": "block",
3129+ "uevent": "MAJOR=8\nMINOR=1\nDEVNAME=sda1\nDEVTYPE=partition\nPARTN=1"
3130+ },
3131+ "partitiontable": {
3132+ "device": "/dev/sda1",
3133+ "id": "0x00000000",
3134+ "label": "dos",
3135+ "partitions": [],
3136+ "unit": "sectors"
3137+ }
3138+ },
3139+ "/dev/sda2": {
3140+ "DEVLINKS": "/dev/disk/by-partuuid/2ed7d79e-33ed-40d2-9a7d-c645b67ce661 /dev/disk/by-path/pci-0000:03:00.0-sas-0x3001438034e549a0-lun-0-part2 /dev/disk/by-dname/sda-part2 /dev/disk/by-uuid/4615b428-57c2-4f45-a14c-ff8d16502247 /dev/disk/by-id/wwn-0x3001438034e549a0-part2 /dev/disk/by-id/scsi-33001438034e549a0-part2",
3141+ "DEVNAME": "/dev/sda2",
3142+ "DEVPATH": "/devices/pci0000:00/0000:00:01.0/0000:03:00.0/host0/scsi_host/host0/port-0:2/end_device-0:2/target0:0:1/0:0:1:0/block/sda/sda2",
3143+ "DEVTYPE": "partition",
3144+ "ID_BUS": "scsi",
3145+ "ID_FS_TYPE": "ext4",
3146+ "ID_FS_USAGE": "filesystem",
3147+ "ID_FS_UUID": "4615b428-57c2-4f45-a14c-ff8d16502247",
3148+ "ID_FS_UUID_ENC": "4615b428-57c2-4f45-a14c-ff8d16502247",
3149+ "ID_FS_VERSION": "1.0",
3150+ "ID_MODEL": "MM1000GBKAL",
3151+ "ID_MODEL_ENC": "MM1000GBKAL\\x20\\x20\\x20\\x20\\x20",
3152+ "ID_PART_ENTRY_DISK": "8:0",
3153+ "ID_PART_ENTRY_NUMBER": "2",
3154+ "ID_PART_ENTRY_OFFSET": "976896",
3155+ "ID_PART_ENTRY_SCHEME": "gpt",
3156+ "ID_PART_ENTRY_SIZE": "194330624",
3157+ "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4",
3158+ "ID_PART_ENTRY_UUID": "2ed7d79e-33ed-40d2-9a7d-c645b67ce661",
3159+ "ID_PART_TABLE_TYPE": "gpt",
3160+ "ID_PART_TABLE_UUID": "a19d045b-8666-4f44-9d95-bf510f4dba68",
3161+ "ID_PATH": "pci-0000:03:00.0-sas-0x3001438034e549a0-lun-0",
3162+ "ID_PATH_TAG": "pci-0000_03_00_0-sas-0x3001438034e549a0-lun-0",
3163+ "ID_REVISION": "HPGC",
3164+ "ID_SCSI": "1",
3165+ "ID_SCSI_SERIAL": "9XG8HR8X",
3166+ "ID_SERIAL": "33001438034e549a0",
3167+ "ID_SERIAL_SHORT": "3001438034e549a0",
3168+ "ID_TYPE": "disk",
3169+ "ID_VENDOR": "ATA",
3170+ "ID_VENDOR_ENC": "ATA\\x20\\x20\\x20\\x20\\x20",
3171+ "ID_WWN": "0x3001438034e549a0",
3172+ "ID_WWN_WITH_EXTENSION": "0x3001438034e549a0",
3173+ "MAJOR": "8",
3174+ "MINOR": "2",
3175+ "PARTN": "2",
3176+ "SUBSYSTEM": "block",
3177+ "TAGS": ":systemd:",
3178+ "USEC_INITIALIZED": "5240059",
3179+ "attrs": {
3180+ "alignment_offset": "0",
3181+ "dev": "8:2",
3182+ "discard_alignment": "0",
3183+ "inflight": " 0 0",
3184+ "partition": "2",
3185+ "ro": "0",
3186+ "size": "99497279488",
3187+ "start": "976896",
3188+ "stat": " 1886 0 123268 6873 1449 572 1806376 72449 0 8912 74792 0 0 0 0",
3189+ "subsystem": "block",
3190+ "uevent": "MAJOR=8\nMINOR=2\nDEVNAME=sda2\nDEVTYPE=partition\nPARTN=2"
3191+ }
3192+ },
3193+ "/dev/sda3": {
3194+ "DEVLINKS": "/dev/disk/by-dname/sda-part3 /dev/disk/by-uuid/f36394c0-3cc0-4423-8d6f-ffac130f171a /dev/disk/by-id/wwn-0x3001438034e549a0-part3 /dev/disk/by-partuuid/f4662970-b21f-4797-9691-689784b30f04 /dev/disk/by-path/pci-0000:03:00.0-sas-0x3001438034e549a0-lun-0-part3 /dev/disk/by-id/scsi-33001438034e549a0-part3",
3195+ "DEVNAME": "/dev/sda3",
3196+ "DEVPATH": "/devices/pci0000:00/0000:00:01.0/0000:03:00.0/host0/scsi_host/host0/port-0:2/end_device-0:2/target0:0:1/0:0:1:0/block/sda/sda3",
3197+ "DEVTYPE": "partition",
3198+ "ID_BUS": "scsi",
3199+ "ID_FS_TYPE": "bcache",
3200+ "ID_FS_USAGE": "other",
3201+ "ID_FS_UUID": "f36394c0-3cc0-4423-8d6f-ffac130f171a",
3202+ "ID_FS_UUID_ENC": "f36394c0-3cc0-4423-8d6f-ffac130f171a",
3203+ "ID_MODEL": "MM1000GBKAL",
3204+ "ID_MODEL_ENC": "MM1000GBKAL\\x20\\x20\\x20\\x20\\x20",
3205+ "ID_PART_ENTRY_DISK": "8:0",
3206+ "ID_PART_ENTRY_NUMBER": "3",
3207+ "ID_PART_ENTRY_OFFSET": "195307520",
3208+ "ID_PART_ENTRY_SCHEME": "gpt",
3209+ "ID_PART_ENTRY_SIZE": "1758208000",
3210+ "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4",
3211+ "ID_PART_ENTRY_UUID": "f4662970-b21f-4797-9691-689784b30f04",
3212+ "ID_PART_TABLE_TYPE": "gpt",
3213+ "ID_PART_TABLE_UUID": "a19d045b-8666-4f44-9d95-bf510f4dba68",
3214+ "ID_PATH": "pci-0000:03:00.0-sas-0x3001438034e549a0-lun-0",
3215+ "ID_PATH_TAG": "pci-0000_03_00_0-sas-0x3001438034e549a0-lun-0",
3216+ "ID_REVISION": "HPGC",
3217+ "ID_SCSI": "1",
3218+ "ID_SCSI_SERIAL": "9XG8HR8X",
3219+ "ID_SERIAL": "33001438034e549a0",
3220+ "ID_SERIAL_SHORT": "3001438034e549a0",
3221+ "ID_TYPE": "disk",
3222+ "ID_VENDOR": "ATA",
3223+ "ID_VENDOR_ENC": "ATA\\x20\\x20\\x20\\x20\\x20",
3224+ "ID_WWN": "0x3001438034e549a0",
3225+ "ID_WWN_WITH_EXTENSION": "0x3001438034e549a0",
3226+ "MAJOR": "8",
3227+ "MINOR": "3",
3228+ "PARTN": "3",
3229+ "SUBSYSTEM": "block",
3230+ "TAGS": ":systemd:",
3231+ "USEC_INITIALIZED": "5344170",
3232+ "attrs": {
3233+ "alignment_offset": "0",
3234+ "dev": "8:3",
3235+ "discard_alignment": "0",
3236+ "inflight": " 0 0",
3237+ "partition": "3",
3238+ "ro": "0",
3239+ "size": "900202496000",
3240+ "start": "195307520",
3241+ "stat": " 1124125 215143 95168714 10787262 2907750 1857524 1361617096 104184679 0 17486360 107768572 0 0 0 0",
3242+ "subsystem": "block",
3243+ "uevent": "MAJOR=8\nMINOR=3\nDEVNAME=sda3\nDEVTYPE=partition\nPARTN=3"
3244+ }
3245+ },
3246+ "/dev/sdb": {
3247+ "DEVLINKS": "/dev/disk/by-dname/sdb /dev/disk/by-path/pci-0000:03:00.0-sas-0x3001438034e549a1-lun-0 /dev/disk/by-id/scsi-33001438034e549a1 /dev/disk/by-id/wwn-0x3001438034e549a1",
3248+ "DEVNAME": "/dev/sdb",
3249+ "DEVPATH": "/devices/pci0000:00/0000:00:01.0/0000:03:00.0/host0/scsi_host/host0/port-0:3/end_device-0:3/target0:0:2/0:0:2:0/block/sdb",
3250+ "DEVTYPE": "disk",
3251+ "ID_BUS": "scsi",
3252+ "ID_MODEL": "MM1000GBKAL",
3253+ "ID_MODEL_ENC": "MM1000GBKAL\\x20\\x20\\x20\\x20\\x20",
3254+ "ID_PART_TABLE_TYPE": "gpt",
3255+ "ID_PART_TABLE_UUID": "b43975e4-0102-4e73-beaf-28c89fb7c168",
3256+ "ID_PATH": "pci-0000:03:00.0-sas-0x3001438034e549a1-lun-0",
3257+ "ID_PATH_TAG": "pci-0000_03_00_0-sas-0x3001438034e549a1-lun-0",
3258+ "ID_REVISION": "HPGC",
3259+ "ID_SCSI": "1",
3260+ "ID_SCSI_SERIAL": "9XG4LCPR",
3261+ "ID_SERIAL": "33001438034e549a1",
3262+ "ID_SERIAL_SHORT": "3001438034e549a1",
3263+ "ID_TYPE": "disk",
3264+ "ID_VENDOR": "ATA",
3265+ "ID_VENDOR_ENC": "ATA\\x20\\x20\\x20\\x20\\x20",
3266+ "ID_WWN": "0x3001438034e549a1",
3267+ "ID_WWN_WITH_EXTENSION": "0x3001438034e549a1",
3268+ "MAJOR": "8",
3269+ "MINOR": "16",
3270+ "SUBSYSTEM": "block",
3271+ "TAGS": ":systemd:",
3272+ "USEC_INITIALIZED": "5641291",
3273+ "attrs": {
3274+ "alignment_offset": "0",
3275+ "bdi": null,
3276+ "capability": "50",
3277+ "dev": "8:16",
3278+ "device": null,
3279+ "discard_alignment": "0",
3280+ "events": "",
3281+ "events_async": "",
3282+ "events_poll_msecs": "-1",
3283+ "ext_range": "256",
3284+ "hidden": "0",
3285+ "inflight": " 0 0",
3286+ "range": "16",
3287+ "removable": "0",
3288+ "ro": "0",
3289+ "size": "1000204886016",
3290+ "stat": " 894 0 19635 335 0 0 0 0 0 576 120 0 0 0 0",
3291+ "subsystem": "block",
3292+ "uevent": "MAJOR=8\nMINOR=16\nDEVNAME=sdb\nDEVTYPE=disk"
3293+ },
3294+ "partitiontable": {
3295+ "device": "/dev/sdb",
3296+ "firstlba": 34,
3297+ "id": "B43975E4-0102-4E73-BEAF-28C89FB7C168",
3298+ "label": "gpt",
3299+ "lastlba": 1953525134,
3300+ "partitions": [],
3301+ "unit": "sectors"
3302+ }
3303+ }
3304+ },
3305+ "dmcrypt": {},
3306+ "filesystem": {
3307+ "/dev/bcache0": {
3308+ "TYPE": "ext4",
3309+ "USAGE": "filesystem",
3310+ "UUID": "45354276-e0c0-4bf6-9083-f130b89411cc",
3311+ "UUID_ENC": "45354276-e0c0-4bf6-9083-f130b89411cc",
3312+ "VERSION": "1.0"
3313+ },
3314+ "/dev/nvme0n1": {
3315+ "LABEL": "zfs-lxd",
3316+ "LABEL_ENC": "zfs-lxd",
3317+ "TYPE": "zfs_member",
3318+ "USAGE": "filesystem",
3319+ "UUID": "13976804636456298589",
3320+ "UUID_ENC": "13976804636456298589",
3321+ "UUID_SUB": "10416813983586022065",
3322+ "UUID_SUB_ENC": "10416813983586022065",
3323+ "VERSION": "5000"
3324+ },
3325+ "/dev/nvme0n1p2": {
3326+ "LABEL": "zfs-lxd",
3327+ "LABEL_ENC": "zfs-lxd",
3328+ "TYPE": "ext4",
3329+ "USAGE": "filesystem",
3330+ "UUID": "a2223601-dc79-4acb-90f3-5ecff7055873",
3331+ "UUID_ENC": "a2223601-dc79-4acb-90f3-5ecff7055873",
3332+ "UUID_SUB": "10416813983586022065",
3333+ "UUID_SUB_ENC": "10416813983586022065",
3334+ "VERSION": "1.0"
3335+ },
3336+ "/dev/nvme0n1p3": {
3337+ "LABEL": "zfs-lxd",
3338+ "LABEL_ENC": "zfs-lxd",
3339+ "TYPE": "zfs_member",
3340+ "USAGE": "filesystem",
3341+ "UUID": "13976804636456298589",
3342+ "UUID_ENC": "13976804636456298589",
3343+ "UUID_SUB": "10416813983586022065",
3344+ "UUID_SUB_ENC": "10416813983586022065",
3345+ "VERSION": "5000"
3346+ },
3347+ "/dev/sda1": {
3348+ "TYPE": "vfat",
3349+ "USAGE": "filesystem",
3350+ "UUID": "5B63-D29B",
3351+ "UUID_ENC": "5B63-D29B",
3352+ "VERSION": "FAT32"
3353+ },
3354+ "/dev/sda2": {
3355+ "TYPE": "ext4",
3356+ "USAGE": "filesystem",
3357+ "UUID": "4615b428-57c2-4f45-a14c-ff8d16502247",
3358+ "UUID_ENC": "4615b428-57c2-4f45-a14c-ff8d16502247",
3359+ "VERSION": "1.0"
3360+ }
3361+ },
3362+ "lvm": {},
3363+ "mount": [
3364+ {
3365+ "children": [
3366+ {
3367+ "children": [
3368+ {
3369+ "fstype": "securityfs",
3370+ "options": "rw,nosuid,nodev,noexec,relatime",
3371+ "source": "securityfs",
3372+ "target": "/sys/kernel/security"
3373+ },
3374+ {
3375+ "children": [
3376+ {
3377+ "fstype": "cgroup2",
3378+ "options": "rw,nosuid,nodev,noexec,relatime",
3379+ "source": "cgroup2",
3380+ "target": "/sys/fs/cgroup/unified"
3381+ },
3382+ {
3383+ "fstype": "cgroup",
3384+ "options": "rw,nosuid,nodev,noexec,relatime,xattr,name=systemd",
3385+ "source": "cgroup",
3386+ "target": "/sys/fs/cgroup/systemd"
3387+ },
3388+ {
3389+ "fstype": "cgroup",
3390+ "options": "rw,nosuid,nodev,noexec,relatime,cpu,cpuacct",
3391+ "source": "cgroup",
3392+ "target": "/sys/fs/cgroup/cpu,cpuacct"
3393+ },
3394+ {
3395+ "fstype": "cgroup",
3396+ "options": "rw,nosuid,nodev,noexec,relatime,net_cls,net_prio",
3397+ "source": "cgroup",
3398+ "target": "/sys/fs/cgroup/net_cls,net_prio"
3399+ },
3400+ {
3401+ "fstype": "cgroup",
3402+ "options": "rw,nosuid,nodev,noexec,relatime,freezer",
3403+ "source": "cgroup",
3404+ "target": "/sys/fs/cgroup/freezer"
3405+ },
3406+ {
3407+ "fstype": "cgroup",
3408+ "options": "rw,nosuid,nodev,noexec,relatime,hugetlb",
3409+ "source": "cgroup",
3410+ "target": "/sys/fs/cgroup/hugetlb"
3411+ },
3412+ {
3413+ "fstype": "cgroup",
3414+ "options": "rw,nosuid,nodev,noexec,relatime,rdma",
3415+ "source": "cgroup",
3416+ "target": "/sys/fs/cgroup/rdma"
3417+ },
3418+ {
3419+ "fstype": "cgroup",
3420+ "options": "rw,nosuid,nodev,noexec,relatime,perf_event",
3421+ "source": "cgroup",
3422+ "target": "/sys/fs/cgroup/perf_event"
3423+ },
3424+ {
3425+ "fstype": "cgroup",
3426+ "options": "rw,nosuid,nodev,noexec,relatime,pids",
3427+ "source": "cgroup",
3428+ "target": "/sys/fs/cgroup/pids"
3429+ },
3430+ {
3431+ "fstype": "cgroup",
3432+ "options": "rw,nosuid,nodev,noexec,relatime,cpuset",
3433+ "source": "cgroup",
3434+ "target": "/sys/fs/cgroup/cpuset"
3435+ },
3436+ {
3437+ "fstype": "cgroup",
3438+ "options": "rw,nosuid,nodev,noexec,relatime,blkio",
3439+ "source": "cgroup",
3440+ "target": "/sys/fs/cgroup/blkio"
3441+ },
3442+ {
3443+ "fstype": "cgroup",
3444+ "options": "rw,nosuid,nodev,noexec,relatime,memory",
3445+ "source": "cgroup",
3446+ "target": "/sys/fs/cgroup/memory"
3447+ },
3448+ {
3449+ "fstype": "cgroup",
3450+ "options": "rw,nosuid,nodev,noexec,relatime,devices",
3451+ "source": "cgroup",
3452+ "target": "/sys/fs/cgroup/devices"
3453+ }
3454+ ],
3455+ "fstype": "tmpfs",
3456+ "options": "ro,nosuid,nodev,noexec,mode=755",
3457+ "source": "tmpfs",
3458+ "target": "/sys/fs/cgroup"
3459+ },
3460+ {
3461+ "fstype": "pstore",
3462+ "options": "rw,nosuid,nodev,noexec,relatime",
3463+ "source": "pstore",
3464+ "target": "/sys/fs/pstore"
3465+ },
3466+ {
3467+ "fstype": "efivarfs",
3468+ "options": "rw,nosuid,nodev,noexec,relatime",
3469+ "source": "efivarfs",
3470+ "target": "/sys/firmware/efi/efivars"
3471+ },
3472+ {
3473+ "fstype": "bpf",
3474+ "options": "rw,nosuid,nodev,noexec,relatime,mode=700",
3475+ "source": "bpf",
3476+ "target": "/sys/fs/bpf"
3477+ },
3478+ {
3479+ "fstype": "debugfs",
3480+ "options": "rw,relatime",
3481+ "source": "debugfs",
3482+ "target": "/sys/kernel/debug"
3483+ },
3484+ {
3485+ "fstype": "configfs",
3486+ "options": "rw,relatime",
3487+ "source": "configfs",
3488+ "target": "/sys/kernel/config"
3489+ },
3490+ {
3491+ "fstype": "fusectl",
3492+ "options": "rw,relatime",
3493+ "source": "fusectl",
3494+ "target": "/sys/fs/fuse/connections"
3495+ }
3496+ ],
3497+ "fstype": "sysfs",
3498+ "options": "rw,nosuid,nodev,noexec,relatime",
3499+ "source": "sysfs",
3500+ "target": "/sys"
3501+ },
3502+ {
3503+ "children": [
3504+ {
3505+ "children": [
3506+ {
3507+ "fstype": "binfmt_misc",
3508+ "options": "rw,relatime",
3509+ "source": "binfmt_misc",
3510+ "target": "/proc/sys/fs/binfmt_misc"
3511+ }
3512+ ],
3513+ "fstype": "autofs",
3514+ "options": "rw,relatime,fd=38,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=18010",
3515+ "source": "systemd-1",
3516+ "target": "/proc/sys/fs/binfmt_misc"
3517+ }
3518+ ],
3519+ "fstype": "proc",
3520+ "options": "rw,nosuid,nodev,noexec,relatime",
3521+ "source": "proc",
3522+ "target": "/proc"
3523+ },
3524+ {
3525+ "children": [
3526+ {
3527+ "fstype": "devpts",
3528+ "options": "rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000",
3529+ "source": "devpts",
3530+ "target": "/dev/pts"
3531+ },
3532+ {
3533+ "fstype": "tmpfs",
3534+ "options": "rw,nosuid,nodev",
3535+ "source": "tmpfs",
3536+ "target": "/dev/shm"
3537+ },
3538+ {
3539+ "fstype": "hugetlbfs",
3540+ "options": "rw,relatime,pagesize=2M",
3541+ "source": "hugetlbfs",
3542+ "target": "/dev/hugepages"
3543+ },
3544+ {
3545+ "fstype": "mqueue",
3546+ "options": "rw,relatime",
3547+ "source": "mqueue",
3548+ "target": "/dev/mqueue"
3549+ }
3550+ ],
3551+ "fstype": "devtmpfs",
3552+ "options": "rw,nosuid,relatime,size=16367252k,nr_inodes=4091813,mode=755",
3553+ "source": "udev",
3554+ "target": "/dev"
3555+ },
3556+ {
3557+ "children": [
3558+ {
3559+ "fstype": "tmpfs",
3560+ "options": "rw,nosuid,nodev,noexec,relatime,size=5120k",
3561+ "source": "tmpfs",
3562+ "target": "/run/lock"
3563+ },
3564+ {
3565+ "children": [
3566+ {
3567+ "fstype": "nsfs",
3568+ "options": "rw",
3569+ "source": "nsfs[mnt:[4026532868]]",
3570+ "target": "/run/snapd/ns/lxd.mnt"
3571+ }
3572+ ],
3573+ "fstype": "tmpfs",
3574+ "options": "rw,nosuid,noexec,relatime,size=3280384k,mode=755",
3575+ "source": "tmpfs[/snapd/ns]",
3576+ "target": "/run/snapd/ns"
3577+ },
3578+ {
3579+ "fstype": "tmpfs",
3580+ "options": "rw,nosuid,nodev,relatime,size=3280384k,mode=700,uid=1001,gid=1001",
3581+ "source": "tmpfs",
3582+ "target": "/run/user/1001"
3583+ },
3584+ {
3585+ "fstype": "tmpfs",
3586+ "options": "rw,nosuid,nodev,relatime,size=3280384k,mode=700,uid=1002,gid=1002",
3587+ "source": "tmpfs",
3588+ "target": "/run/user/1002"
3589+ },
3590+ {
3591+ "fstype": "tmpfs",
3592+ "options": "rw,nosuid,nodev,relatime,size=3280384k,mode=700,uid=1011,gid=1014",
3593+ "source": "tmpfs",
3594+ "target": "/run/user/1011"
3595+ }
3596+ ],
3597+ "fstype": "tmpfs",
3598+ "options": "rw,nosuid,noexec,relatime,size=3280384k,mode=755",
3599+ "source": "tmpfs",
3600+ "target": "/run"
3601+ },
3602+ {
3603+ "fstype": "squashfs",
3604+ "options": "ro,nodev,relatime",
3605+ "source": "/dev/loop2",
3606+ "target": "/snap/juju/7729"
3607+ },
3608+ {
3609+ "fstype": "squashfs",
3610+ "options": "ro,nodev,relatime",
3611+ "source": "/dev/loop3",
3612+ "target": "/snap/git-ubuntu/450"
3613+ },
3614+ {
3615+ "fstype": "squashfs",
3616+ "options": "ro,nodev,relatime",
3617+ "source": "/dev/loop9",
3618+ "target": "/snap/juju/7598"
3619+ },
3620+ {
3621+ "fstype": "squashfs",
3622+ "options": "ro,nodev,relatime",
3623+ "source": "/dev/loop18",
3624+ "target": "/snap/ubuntu-image/141"
3625+ },
3626+ {
3627+ "fstype": "squashfs",
3628+ "options": "ro,nodev,relatime",
3629+ "source": "/dev/loop0",
3630+ "target": "/snap/image-status/26"
3631+ },
3632+ {
3633+ "fstype": "squashfs",
3634+ "options": "ro,nodev,relatime",
3635+ "source": "/dev/loop1",
3636+ "target": "/snap/core/6531"
3637+ },
3638+ {
3639+ "fstype": "squashfs",
3640+ "options": "ro,nodev,relatime",
3641+ "source": "/dev/loop25",
3642+ "target": "/snap/ubuntu-image/139"
3643+ },
3644+ {
3645+ "fstype": "squashfs",
3646+ "options": "ro,nodev,relatime",
3647+ "source": "/dev/loop7",
3648+ "target": "/snap/multipass/587"
3649+ },
3650+ {
3651+ "fstype": "squashfs",
3652+ "options": "ro,nodev,relatime",
3653+ "source": "/dev/loop28",
3654+ "target": "/snap/ubuntu-image/143"
3655+ },
3656+ {
3657+ "children": [
3658+ {
3659+ "fstype": "vfat",
3660+ "options": "rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro",
3661+ "source": "/dev/sda1",
3662+ "target": "/boot/efi"
3663+ }
3664+ ],
3665+ "fstype": "ext4",
3666+ "options": "rw,relatime",
3667+ "source": "/dev/sda2",
3668+ "target": "/boot"
3669+ },
3670+ {
3671+ "fstype": "squashfs",
3672+ "options": "ro,nodev,relatime",
3673+ "source": "/dev/loop13",
3674+ "target": "/snap/image-status/1"
3675+ },
3676+ {
3677+ "fstype": "ext4",
3678+ "options": "rw,relatime",
3679+ "source": "/dev/nvme0n1p2",
3680+ "target": "/srv"
3681+ },
3682+ {
3683+ "fstype": "squashfs",
3684+ "options": "ro,nodev,relatime",
3685+ "source": "/dev/loop14",
3686+ "target": "/snap/ubuntu-bug-triage/66"
3687+ },
3688+ {
3689+ "fstype": "squashfs",
3690+ "options": "ro,nodev,relatime",
3691+ "source": "/dev/loop15",
3692+ "target": "/snap/image-status/3"
3693+ },
3694+ {
3695+ "fstype": "squashfs",
3696+ "options": "ro,nodev,relatime",
3697+ "source": "/dev/loop20",
3698+ "target": "/snap/cmadison/3"
3699+ },
3700+ {
3701+ "fstype": "squashfs",
3702+ "options": "ro,nodev,relatime",
3703+ "source": "/dev/loop22",
3704+ "target": "/snap/cmadison/2"
3705+ },
3706+ {
3707+ "fstype": "squashfs",
3708+ "options": "ro,nodev,relatime",
3709+ "source": "/dev/loop19",
3710+ "target": "/snap/ubuntu-bug-triage/91"
3711+ },
3712+ {
3713+ "fstype": "squashfs",
3714+ "options": "ro,nodev,relatime",
3715+ "source": "/dev/loop8",
3716+ "target": "/snap/multipass/752"
3717+ },
3718+ {
3719+ "fstype": "squashfs",
3720+ "options": "ro,nodev,relatime",
3721+ "source": "/dev/loop26",
3722+ "target": "/snap/juju/7686"
3723+ },
3724+ {
3725+ "fstype": "squashfs",
3726+ "options": "ro,nodev,relatime",
3727+ "source": "/dev/loop11",
3728+ "target": "/snap/lxd/10601"
3729+ },
3730+ {
3731+ "fstype": "squashfs",
3732+ "options": "ro,nodev,relatime",
3733+ "source": "/dev/loop5",
3734+ "target": "/snap/lxd/10756"
3735+ },
3736+ {
3737+ "fstype": "squashfs",
3738+ "options": "ro,nodev,relatime",
3739+ "source": "/dev/loop10",
3740+ "target": "/snap/core/6818"
3741+ },
3742+ {
3743+ "fstype": "squashfs",
3744+ "options": "ro,nodev,relatime",
3745+ "source": "/dev/loop27",
3746+ "target": "/snap/git-ubuntu/451"
3747+ },
3748+ {
3749+ "fstype": "squashfs",
3750+ "options": "ro,nodev,relatime",
3751+ "source": "/dev/loop24",
3752+ "target": "/snap/ubuntu-bug-triage/95"
3753+ },
3754+ {
3755+ "fstype": "squashfs",
3756+ "options": "ro,nodev,relatime",
3757+ "source": "/dev/loop6",
3758+ "target": "/snap/core/6673"
3759+ },
3760+ {
3761+ "fstype": "squashfs",
3762+ "options": "ro,nodev,relatime",
3763+ "source": "/dev/loop12",
3764+ "target": "/snap/git-ubuntu/449"
3765+ },
3766+ {
3767+ "fstype": "squashfs",
3768+ "options": "ro,nodev,relatime",
3769+ "source": "/dev/loop4",
3770+ "target": "/snap/multipass/716"
3771+ },
3772+ {
3773+ "fstype": "squashfs",
3774+ "options": "ro,nodev,relatime",
3775+ "source": "/dev/loop23",
3776+ "target": "/snap/lxd/10526"
3777+ },
3778+ {
3779+ "children": [
3780+ {
3781+ "fstype": "nsfs",
3782+ "options": "rw",
3783+ "source": "nsfs[mnt:[4026532851]]",
3784+ "target": "/var/snap/lxd/common/ns/shmounts"
3785+ }
3786+ ],
3787+ "fstype": "tmpfs",
3788+ "options": "rw,relatime,size=1024k,mode=700",
3789+ "source": "tmpfs",
3790+ "target": "/var/snap/lxd/common/ns"
3791+ }
3792+ ],
3793+ "fstype": "ext4",
3794+ "options": "rw,relatime",
3795+ "source": "/dev/bcache0",
3796+ "target": "/"
3797+ }
3798+ ],
3799+ "multipath": {},
3800+ "raid": {},
3801+ "zfs": {
3802+ "zpools": {
3803+ "zfs-lxd": {
3804+ "datasets": {
3805+ "zfs-lxd": {
3806+ "properties": {
3807+ "aclinherit": {
3808+ "source": "default",
3809+ "value": "restricted"
3810+ },
3811+ "acltype": {
3812+ "source": "default",
3813+ "value": "off"
3814+ },
3815+ "atime": {
3816+ "source": "default",
3817+ "value": "on"
3818+ },
3819+ "available": {
3820+ "source": "-",
3821+ "value": "27543762944"
3822+ },
3823+ "canmount": {
3824+ "source": "default",
3825+ "value": "on"
3826+ },
3827+ "casesensitivity": {
3828+ "source": "-",
3829+ "value": "sensitive"
3830+ },
3831+ "checksum": {
3832+ "source": "default",
3833+ "value": "on"
3834+ },
3835+ "compression": {
3836+ "source": "local",
3837+ "value": "on"
3838+ },
3839+ "compressratio": {
3840+ "source": "-",
3841+ "value": "1.89"
3842+ },
3843+ "context": {
3844+ "source": "default",
3845+ "value": "none"
3846+ },
3847+ "copies": {
3848+ "source": "default",
3849+ "value": "1"
3850+ },
3851+ "createtxg": {
3852+ "source": "-",
3853+ "value": "1"
3854+ },
3855+ "creation": {
3856+ "source": "-",
3857+ "value": "1528992782"
3858+ },
3859+ "dedup": {
3860+ "source": "default",
3861+ "value": "off"
3862+ },
3863+ "defcontext": {
3864+ "source": "default",
3865+ "value": "none"
3866+ },
3867+ "devices": {
3868+ "source": "default",
3869+ "value": "on"
3870+ },
3871+ "dnodesize": {
3872+ "source": "default",
3873+ "value": "legacy"
3874+ },
3875+ "exec": {
3876+ "source": "default",
3877+ "value": "on"
3878+ },
3879+ "filesystem_count": {
3880+ "source": "default",
3881+ "value": "18446744073709551615"
3882+ },
3883+ "filesystem_limit": {
3884+ "source": "default",
3885+ "value": "18446744073709551615"
3886+ },
3887+ "fscontext": {
3888+ "source": "default",
3889+ "value": "none"
3890+ },
3891+ "guid": {
3892+ "source": "-",
3893+ "value": "13025381288287755859"
3894+ },
3895+ "logbias": {
3896+ "source": "default",
3897+ "value": "latency"
3898+ },
3899+ "logicalreferenced": {
3900+ "source": "-",
3901+ "value": "12288"
3902+ },
3903+ "logicalused": {
3904+ "source": "-",
3905+ "value": "66775106560"
3906+ },
3907+ "mlslabel": {
3908+ "source": "default",
3909+ "value": "none"
3910+ },
3911+ "mounted": {
3912+ "source": "-",
3913+ "value": "no"
3914+ },
3915+ "mountpoint": {
3916+ "source": "local",
3917+ "value": "none"
3918+ },
3919+ "nbmand": {
3920+ "source": "default",
3921+ "value": "off"
3922+ },
3923+ "normalization": {
3924+ "source": "-",
3925+ "value": "none"
3926+ },
3927+ "overlay": {
3928+ "source": "default",
3929+ "value": "off"
3930+ },
3931+ "primarycache": {
3932+ "source": "default",
3933+ "value": "all"
3934+ },
3935+ "quota": {
3936+ "source": "default",
3937+ "value": "0"
3938+ },
3939+ "readonly": {
3940+ "source": "default",
3941+ "value": "off"
3942+ },
3943+ "recordsize": {
3944+ "source": "default",
3945+ "value": "131072"
3946+ },
3947+ "redundant_metadata": {
3948+ "source": "default",
3949+ "value": "all"
3950+ },
3951+ "refcompressratio": {
3952+ "source": "-",
3953+ "value": "1.00"
3954+ },
3955+ "referenced": {
3956+ "source": "-",
3957+ "value": "24576"
3958+ },
3959+ "refquota": {
3960+ "source": "default",
3961+ "value": "0"
3962+ },
3963+ "refreservation": {
3964+ "source": "default",
3965+ "value": "0"
3966+ },
3967+ "relatime": {
3968+ "source": "default",
3969+ "value": "off"
3970+ },
3971+ "reservation": {
3972+ "source": "default",
3973+ "value": "0"
3974+ },
3975+ "rootcontext": {
3976+ "source": "default",
3977+ "value": "none"
3978+ },
3979+ "secondarycache": {
3980+ "source": "default",
3981+ "value": "all"
3982+ },
3983+ "setuid": {
3984+ "source": "default",
3985+ "value": "on"
3986+ },
3987+ "sharenfs": {
3988+ "source": "default",
3989+ "value": "off"
3990+ },
3991+ "sharesmb": {
3992+ "source": "default",
3993+ "value": "off"
3994+ },
3995+ "snapdev": {
3996+ "source": "default",
3997+ "value": "hidden"
3998+ },
3999+ "snapdir": {
4000+ "source": "default",
4001+ "value": "hidden"
4002+ },
4003+ "snapshot_count": {
4004+ "source": "default",
4005+ "value": "18446744073709551615"
4006+ },
4007+ "snapshot_limit": {
4008+ "source": "default",
4009+ "value": "18446744073709551615"
4010+ },
4011+ "sync": {
4012+ "source": "default",
4013+ "value": "standard"
4014+ },
4015+ "type": {
4016+ "source": "-",
4017+ "value": "filesystem"
4018+ },
4019+ "used": {
4020+ "source": "-",
4021+ "value": "35387574272"
4022+ },
4023+ "usedbychildren": {
4024+ "source": "-",
4025+ "value": "35387549696"
4026+ },
4027+ "usedbydataset": {
4028+ "source": "-",
4029+ "value": "24576"
4030+ },
4031+ "usedbyrefreservation": {
4032+ "source": "-",
4033+ "value": "0"
4034+ },
4035+ "usedbysnapshots": {
4036+ "source": "-",
4037+ "value": "0"
4038+ },
4039+ "utf8only": {
4040+ "source": "-",
4041+ "value": "off"
4042+ },
4043+ "version": {
4044+ "source": "-",
4045+ "value": "5"
4046+ },
4047+ "volmode": {
4048+ "source": "default",
4049+ "value": "default"
4050+ },
4051+ "vscan": {
4052+ "source": "default",
4053+ "value": "off"
4054+ },
4055+ "written": {
4056+ "source": "-",
4057+ "value": "24576"
4058+ },
4059+ "xattr": {
4060+ "source": "default",
4061+ "value": "on"
4062+ },
4063+ "zoned": {
4064+ "source": "default",
4065+ "value": "off"
4066+ }
4067+ }
4068+ },
4069+ "zfs-lxd/containers": {
4070+ "properties": {
4071+ "aclinherit": {
4072+ "source": "default",
4073+ "value": "restricted"
4074+ },
4075+ "acltype": {
4076+ "source": "default",
4077+ "value": "off"
4078+ },
4079+ "atime": {
4080+ "source": "default",
4081+ "value": "on"
4082+ },
4083+ "available": {
4084+ "source": "-",
4085+ "value": "27543762944"
4086+ },
4087+ "canmount": {
4088+ "source": "default",
4089+ "value": "on"
4090+ },
4091+ "casesensitivity": {
4092+ "source": "-",
4093+ "value": "sensitive"
4094+ },
4095+ "checksum": {
4096+ "source": "default",
4097+ "value": "on"
4098+ },
4099+ "compression": {
4100+ "source": "inherited from zfs-lxd",
4101+ "value": "on"
4102+ },
4103+ "compressratio": {
4104+ "source": "-",
4105+ "value": "1.92"
4106+ },
4107+ "context": {
4108+ "source": "default",
4109+ "value": "none"
4110+ },
4111+ "copies": {
4112+ "source": "default",
4113+ "value": "1"
4114+ },
4115+ "createtxg": {
4116+ "source": "-",
4117+ "value": "6"
4118+ },
4119+ "creation": {
4120+ "source": "-",
4121+ "value": "1528992782"
4122+ },
4123+ "dedup": {
4124+ "source": "default",
4125+ "value": "off"
4126+ },
4127+ "defcontext": {
4128+ "source": "default",
4129+ "value": "none"
4130+ },
4131+ "devices": {
4132+ "source": "default",
4133+ "value": "on"
4134+ },
4135+ "dnodesize": {
4136+ "source": "default",
4137+ "value": "legacy"
4138+ },
4139+ "exec": {
4140+ "source": "default",
4141+ "value": "on"
4142+ },
4143+ "filesystem_count": {
4144+ "source": "default",
4145+ "value": "18446744073709551615"
4146+ },
4147+ "filesystem_limit": {
4148+ "source": "default",
4149+ "value": "18446744073709551615"
4150+ },
4151+ "fscontext": {
4152+ "source": "default",
4153+ "value": "none"
4154+ },
4155+ "guid": {
4156+ "source": "-",
4157+ "value": "10922728633316508647"
4158+ },
4159+ "logbias": {
4160+ "source": "default",
4161+ "value": "latency"
4162+ },
4163+ "logicalreferenced": {
4164+ "source": "-",
4165+ "value": "12288"
4166+ },
4167+ "logicalused": {
4168+ "source": "-",
4169+ "value": "53562651648"
4170+ },
4171+ "mlslabel": {
4172+ "source": "default",
4173+ "value": "none"
4174+ },
4175+ "mounted": {
4176+ "source": "-",
4177+ "value": "no"
4178+ },
4179+ "mountpoint": {
4180+ "source": "local",
4181+ "value": "none"
4182+ },
4183+ "nbmand": {
4184+ "source": "default",
4185+ "value": "off"
4186+ },
4187+ "normalization": {
4188+ "source": "-",
4189+ "value": "none"
4190+ },
4191+ "overlay": {
4192+ "source": "default",
4193+ "value": "off"
4194+ },
4195+ "primarycache": {
4196+ "source": "default",
4197+ "value": "all"
4198+ },
4199+ "quota": {
4200+ "source": "default",
4201+ "value": "0"
4202+ },
4203+ "readonly": {
4204+ "source": "default",
4205+ "value": "off"
4206+ },
4207+ "recordsize": {
4208+ "source": "default",
4209+ "value": "131072"
4210+ },
4211+ "redundant_metadata": {
4212+ "source": "default",
4213+ "value": "all"
4214+ },
4215+ "refcompressratio": {
4216+ "source": "-",
4217+ "value": "1.00"
4218+ },
4219+ "referenced": {
4220+ "source": "-",
4221+ "value": "24576"
4222+ },
4223+ "refquota": {
4224+ "source": "default",
4225+ "value": "0"
4226+ },
4227+ "refreservation": {
4228+ "source": "default",
4229+ "value": "0"
4230+ },
4231+ "relatime": {
4232+ "source": "default",
4233+ "value": "off"
4234+ },
4235+ "reservation": {
4236+ "source": "default",
4237+ "value": "0"
4238+ },
4239+ "rootcontext": {
4240+ "source": "default",
4241+ "value": "none"
4242+ },
4243+ "secondarycache": {
4244+ "source": "default",
4245+ "value": "all"
4246+ },
4247+ "setuid": {
4248+ "source": "default",
4249+ "value": "on"
4250+ },
4251+ "sharenfs": {
4252+ "source": "default",
4253+ "value": "off"
4254+ },
4255+ "sharesmb": {
4256+ "source": "default",
4257+ "value": "off"
4258+ },
4259+ "snapdev": {
4260+ "source": "default",
4261+ "value": "hidden"
4262+ },
4263+ "snapdir": {
4264+ "source": "default",
4265+ "value": "hidden"
4266+ },
4267+ "snapshot_count": {
4268+ "source": "default",
4269+ "value": "18446744073709551615"
4270+ },
4271+ "snapshot_limit": {
4272+ "source": "default",
4273+ "value": "18446744073709551615"
4274+ },
4275+ "sync": {
4276+ "source": "default",
4277+ "value": "standard"
4278+ },
4279+ "type": {
4280+ "source": "-",
4281+ "value": "filesystem"
4282+ },
4283+ "used": {
4284+ "source": "-",
4285+ "value": "27919717888"
4286+ },
4287+ "usedbychildren": {
4288+ "source": "-",
4289+ "value": "27919693312"
4290+ },
4291+ "usedbydataset": {
4292+ "source": "-",
4293+ "value": "24576"
4294+ },
4295+ "usedbyrefreservation": {
4296+ "source": "-",
4297+ "value": "0"
4298+ },
4299+ "usedbysnapshots": {
4300+ "source": "-",
4301+ "value": "0"
4302+ },
4303+ "utf8only": {
4304+ "source": "-",
4305+ "value": "off"
4306+ },
4307+ "version": {
4308+ "source": "-",
4309+ "value": "5"
4310+ },
4311+ "volmode": {
4312+ "source": "default",
4313+ "value": "default"
4314+ },
4315+ "vscan": {
4316+ "source": "default",
4317+ "value": "off"
4318+ },
4319+ "written": {
4320+ "source": "-",
4321+ "value": "24576"
4322+ },
4323+ "xattr": {
4324+ "source": "default",
4325+ "value": "on"
4326+ },
4327+ "zoned": {
4328+ "source": "default",
4329+ "value": "off"
4330+ }
4331+ }
4332+ },
4333+ "zfs-lxd/containers/andreas-cosmic-mongodb": {
4334+ "properties": {
4335+ "aclinherit": {
4336+ "source": "default",
4337+ "value": "restricted"
4338+ },
4339+ "acltype": {
4340+ "source": "default",
4341+ "value": "off"
4342+ },
4343+ "atime": {
4344+ "source": "default",
4345+ "value": "on"
4346+ },
4347+ "available": {
4348+ "source": "-",
4349+ "value": "27543762944"
4350+ },
4351+ "canmount": {
4352+ "source": "local",
4353+ "value": "noauto"
4354+ },
4355+ "casesensitivity": {
4356+ "source": "-",
4357+ "value": "sensitive"
4358+ },
4359+ "checksum": {
4360+ "source": "default",
4361+ "value": "on"
4362+ },
4363+ "compression": {
4364+ "source": "inherited from zfs-lxd",
4365+ "value": "on"
4366+ },
4367+ "compressratio": {
4368+ "source": "-",
4369+ "value": "2.31"
4370+ },
4371+ "context": {
4372+ "source": "default",
4373+ "value": "none"
4374+ },
4375+ "copies": {
4376+ "source": "default",
4377+ "value": "1"
4378+ },
4379+ "createtxg": {
4380+ "source": "-",
4381+ "value": "4756245"
4382+ },
4383+ "creation": {
4384+ "source": "-",
4385+ "value": "1553280441"
4386+ },
4387+ "dedup": {
4388+ "source": "default",
4389+ "value": "off"
4390+ },
4391+ "defcontext": {
4392+ "source": "default",
4393+ "value": "none"
4394+ },
4395+ "devices": {
4396+ "source": "default",
4397+ "value": "on"
4398+ },
4399+ "dnodesize": {
4400+ "source": "default",
4401+ "value": "legacy"
4402+ },
4403+ "exec": {
4404+ "source": "default",
4405+ "value": "on"
4406+ },
4407+ "filesystem_count": {
4408+ "source": "default",
4409+ "value": "18446744073709551615"
4410+ },
4411+ "filesystem_limit": {
4412+ "source": "default",
4413+ "value": "18446744073709551615"
4414+ },
4415+ "fscontext": {
4416+ "source": "default",
4417+ "value": "none"
4418+ },
4419+ "guid": {
4420+ "source": "-",
4421+ "value": "18350500034647316947"
4422+ },
4423+ "logbias": {
4424+ "source": "default",
4425+ "value": "latency"
4426+ },
4427+ "logicalreferenced": {
4428+ "source": "-",
4429+ "value": "33654733824"
4430+ },
4431+ "logicalused": {
4432+ "source": "-",
4433+ "value": "32866620928"
4434+ },
4435+ "mlslabel": {
4436+ "source": "default",
4437+ "value": "none"
4438+ },
4439+ "mounted": {
4440+ "source": "-",
4441+ "value": "no"
4442+ },
4443+ "mountpoint": {
4444+ "source": "local",
4445+ "value": "/var/snap/lxd/common/lxd/storage-pools/zfs-lxd/containers/andreas-cosmic-mongodb"
4446+ },
4447+ "nbmand": {
4448+ "source": "default",
4449+ "value": "off"
4450+ },
4451+ "normalization": {
4452+ "source": "-",
4453+ "value": "none"
4454+ },
4455+ "origin": {
4456+ "source": "-",
4457+ "value": "zfs-lxd/deleted/images/1650846799559e33e536cd8f4576d3c4e8d79c15e445c293471587abe55a805f@readonly"
4458+ },
4459+ "overlay": {
4460+ "source": "default",
4461+ "value": "off"
4462+ },
4463+ "primarycache": {
4464+ "source": "default",
4465+ "value": "all"
4466+ },
4467+ "quota": {
4468+ "source": "default",
4469+ "value": "0"
4470+ },
4471+ "readonly": {
4472+ "source": "default",
4473+ "value": "off"
4474+ },
4475+ "recordsize": {
4476+ "source": "default",
4477+ "value": "131072"
4478+ },
4479+ "redundant_metadata": {
4480+ "source": "default",
4481+ "value": "all"
4482+ },
4483+ "refcompressratio": {
4484+ "source": "-",
4485+ "value": "2.29"
4486+ },
4487+ "referenced": {
4488+ "source": "-",
4489+ "value": "14717420544"
4490+ },
4491+ "refquota": {
4492+ "source": "default",
4493+ "value": "0"
4494+ },
4495+ "refreservation": {
4496+ "source": "default",
4497+ "value": "0"
4498+ },
4499+ "relatime": {
4500+ "source": "default",
4501+ "value": "off"
4502+ },
4503+ "reservation": {
4504+ "source": "default",
4505+ "value": "0"
4506+ },
4507+ "rootcontext": {
4508+ "source": "default",
4509+ "value": "none"
4510+ },
4511+ "secondarycache": {
4512+ "source": "default",
4513+ "value": "all"
4514+ },
4515+ "setuid": {
4516+ "source": "default",
4517+ "value": "on"
4518+ },
4519+ "sharenfs": {
4520+ "source": "default",
4521+ "value": "off"
4522+ },
4523+ "sharesmb": {
4524+ "source": "default",
4525+ "value": "off"
4526+ },
4527+ "snapdev": {
4528+ "source": "default",
4529+ "value": "hidden"
4530+ },
4531+ "snapdir": {
4532+ "source": "default",
4533+ "value": "hidden"
4534+ },
4535+ "snapshot_count": {
4536+ "source": "default",
4537+ "value": "18446744073709551615"
4538+ },
4539+ "snapshot_limit": {
4540+ "source": "default",
4541+ "value": "18446744073709551615"
4542+ },
4543+ "sync": {
4544+ "source": "default",
4545+ "value": "standard"
4546+ },
4547+ "type": {
4548+ "source": "-",
4549+ "value": "filesystem"
4550+ },
4551+ "used": {
4552+ "source": "-",
4553+ "value": "14237662208"
4554+ },
4555+ "usedbychildren": {
4556+ "source": "-",
4557+ "value": "0"
4558+ },
4559+ "usedbydataset": {
4560+ "source": "-",
4561+ "value": "14237662208"
4562+ },
4563+ "usedbyrefreservation": {
4564+ "source": "-",
4565+ "value": "0"
4566+ },
4567+ "usedbysnapshots": {
4568+ "source": "-",
4569+ "value": "0"
4570+ },
4571+ "utf8only": {
4572+ "source": "-",
4573+ "value": "off"
4574+ },
4575+ "version": {
4576+ "source": "-",
4577+ "value": "5"
4578+ },
4579+ "volmode": {
4580+ "source": "default",
4581+ "value": "default"
4582+ },
4583+ "vscan": {
4584+ "source": "default",
4585+ "value": "off"
4586+ },
4587+ "written": {
4588+ "source": "-",
4589+ "value": "14237662208"
4590+ },
4591+ "xattr": {
4592+ "source": "default",
4593+ "value": "on"
4594+ },
4595+ "zoned": {
4596+ "source": "default",
4597+ "value": "off"
4598+ }
4599+ }
4600+ },
4601+ "zfs-lxd/containers/andreas-cosmici386-mothur": {
4602+ "properties": {
4603+ "aclinherit": {
4604+ "source": "default",
4605+ "value": "restricted"
4606+ },
4607+ "acltype": {
4608+ "source": "default",
4609+ "value": "off"
4610+ },
4611+ "atime": {
4612+ "source": "default",
4613+ "value": "on"
4614+ },
4615+ "available": {
4616+ "source": "-",
4617+ "value": "27543762944"
4618+ },
4619+ "canmount": {
4620+ "source": "local",
4621+ "value": "noauto"
4622+ },
4623+ "casesensitivity": {
4624+ "source": "-",
4625+ "value": "sensitive"
4626+ },
4627+ "checksum": {
4628+ "source": "default",
4629+ "value": "on"
4630+ },
4631+ "compression": {
4632+ "source": "inherited from zfs-lxd",
4633+ "value": "on"
4634+ },
4635+ "compressratio": {
4636+ "source": "-",
4637+ "value": "1.88"
4638+ },
4639+ "context": {
4640+ "source": "default",
4641+ "value": "none"
4642+ },
4643+ "copies": {
4644+ "source": "default",
4645+ "value": "1"
4646+ },
4647+ "createtxg": {
4648+ "source": "-",
4649+ "value": "5096275"
4650+ },
4651+ "creation": {
4652+ "source": "-",
4653+ "value": "1553893679"
4654+ },
4655+ "dedup": {
4656+ "source": "default",
4657+ "value": "off"
4658+ },
4659+ "defcontext": {
4660+ "source": "default",
4661+ "value": "none"
4662+ },
4663+ "devices": {
4664+ "source": "default",
4665+ "value": "on"
4666+ },
4667+ "dnodesize": {
4668+ "source": "default",
4669+ "value": "legacy"
4670+ },
4671+ "exec": {
4672+ "source": "default",
4673+ "value": "on"
4674+ },
4675+ "filesystem_count": {
4676+ "source": "default",
4677+ "value": "18446744073709551615"
4678+ },
4679+ "filesystem_limit": {
4680+ "source": "default",
4681+ "value": "18446744073709551615"
4682+ },
4683+ "fscontext": {
4684+ "source": "default",
4685+ "value": "none"
4686+ },
4687+ "guid": {
4688+ "source": "-",
4689+ "value": "6258600806920849973"
4690+ },
4691+ "logbias": {
4692+ "source": "default",
4693+ "value": "latency"
4694+ },
4695+ "logicalreferenced": {
4696+ "source": "-",
4697+ "value": "4612554752"
4698+ },
4699+ "logicalused": {
4700+ "source": "-",
4701+ "value": "3843475456"
4702+ },
4703+ "mlslabel": {
4704+ "source": "default",
4705+ "value": "none"
4706+ },
4707+ "mounted": {
4708+ "source": "-",
4709+ "value": "no"
4710+ },
4711+ "mountpoint": {
4712+ "source": "local",
4713+ "value": "/var/snap/lxd/common/lxd/storage-pools/zfs-lxd/containers/andreas-cosmici386-mothur"
4714+ },
4715+ "nbmand": {
4716+ "source": "default",
4717+ "value": "off"
4718+ },
4719+ "normalization": {
4720+ "source": "-",
4721+ "value": "none"
4722+ },
4723+ "origin": {
4724+ "source": "-",
4725+ "value": "zfs-lxd/deleted/images/d7d4cfa08c1f19fe6f266befcb8499a6b6f2149b520b35106344be11124398b4@readonly"
4726+ },
4727+ "overlay": {
4728+ "source": "default",
4729+ "value": "off"
4730+ },
4731+ "primarycache": {
4732+ "source": "default",
4733+ "value": "all"
4734+ },
4735+ "quota": {
4736+ "source": "default",
4737+ "value": "0"
4738+ },
4739+ "readonly": {
4740+ "source": "default",
4741+ "value": "off"
4742+ },
4743+ "recordsize": {
4744+ "source": "default",
4745+ "value": "131072"
4746+ },
4747+ "redundant_metadata": {
4748+ "source": "default",
4749+ "value": "all"
4750+ },
4751+ "refcompressratio": {
4752+ "source": "-",
4753+ "value": "1.83"
4754+ },
4755+ "referenced": {
4756+ "source": "-",
4757+ "value": "2525002752"
4758+ },
4759+ "refquota": {
4760+ "source": "default",
4761+ "value": "0"
4762+ },
4763+ "refreservation": {
4764+ "source": "default",
4765+ "value": "0"
4766+ },
4767+ "relatime": {
4768+ "source": "default",
4769+ "value": "off"
4770+ },
4771+ "reservation": {
4772+ "source": "default",
4773+ "value": "0"
4774+ },
4775+ "rootcontext": {
4776+ "source": "default",
4777+ "value": "none"
4778+ },
4779+ "secondarycache": {
4780+ "source": "default",
4781+ "value": "all"
4782+ },
4783+ "setuid": {
4784+ "source": "default",
4785+ "value": "on"
4786+ },
4787+ "sharenfs": {
4788+ "source": "default",
4789+ "value": "off"
4790+ },
4791+ "sharesmb": {
4792+ "source": "default",
4793+ "value": "off"
4794+ },
4795+ "snapdev": {
4796+ "source": "default",
4797+ "value": "hidden"
4798+ },
4799+ "snapdir": {
4800+ "source": "default",
4801+ "value": "hidden"
4802+ },
4803+ "snapshot_count": {
4804+ "source": "default",
4805+ "value": "18446744073709551615"
4806+ },
4807+ "snapshot_limit": {
4808+ "source": "default",
4809+ "value": "18446744073709551615"
4810+ },
4811+ "sync": {
4812+ "source": "default",
4813+ "value": "standard"
4814+ },
4815+ "type": {
4816+ "source": "-",
4817+ "value": "filesystem"
4818+ },
4819+ "used": {
4820+ "source": "-",
4821+ "value": "2051683840"
4822+ },
4823+ "usedbychildren": {
4824+ "source": "-",
4825+ "value": "0"
4826+ },
4827+ "usedbydataset": {
4828+ "source": "-",
4829+ "value": "2051683840"
4830+ },
4831+ "usedbyrefreservation": {
4832+ "source": "-",
4833+ "value": "0"
4834+ },
4835+ "usedbysnapshots": {
4836+ "source": "-",
4837+ "value": "0"
4838+ },
4839+ "utf8only": {
4840+ "source": "-",
4841+ "value": "off"
4842+ },
4843+ "version": {
4844+ "source": "-",
4845+ "value": "5"
4846+ },
4847+ "volmode": {
4848+ "source": "default",
4849+ "value": "default"
4850+ },
4851+ "vscan": {
4852+ "source": "default",
4853+ "value": "off"
4854+ },
4855+ "written": {
4856+ "source": "-",
4857+ "value": "2051683840"
4858+ },
4859+ "xattr": {
4860+ "source": "default",
4861+ "value": "on"
4862+ },
4863+ "zoned": {
4864+ "source": "default",
4865+ "value": "off"
4866+ }
4867+ }
4868+ },
4869+ "zfs-lxd/containers/bionic-proposed-1563111558": {
4870+ "properties": {
4871+ "aclinherit": {
4872+ "source": "default",
4873+ "value": "restricted"
4874+ },
4875+ "acltype": {
4876+ "source": "default",
4877+ "value": "off"
4878+ },
4879+ "atime": {
4880+ "source": "default",
4881+ "value": "on"
4882+ },
4883+ "available": {
4884+ "source": "-",
4885+ "value": "27543762944"
4886+ },
4887+ "canmount": {
4888+ "source": "local",
4889+ "value": "noauto"
4890+ },
4891+ "casesensitivity": {
4892+ "source": "-",
4893+ "value": "sensitive"
4894+ },
4895+ "checksum": {
4896+ "source": "default",
4897+ "value": "on"
4898+ },
4899+ "compression": {
4900+ "source": "inherited from zfs-lxd",
4901+ "value": "on"
4902+ },
4903+ "compressratio": {
4904+ "source": "-",
4905+ "value": "1.00"
4906+ },
4907+ "context": {
4908+ "source": "default",
4909+ "value": "none"
4910+ },
4911+ "copies": {
4912+ "source": "default",
4913+ "value": "1"
4914+ },
4915+ "createtxg": {
4916+ "source": "-",
4917+ "value": "4347914"
4918+ },
4919+ "creation": {
4920+ "source": "-",
4921+ "value": "1551202367"
4922+ },
4923+ "dedup": {
4924+ "source": "default",
4925+ "value": "off"
4926+ },
4927+ "defcontext": {
4928+ "source": "default",
4929+ "value": "none"
4930+ },
4931+ "devices": {
4932+ "source": "default",
4933+ "value": "on"
4934+ },
4935+ "dnodesize": {
4936+ "source": "default",
4937+ "value": "legacy"
4938+ },
4939+ "exec": {
4940+ "source": "default",
4941+ "value": "on"
4942+ },
4943+ "filesystem_count": {
4944+ "source": "default",
4945+ "value": "18446744073709551615"
4946+ },
4947+ "filesystem_limit": {
4948+ "source": "default",
4949+ "value": "18446744073709551615"
4950+ },
4951+ "fscontext": {
4952+ "source": "default",
4953+ "value": "none"
4954+ },
4955+ "guid": {
4956+ "source": "-",
4957+ "value": "9613689284689146091"
4958+ },
4959+ "logbias": {
4960+ "source": "default",
4961+ "value": "latency"
4962+ },
4963+ "logicalreferenced": {
4964+ "source": "-",
4965+ "value": "678938624"
4966+ },
4967+ "logicalused": {
4968+ "source": "-",
4969+ "value": "2898432"
4970+ },
4971+ "mlslabel": {
4972+ "source": "default",
4973+ "value": "none"
4974+ },
4975+ "mounted": {
4976+ "source": "-",
4977+ "value": "no"
4978+ },
4979+ "mountpoint": {
4980+ "source": "local",
4981+ "value": "/var/snap/lxd/common/lxd/storage-pools/zfs-lxd/containers/bionic-proposed-1563111558"
4982+ },
4983+ "nbmand": {
4984+ "source": "default",
4985+ "value": "off"
4986+ },
4987+ "normalization": {
4988+ "source": "-",
4989+ "value": "none"
4990+ },
4991+ "origin": {
4992+ "source": "-",
4993+ "value": "zfs-lxd/deleted/images/e195799c04654a382216bd3b138a099226aac00b092d864e0b9fc4785e9aec62@readonly"
4994+ },
4995+ "overlay": {
4996+ "source": "default",
4997+ "value": "off"
4998+ },
4999+ "primarycache": {
5000+ "source": "default",
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches