From e6ace190e3538616a2417dfc1390dbd12ae47214 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Fri, 10 May 2019 13:24:25 +1200 Subject: [PATCH 01/23] add existing partitions sample data --- examples/existing-partitions.json | 1782 +++++++++++++++++++++++++++++ examples/simple.json | 697 +++++++++++ 2 files changed, 2479 insertions(+) create mode 100644 examples/existing-partitions.json create mode 100644 examples/simple.json diff --git a/examples/existing-partitions.json b/examples/existing-partitions.json new file mode 100644 index 00000000..6abff1a9 --- /dev/null +++ b/examples/existing-partitions.json @@ -0,0 +1,1782 @@ +{ + "network": { + "links": [ + { + "addresses": [ + { + "address": "127.0.0.1/8", + "family": 2, + "scope": "host", + "source": "static" + }, + { + "address": "::1/128", + "family": 10, + "scope": "host", + "source": "static" + } + ], + "bond": { + "is_master": false, + "is_slave": false, + "lacp_rate": null, + "master": null, + "mode": null, + "slaves": [], + "xmit_hash_policy": null + }, + "bridge": { + "interfaces": [], + "is_bridge": false, + "is_port": false, + "options": {} + }, + "netlink_data": { + "arptype": 772, + "family": 0, + "flags": 65609, + "ifindex": 1, + "is_vlan": false, + "name": "lo" + }, + "type": "lo", + "udev_data": { + "DEVPATH": "/devices/virtual/net/lo", + "ID_MM_CANDIDATE": "1", + "IFINDEX": "1", + "INTERFACE": "lo", + "SUBSYSTEM": "net", + "USEC_INITIALIZED": "16370691", + "attrs": { + "addr_assign_type": "0", + "addr_len": "6", + "address": "00:00:00:00:00:00", + "broadcast": "00:00:00:00:00:00", + "carrier": "1", + "carrier_changes": "0", + "carrier_down_count": "0", + "carrier_up_count": "0", + "dev_id": "0x0", + "dev_port": "0", + "dormant": "0", + "duplex": null, + "flags": "0x9", + "gro_flush_timeout": "0", + "ifalias": "", + "ifindex": "1", + "iflink": "1", + "link_mode": "0", + "mtu": "65536", + "name_assign_type": null, + "netdev_group": "0", + "operstate": "unknown", + "phys_port_id": null, + "phys_port_name": null, + "phys_switch_id": null, + "proto_down": "0", + "speed": null, + "subsystem": "net", + "tx_queue_len": "1000", + "type": "772", + "uevent": "INTERFACE=lo\nIFINDEX=1" + } + } + }, + { + "addresses": [ + { + "address": "10.0.2.15/24", + "family": 2, + "scope": "global", + "source": "dhcp" + }, + { + "address": "fec0::5054:ff:fe12:3456/64", + "family": 10, + "scope": "site", + "source": "dhcp" + }, + { + "address": "fe80::5054:ff:fe12:3456/64", + "family": 10, + "scope": "link", + "source": "static" + } + ], + "bond": { + "is_master": false, + "is_slave": false, + "lacp_rate": null, + "master": null, + "mode": null, + "slaves": [], + "xmit_hash_policy": null + }, + "bridge": { + "interfaces": [], + "is_bridge": false, + "is_port": false, + "options": {} + }, + "netlink_data": { + "arptype": 1, + "family": 0, + "flags": 69699, + "ifindex": 2, + "is_vlan": false, + "name": "ens3" + }, + "type": "eth", + "udev_data": { + "DEVPATH": "/devices/pci0000:00/0000:00:03.0/net/ens3", + "ID_BUS": "pci", + "ID_MM_CANDIDATE": "1", + "ID_MODEL_FROM_DATABASE": "82540EM Gigabit Ethernet Controller (QEMU Virtual Machine)", + "ID_MODEL_ID": "0x100e", + "ID_NET_NAME_MAC": "enx525400123456", + "ID_NET_NAME_PATH": "enp0s3", + "ID_NET_NAME_SLOT": "ens3", + "ID_NET_NAMING_SCHEME": "v240", + "ID_PATH": "pci-0000:00:03.0", + "ID_PATH_TAG": "pci-0000_00_03_0", + "ID_PCI_CLASS_FROM_DATABASE": "Network controller", + "ID_PCI_SUBCLASS_FROM_DATABASE": "Ethernet controller", + "ID_VENDOR_FROM_DATABASE": "Intel Corporation", + "ID_VENDOR_ID": "0x8086", + "IFINDEX": "2", + "INTERFACE": "ens3", + "SUBSYSTEM": "net", + "SYSTEMD_ALIAS": "/sys/subsystem/net/devices/ens3", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8818147", + "attrs": { + "addr_assign_type": "0", + "addr_len": "6", + "address": "52:54:00:12:34:56", + "broadcast": "ff:ff:ff:ff:ff:ff", + "carrier": "1", + "carrier_changes": "2", + "carrier_down_count": "1", + "carrier_up_count": "1", + "dev_id": "0x0", + "dev_port": "0", + "device": null, + "dormant": "0", + "duplex": "full", + "flags": "0x1003", + "gro_flush_timeout": "0", + "ifalias": "", + "ifindex": "2", + "iflink": "2", + "link_mode": "0", + "mtu": "1500", + "name_assign_type": "4", + "netdev_group": "0", + "operstate": "up", + "phys_port_id": null, + "phys_port_name": null, + "phys_switch_id": null, + "proto_down": "0", + "speed": "1000", + "subsystem": "net", + "tx_queue_len": "1000", + "type": "1", + "uevent": "INTERFACE=ens3\nIFINDEX=2" + } + } + } + ], + "routes": [ + { + "dst": "default", + "family": 2, + "ifindex": 2, + "table": 254, + "type": 1 + }, + { + "dst": "10.0.2.0/24", + "family": 2, + "ifindex": 2, + "table": 254, + "type": 1 + }, + { + "dst": "10.0.2.2", + "family": 2, + "ifindex": 2, + "table": 254, + "type": 1 + }, + { + "dst": "10.0.2.0", + "family": 2, + "ifindex": 2, + "table": 255, + "type": 3 + }, + { + "dst": "10.0.2.15", + "family": 2, + "ifindex": 2, + "table": 255, + "type": 2 + }, + { + "dst": "10.0.2.255", + "family": 2, + "ifindex": 2, + "table": 255, + "type": 3 + }, + { + "dst": "127.0.0.0", + "family": 2, + "ifindex": 1, + "table": 255, + "type": 3 + }, + { + "dst": "127.0.0.0/8", + "family": 2, + "ifindex": 1, + "table": 255, + "type": 2 + }, + { + "dst": "127.0.0.1", + "family": 2, + "ifindex": 1, + "table": 255, + "type": 2 + }, + { + "dst": "127.255.255.255", + "family": 2, + "ifindex": 1, + "table": 255, + "type": 3 + }, + { + "dst": "::1", + "family": 10, + "ifindex": 1, + "table": 254, + "type": 1 + }, + { + "dst": "fe80::/64", + "family": 10, + "ifindex": 2, + "table": 254, + "type": 1 + }, + { + "dst": "fec0::/64", + "family": 10, + "ifindex": 2, + "table": 254, + "type": 1 + }, + { + "dst": "default", + "family": 10, + "ifindex": 2, + "table": 254, + "type": 1 + }, + { + "dst": "::1", + "family": 10, + "ifindex": 1, + "table": 255, + "type": 2 + }, + { + "dst": "fe80::5054:ff:fe12:3456", + "family": 10, + "ifindex": 2, + "table": 255, + "type": 2 + }, + { + "dst": "fec0::5054:ff:fe12:3456", + "family": 10, + "ifindex": 2, + "table": 255, + "type": 2 + }, + { + "dst": "ff00::/8", + "family": 10, + "ifindex": 2, + "table": 255, + "type": 1 + } + ] + }, + "storage": { + "bcache": { + "backing": {}, + "caching": {} + }, + "blockdev": { + "/dev/dm-0": { + "DEVLINKS": "/dev/disk/by-uuid/6a13a61c-51d5-46b8-bb97-02341f79e003 /dev/disk/by-id/dm-uuid-LVM-wdKuTVOtDbjf6qLyGvJZxcswOQtrFv5uhgqyCLzgSRGW6MDO6mLypSTUGNeBAARK /dev/amazing-vg/my-lv1 /dev/disk/by-id/dm-name-amazing--vg-my--lv1 /dev/mapper/amazing--vg-my--lv1 /dev/disk/by-label/lv", + "DEVNAME": "/dev/dm-0", + "DEVPATH": "/devices/virtual/block/dm-0", + "DEVTYPE": "disk", + "DM_LV_NAME": "my-lv1", + "DM_NAME": "amazing--vg-my--lv1", + "DM_STATE": "ACTIVE", + "DM_SUSPENDED": "0", + "DM_TABLE_STATE": "LIVE", + "DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG": "1", + "DM_UDEV_PRIMARY_SOURCE_FLAG": "1", + "DM_UDEV_RULES": "1", + "DM_UDEV_RULES_VSN": "2", + "DM_UUID": "LVM-wdKuTVOtDbjf6qLyGvJZxcswOQtrFv5uhgqyCLzgSRGW6MDO6mLypSTUGNeBAARK", + "DM_VG_NAME": "amazing-vg", + "ID_FS_LABEL": "lv", + "ID_FS_LABEL_ENC": "lv", + "ID_FS_TYPE": "ext4", + "ID_FS_USAGE": "filesystem", + "ID_FS_UUID": "6a13a61c-51d5-46b8-bb97-02341f79e003", + "ID_FS_UUID_ENC": "6a13a61c-51d5-46b8-bb97-02341f79e003", + "ID_FS_VERSION": "1.0", + "MAJOR": "253", + "MINOR": "0", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "17674934", + "attrs": { + "alignment_offset": "0", + "bdi": null, + "capability": "10", + "dev": "253:0", + "discard_alignment": "0", + "ext_range": "1", + "hidden": "0", + "inflight": " 0 0", + "range": "1", + "removable": "0", + "ro": "0", + "size": "5364514816", + "stat": " 200 0 5808 4 0 0 0 0 0 88 4 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=253\nMINOR=0\nDEVNAME=dm-0\nDEVTYPE=disk" + } + }, + "/dev/fd0": { + "DEVNAME": "/dev/fd0", + "DEVPATH": "/devices/platform/floppy.0/block/fd0", + "DEVTYPE": "disk", + "MAJOR": "2", + "MINOR": "0", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8362401", + "attrs": { + "alignment_offset": "0", + "bdi": null, + "capability": "11", + "dev": "2:0", + "device": null, + "discard_alignment": "0", + "events": "", + "events_async": "", + "events_poll_msecs": "-1", + "ext_range": "1", + "hidden": "0", + "inflight": " 0 0", + "range": "1", + "removable": "1", + "ro": "0", + "size": "4096", + "stat": " 2 0 16 116 0 0 0 0 0 16 112 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=2\nMINOR=0\nDEVNAME=fd0\nDEVTYPE=disk" + } + }, + "/dev/md127": { + "DEVLINKS": "/dev/md/ringil:foobar /dev/disk/by-id/md-name-ringil:foobar /dev/disk/by-id/md-uuid-26d43bb7:2b9bb08e:6912462a:d6572672 /dev/disk/by-label/data /dev/disk/by-uuid/f59e9a4e-2ffd-4746-8f3c-1a6fd3556ba4", + "DEVNAME": "/dev/md127", + "DEVPATH": "/devices/virtual/block/md127", + "DEVTYPE": "disk", + "ID_FS_LABEL": "data", + "ID_FS_LABEL_ENC": "data", + "ID_FS_TYPE": "ext4", + "ID_FS_USAGE": "filesystem", + "ID_FS_UUID": "f59e9a4e-2ffd-4746-8f3c-1a6fd3556ba4", + "ID_FS_UUID_ENC": "f59e9a4e-2ffd-4746-8f3c-1a6fd3556ba4", + "ID_FS_VERSION": "1.0", + "MAJOR": "9", + "MD_DEVICES": "2", + "MD_DEVICE_ev_vdc1_DEV": "/dev/vdc1", + "MD_DEVICE_ev_vdc1_ROLE": "0", + "MD_DEVICE_ev_vdd1_DEV": "/dev/vdd1", + "MD_DEVICE_ev_vdd1_ROLE": "1", + "MD_DEVNAME": "ringil:foobar", + "MD_LEVEL": "raid1", + "MD_METADATA": "1.2", + "MD_NAME": "ringil:foobar", + "MD_UUID": "26d43bb7:2b9bb08e:6912462a:d6572672", + "MINOR": "127", + "SUBSYSTEM": "block", + "SYSTEMD_WANTS": "mdmonitor.service", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8488818", + "attrs": { + "alignment_offset": "0", + "bdi": null, + "capability": "50", + "dev": "9:127", + "discard_alignment": "0", + "ext_range": "256", + "hidden": "0", + "inflight": " 0 0", + "range": "1", + "removable": "0", + "ro": "0", + "size": "10725883904", + "stat": " 322 0 10080 0 0 0 0 0 0 0 0 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=9\nMINOR=127\nDEVNAME=md127\nDEVTYPE=disk" + } + }, + "/dev/sr0": { + "DEVLINKS": "/dev/disk/by-id/scsi-0QEMU_QEMU_DVD-ROM_QM00003 /dev/disk/by-path/pci-0000:00:01.1-ata-2 /dev/cdrom /dev/dvd /dev/disk/by-id/ata-QEMU_DVD-ROM_QM00003 /dev/disk/by-id/scsi-1ATA_QEMU_DVD-ROM_QM00003", + "DEVNAME": "/dev/sr0", + "DEVPATH": "/devices/pci0000:00/0000:00:01.1/ata2/host1/target1:0:0/1:0:0:0/block/sr0", + "DEVTYPE": "disk", + "ID_ATA": "1", + "ID_BUS": "ata", + "ID_CDROM": "1", + "ID_CDROM_DVD": "1", + "ID_CDROM_MRW": "1", + "ID_CDROM_MRW_W": "1", + "ID_FOR_SEAT": "block-pci-0000_00_01_1-ata-2", + "ID_MODEL": "QEMU_DVD-ROM", + "ID_MODEL_ENC": "QEMU\\x20DVD-ROM\\x20\\x20\\x20\\x20", + "ID_PATH": "pci-0000:00:01.1-ata-2", + "ID_PATH_TAG": "pci-0000_00_01_1-ata-2", + "ID_REVISION": "2.5+", + "ID_SCSI": "1", + "ID_SCSI_DI": "1", + "ID_SERIAL": "QEMU_DVD-ROM_QM00003", + "ID_TYPE": "cd/dvd", + "ID_VENDOR": "QEMU", + "ID_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20", + "MAJOR": "11", + "MINOR": "0", + "SCSI_IDENT_LUN_ATA": "QEMU_DVD-ROM_QM00003", + "SCSI_IDENT_LUN_T10": "ATA_QEMU_DVD-ROM_QM00003", + "SCSI_IDENT_LUN_VENDOR": "QM00003", + "SCSI_MODEL": "QEMU_DVD-ROM", + "SCSI_MODEL_ENC": "QEMU\\x20DVD-ROM\\x20\\x20\\x20\\x20", + "SCSI_REVISION": "2.5+", + "SCSI_TPGS": "0", + "SCSI_TYPE": "cd/dvd", + "SCSI_VENDOR": "QEMU", + "SCSI_VENDOR_ENC": "QEMU\\x20\\x20\\x20\\x20", + "SUBSYSTEM": "block", + "SYSTEMD_MOUNT_DEVICE_BOUND": "1", + "TAGS": ":seat:systemd:uaccess:", + "USEC_INITIALIZED": "8465753", + "attrs": { + "alignment_offset": "0", + "bdi": null, + "capability": "119", + "dev": "11:0", + "device": null, + "discard_alignment": "0", + "events": "media_change eject_request", + "events_async": "", + "events_poll_msecs": "-1", + "ext_range": "1", + "hidden": "0", + "inflight": " 0 0", + "range": "1", + "removable": "1", + "ro": "0", + "size": "1073741312", + "stat": " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=11\nMINOR=0\nDEVNAME=sr0\nDEVTYPE=disk" + } + }, + "/dev/vda": { + "DEVLINKS": "/dev/disk/by-label/Ubuntu\\x20custom\\x20amd64 /dev/disk/by-uuid/2019-05-23-03-04-53-00 /dev/disk/by-path/pci-0000:00:04.0 /dev/disk/by-path/virtio-pci-0000:00:04.0", + "DEVNAME": "/dev/vda", + "DEVPATH": "/devices/pci0000:00/0000:00:04.0/virtio0/block/vda", + "DEVTYPE": "disk", + "ID_FS_BOOT_SYSTEM_ID": "EL\\x20TORITO\\x20SPECIFICATION", + "ID_FS_LABEL": "Ubuntu_custom_amd64", + "ID_FS_LABEL_ENC": "Ubuntu\\x20custom\\x20amd64", + "ID_FS_TYPE": "iso9660", + "ID_FS_USAGE": "filesystem", + "ID_FS_UUID": "2019-05-23-03-04-53-00", + "ID_FS_UUID_ENC": "2019-05-23-03-04-53-00", + "ID_FS_VERSION": "Joliet Extension", + "ID_PART_TABLE_TYPE": "dos", + "ID_PART_TABLE_UUID": "013b97f5", + "ID_PATH": "pci-0000:00:04.0", + "ID_PATH_TAG": "pci-0000_00_04_0", + "MAJOR": "252", + "MINOR": "0", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8389241", + "attrs": { + "alignment_offset": "0", + "bdi": null, + "cache_type": "write back", + "capability": "50", + "dev": "252:0", + "device": null, + "discard_alignment": "0", + "ext_range": "256", + "hidden": "0", + "inflight": " 0 0", + "range": "16", + "removable": "0", + "ro": "0", + "serial": "", + "size": "786432000", + "stat": " 3825 0 454630 16549 0 0 0 0 0 5764 14960 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=252\nMINOR=0\nDEVNAME=vda\nDEVTYPE=disk" + }, + "partitiontable": { + "device": "/dev/vda", + "id": "0x013b97f5", + "label": "dos", + "partitions": [ + { + "bootable": true, + "node": "/dev/vda1", + "size": 1536000, + "start": 0, + "type": "0" + }, + { + "node": "/dev/vda2", + "size": 7488, + "start": 996, + "type": "ef" + } + ], + "unit": "sectors" + } + }, + "/dev/vda1": { + "DEVLINKS": "/dev/disk/by-label/Ubuntu\\x20custom\\x20amd64 /dev/disk/by-uuid/2019-05-23-03-04-53-00 /dev/disk/by-path/virtio-pci-0000:00:04.0-part1 /dev/disk/by-path/pci-0000:00:04.0-part1 /dev/disk/by-partuuid/013b97f5-01", + "DEVNAME": "/dev/vda1", + "DEVPATH": "/devices/pci0000:00/0000:00:04.0/virtio0/block/vda/vda1", + "DEVTYPE": "partition", + "ID_FS_BOOT_SYSTEM_ID": "EL\\x20TORITO\\x20SPECIFICATION", + "ID_FS_LABEL": "Ubuntu_custom_amd64", + "ID_FS_LABEL_ENC": "Ubuntu\\x20custom\\x20amd64", + "ID_FS_TYPE": "iso9660", + "ID_FS_USAGE": "filesystem", + "ID_FS_UUID": "2019-05-23-03-04-53-00", + "ID_FS_UUID_ENC": "2019-05-23-03-04-53-00", + "ID_FS_VERSION": "Joliet Extension", + "ID_PART_ENTRY_DISK": "252:0", + "ID_PART_ENTRY_FLAGS": "0x80", + "ID_PART_ENTRY_NUMBER": "1", + "ID_PART_ENTRY_OFFSET": "0", + "ID_PART_ENTRY_SCHEME": "dos", + "ID_PART_ENTRY_SIZE": "1536000", + "ID_PART_ENTRY_TYPE": "0x0", + "ID_PART_ENTRY_UUID": "013b97f5-01", + "ID_PART_TABLE_TYPE": "dos", + "ID_PART_TABLE_UUID": "013b97f5", + "ID_PATH": "pci-0000:00:04.0", + "ID_PATH_TAG": "pci-0000_00_04_0", + "ID_SCSI": "1", + "MAJOR": "252", + "MINOR": "1", + "PARTN": "1", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8400805", + "attrs": { + "alignment_offset": "0", + "dev": "252:1", + "discard_alignment": "0", + "inflight": " 0 0", + "partition": "1", + "ro": "0", + "size": "786432000", + "start": "0", + "stat": " 3824 0 454622 16548 0 0 0 0 0 5760 14960 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=252\nMINOR=1\nDEVNAME=vda1\nDEVTYPE=partition\nPARTN=1" + }, + "partitiontable": { + "device": "/dev/vda1", + "id": "0x013b97f5", + "label": "dos", + "partitions": [ + { + "bootable": true, + "node": "/dev/vda1p1", + "size": 1536000, + "start": 0, + "type": "0" + }, + { + "node": "/dev/vda1p2", + "size": 7488, + "start": 996, + "type": "ef" + } + ], + "unit": "sectors" + } + }, + "/dev/vda2": { + "DEVLINKS": "/dev/disk/by-uuid/039E-EF17 /dev/disk/by-path/virtio-pci-0000:00:04.0-part2 /dev/disk/by-partuuid/013b97f5-02 /dev/disk/by-label/Ubuntu\\x20custom\\x20amd64 /dev/disk/by-path/pci-0000:00:04.0-part2", + "DEVNAME": "/dev/vda2", + "DEVPATH": "/devices/pci0000:00/0000:00:04.0/virtio0/block/vda/vda2", + "DEVTYPE": "partition", + "ID_FS_BOOT_SYSTEM_ID": "EL\\x20TORITO\\x20SPECIFICATION", + "ID_FS_LABEL": "Ubuntu_custom_amd64", + "ID_FS_LABEL_ENC": "Ubuntu\\x20custom\\x20amd64", + "ID_FS_TYPE": "vfat", + "ID_FS_USAGE": "filesystem", + "ID_FS_UUID": "039E-EF17", + "ID_FS_UUID_ENC": "039E-EF17", + "ID_FS_VERSION": "FAT12", + "ID_PART_ENTRY_DISK": "252:0", + "ID_PART_ENTRY_NUMBER": "2", + "ID_PART_ENTRY_OFFSET": "996", + "ID_PART_ENTRY_SCHEME": "dos", + "ID_PART_ENTRY_SIZE": "7488", + "ID_PART_ENTRY_TYPE": "0xef", + "ID_PART_ENTRY_UUID": "013b97f5-02", + "ID_PART_TABLE_TYPE": "dos", + "ID_PART_TABLE_UUID": "013b97f5", + "ID_PATH": "pci-0000:00:04.0", + "ID_PATH_TAG": "pci-0000_00_04_0", + "ID_SCSI": "1", + "MAJOR": "252", + "MINOR": "2", + "PARTN": "2", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8394933", + "attrs": { + "alignment_offset": "0", + "dev": "252:2", + "discard_alignment": "0", + "inflight": " 0 0", + "partition": "2", + "ro": "0", + "size": "3833856", + "start": "996", + "stat": " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=252\nMINOR=2\nDEVNAME=vda2\nDEVTYPE=partition\nPARTN=2" + }, + "partitiontable": { + "device": "/dev/vda2", + "grain": "512", + "id": "0x00000000", + "label": "dos", + "partitions": [], + "unit": "sectors" + } + }, + "/dev/vdb": { + "DEVLINKS": "/dev/disk/by-path/pci-0000:00:05.0 /dev/disk/by-path/virtio-pci-0000:00:05.0 /dev/disk/by-id/virtio-serial1", + "DEVNAME": "/dev/vdb", + "DEVPATH": "/devices/pci0000:00/0000:00:05.0/virtio1/block/vdb", + "DEVTYPE": "disk", + "ID_PART_TABLE_TYPE": "gpt", + "ID_PART_TABLE_UUID": "69d0da07-9bea-4aab-a876-219fc2fb6495", + "ID_PATH": "pci-0000:00:05.0", + "ID_PATH_TAG": "pci-0000_00_05_0", + "ID_SERIAL": "serial1", + "MAJOR": "252", + "MINOR": "16", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8420525", + "attrs": { + "alignment_offset": "0", + "bdi": null, + "cache_type": "write back", + "capability": "50", + "dev": "252:16", + "device": null, + "discard_alignment": "0", + "ext_range": "256", + "hidden": "0", + "inflight": " 0 0", + "range": "16", + "removable": "0", + "ro": "0", + "serial": "serial1", + "size": "10737418240", + "stat": " 1328 0 47798 252 0 0 0 0 0 464 128 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=252\nMINOR=16\nDEVNAME=vdb\nDEVTYPE=disk" + }, + "partitiontable": { + "device": "/dev/vdb", + "firstlba": 34, + "id": "69D0DA07-9BEA-4AAB-A876-219FC2FB6495", + "label": "gpt", + "lastlba": 20971486, + "partitions": [ + { + "name": "primary", + "node": "/dev/vdb1", + "size": 2048, + "start": 2048, + "type": "21686148-6449-6E6F-744E-656564454649", + "uuid": "0933DFC4-B5DB-42DA-802C-A40336E73664" + }, + { + "name": "primary", + "node": "/dev/vdb2", + "size": 1048576, + "start": 4096, + "type": "C12A7328-F81F-11D2-BA4B-00A0C93EC93B", + "uuid": "6C831554-0AEF-4A9A-BC46-4DFB1B23A73C" + }, + { + "name": "primary", + "node": "/dev/vdb3", + "size": 16384, + "start": 1052672, + "type": "9E1A2D38-C612-4316-AA26-8B49521E5A8B", + "uuid": "FFFA85B8-D2A4-45D0-BDB5-19BEE357BC3A" + }, + { + "name": "primary", + "node": "/dev/vdb4", + "size": 1028096, + "start": 1069056, + "type": "0657FD6D-A4AB-43C4-84E5-0933C84B4F4F", + "uuid": "B7A3FA62-DE81-45BF-AE8A-63A6BCE26D75" + }, + { + "name": "primary", + "node": "/dev/vdb5", + "size": 8388608, + "start": 2097152, + "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4", + "uuid": "46DC3AEE-F530-4820-8202-2E42B29CF2C7" + }, + { + "name": "primary", + "node": "/dev/vdb6", + "size": 10483713, + "start": 10485760, + "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4", + "uuid": "05B1C69C-5B00-4D35-85ED-61812EC572F5" + } + ], + "unit": "sectors" + } + }, + "/dev/vdb1": { + "DEVLINKS": "/dev/disk/by-partuuid/0933dfc4-b5db-42da-802c-a40336e73664 /dev/disk/by-partlabel/primary /dev/disk/by-path/virtio-pci-0000:00:05.0-part1 /dev/disk/by-id/virtio-serial1-part1 /dev/disk/by-path/pci-0000:00:05.0-part1", + "DEVNAME": "/dev/vdb1", + "DEVPATH": "/devices/pci0000:00/0000:00:05.0/virtio1/block/vdb/vdb1", + "DEVTYPE": "partition", + "ID_PART_ENTRY_DISK": "252:16", + "ID_PART_ENTRY_NAME": "primary", + "ID_PART_ENTRY_NUMBER": "1", + "ID_PART_ENTRY_OFFSET": "2048", + "ID_PART_ENTRY_SCHEME": "gpt", + "ID_PART_ENTRY_SIZE": "2048", + "ID_PART_ENTRY_TYPE": "21686148-6449-6e6f-744e-656564454649", + "ID_PART_ENTRY_UUID": "0933dfc4-b5db-42da-802c-a40336e73664", + "ID_PART_TABLE_TYPE": "gpt", + "ID_PART_TABLE_UUID": "69d0da07-9bea-4aab-a876-219fc2fb6495", + "ID_PATH": "pci-0000:00:05.0", + "ID_PATH_TAG": "pci-0000_00_05_0", + "ID_SCSI": "1", + "ID_SERIAL": "serial1", + "MAJOR": "252", + "MINOR": "17", + "PARTN": "1", + "PARTNAME": "primary", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8468969", + "attrs": { + "alignment_offset": "0", + "dev": "252:17", + "discard_alignment": "0", + "inflight": " 0 0", + "partition": "1", + "ro": "0", + "size": "1048576", + "start": "2048", + "stat": " 134 0 1072 10 0 0 0 0 0 144 0 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=252\nMINOR=17\nDEVNAME=vdb1\nDEVTYPE=partition\nPARTN=1\nPARTNAME=primary" + } + }, + "/dev/vdb2": { + "DEVLINKS": "/dev/disk/by-uuid/6A43-2198 /dev/disk/by-partlabel/primary /dev/disk/by-path/virtio-pci-0000:00:05.0-part2 /dev/disk/by-partuuid/6c831554-0aef-4a9a-bc46-4dfb1b23a73c /dev/disk/by-id/virtio-serial1-part2 /dev/disk/by-path/pci-0000:00:05.0-part2", + "DEVNAME": "/dev/vdb2", + "DEVPATH": "/devices/pci0000:00/0000:00:05.0/virtio1/block/vdb/vdb2", + "DEVTYPE": "partition", + "ID_FS_TYPE": "vfat", + "ID_FS_USAGE": "filesystem", + "ID_FS_UUID": "6A43-2198", + "ID_FS_UUID_ENC": "6A43-2198", + "ID_FS_VERSION": "FAT32", + "ID_PART_ENTRY_DISK": "252:16", + "ID_PART_ENTRY_NAME": "primary", + "ID_PART_ENTRY_NUMBER": "2", + "ID_PART_ENTRY_OFFSET": "4096", + "ID_PART_ENTRY_SCHEME": "gpt", + "ID_PART_ENTRY_SIZE": "1048576", + "ID_PART_ENTRY_TYPE": "c12a7328-f81f-11d2-ba4b-00a0c93ec93b", + "ID_PART_ENTRY_UUID": "6c831554-0aef-4a9a-bc46-4dfb1b23a73c", + "ID_PART_TABLE_TYPE": "gpt", + "ID_PART_TABLE_UUID": "69d0da07-9bea-4aab-a876-219fc2fb6495", + "ID_PATH": "pci-0000:00:05.0", + "ID_PATH_TAG": "pci-0000_00_05_0", + "ID_SCSI": "1", + "ID_SERIAL": "serial1", + "MAJOR": "252", + "MINOR": "18", + "PARTN": "2", + "PARTNAME": "primary", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8441263", + "attrs": { + "alignment_offset": "0", + "dev": "252:18", + "discard_alignment": "0", + "inflight": " 0 0", + "partition": "2", + "ro": "0", + "size": "536870912", + "start": "4096", + "stat": " 170 0 8752 12 0 0 0 0 0 144 0 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=252\nMINOR=18\nDEVNAME=vdb2\nDEVTYPE=partition\nPARTN=2\nPARTNAME=primary" + }, + "partitiontable": { + "device": "/dev/vdb2", + "id": "0x00000000", + "label": "dos", + "partitions": [], + "unit": "sectors" + } + }, + "/dev/vdb3": { + "DEVLINKS": "/dev/disk/by-partlabel/primary /dev/disk/by-partuuid/fffa85b8-d2a4-45d0-bdb5-19bee357bc3a /dev/disk/by-id/virtio-serial1-part3 /dev/disk/by-path/virtio-pci-0000:00:05.0-part3 /dev/disk/by-path/pci-0000:00:05.0-part3", + "DEVNAME": "/dev/vdb3", + "DEVPATH": "/devices/pci0000:00/0000:00:05.0/virtio1/block/vdb/vdb3", + "DEVTYPE": "partition", + "ID_PART_ENTRY_DISK": "252:16", + "ID_PART_ENTRY_NAME": "primary", + "ID_PART_ENTRY_NUMBER": "3", + "ID_PART_ENTRY_OFFSET": "1052672", + "ID_PART_ENTRY_SCHEME": "gpt", + "ID_PART_ENTRY_SIZE": "16384", + "ID_PART_ENTRY_TYPE": "9e1a2d38-c612-4316-aa26-8b49521e5a8b", + "ID_PART_ENTRY_UUID": "fffa85b8-d2a4-45d0-bdb5-19bee357bc3a", + "ID_PART_TABLE_TYPE": "gpt", + "ID_PART_TABLE_UUID": "69d0da07-9bea-4aab-a876-219fc2fb6495", + "ID_PATH": "pci-0000:00:05.0", + "ID_PATH_TAG": "pci-0000_00_05_0", + "ID_SCSI": "1", + "ID_SERIAL": "serial1", + "MAJOR": "252", + "MINOR": "19", + "PARTN": "3", + "PARTNAME": "primary", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8467979", + "attrs": { + "alignment_offset": "0", + "dev": "252:19", + "discard_alignment": "0", + "inflight": " 0 0", + "partition": "3", + "ro": "0", + "size": "8388608", + "start": "1052672", + "stat": " 230 0 1840 16 0 0 0 0 0 172 0 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=252\nMINOR=19\nDEVNAME=vdb3\nDEVTYPE=partition\nPARTN=3\nPARTNAME=primary" + } + }, + "/dev/vdb4": { + "DEVLINKS": "/dev/disk/by-partlabel/primary /dev/disk/by-partuuid/b7a3fa62-de81-45bf-ae8a-63a6bce26d75 /dev/disk/by-uuid/adc9a936-80b3-4988-b2b2-57f0b5eaf169 /dev/disk/by-path/pci-0000:00:05.0-part4 /dev/disk/by-id/virtio-serial1-part4 /dev/disk/by-path/virtio-pci-0000:00:05.0-part4", + "DEVNAME": "/dev/vdb4", + "DEVPATH": "/devices/pci0000:00/0000:00:05.0/virtio1/block/vdb/vdb4", + "DEVTYPE": "partition", + "ID_FS_TYPE": "swap", + "ID_FS_USAGE": "other", + "ID_FS_UUID": "adc9a936-80b3-4988-b2b2-57f0b5eaf169", + "ID_FS_UUID_ENC": "adc9a936-80b3-4988-b2b2-57f0b5eaf169", + "ID_FS_VERSION": "1", + "ID_PART_ENTRY_DISK": "252:16", + "ID_PART_ENTRY_NAME": "primary", + "ID_PART_ENTRY_NUMBER": "4", + "ID_PART_ENTRY_OFFSET": "1069056", + "ID_PART_ENTRY_SCHEME": "gpt", + "ID_PART_ENTRY_SIZE": "1028096", + "ID_PART_ENTRY_TYPE": "0657fd6d-a4ab-43c4-84e5-0933c84b4f4f", + "ID_PART_ENTRY_UUID": "b7a3fa62-de81-45bf-ae8a-63a6bce26d75", + "ID_PART_TABLE_TYPE": "gpt", + "ID_PART_TABLE_UUID": "69d0da07-9bea-4aab-a876-219fc2fb6495", + "ID_PATH": "pci-0000:00:05.0", + "ID_PATH_TAG": "pci-0000_00_05_0", + "ID_SCSI": "1", + "ID_SERIAL": "serial1", + "MAJOR": "252", + "MINOR": "20", + "PARTN": "4", + "PARTNAME": "primary", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8424763", + "attrs": { + "alignment_offset": "0", + "dev": "252:20", + "discard_alignment": "0", + "inflight": " 0 0", + "partition": "4", + "ro": "0", + "size": "526385152", + "start": "1069056", + "stat": " 188 0 8928 13 0 0 0 0 0 80 0 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=252\nMINOR=20\nDEVNAME=vdb4\nDEVTYPE=partition\nPARTN=4\nPARTNAME=primary" + } + }, + "/dev/vdb5": { + "DEVLINKS": "/dev/disk/by-path/virtio-pci-0000:00:05.0-part5 /dev/disk/by-id/virtio-serial1-part5 /dev/disk/by-partlabel/primary /dev/disk/by-label/root /dev/disk/by-path/pci-0000:00:05.0-part5 /dev/disk/by-partuuid/46dc3aee-f530-4820-8202-2e42b29cf2c7 /dev/disk/by-uuid/70115965-56dd-4de3-bdb2-8ecdb9a5c715", + "DEVNAME": "/dev/vdb5", + "DEVPATH": "/devices/pci0000:00/0000:00:05.0/virtio1/block/vdb/vdb5", + "DEVTYPE": "partition", + "ID_FS_LABEL": "root", + "ID_FS_LABEL_ENC": "root", + "ID_FS_TYPE": "ext4", + "ID_FS_USAGE": "filesystem", + "ID_FS_UUID": "70115965-56dd-4de3-bdb2-8ecdb9a5c715", + "ID_FS_UUID_ENC": "70115965-56dd-4de3-bdb2-8ecdb9a5c715", + "ID_FS_VERSION": "1.0", + "ID_PART_ENTRY_DISK": "252:16", + "ID_PART_ENTRY_NAME": "primary", + "ID_PART_ENTRY_NUMBER": "5", + "ID_PART_ENTRY_OFFSET": "2097152", + "ID_PART_ENTRY_SCHEME": "gpt", + "ID_PART_ENTRY_SIZE": "8388608", + "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4", + "ID_PART_ENTRY_UUID": "46dc3aee-f530-4820-8202-2e42b29cf2c7", + "ID_PART_TABLE_TYPE": "gpt", + "ID_PART_TABLE_UUID": "69d0da07-9bea-4aab-a876-219fc2fb6495", + "ID_PATH": "pci-0000:00:05.0", + "ID_PATH_TAG": "pci-0000_00_05_0", + "ID_SCSI": "1", + "ID_SERIAL": "serial1", + "MAJOR": "252", + "MINOR": "21", + "PARTN": "5", + "PARTNAME": "primary", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8426791", + "attrs": { + "alignment_offset": "0", + "dev": "252:21", + "discard_alignment": "0", + "inflight": " 0 0", + "partition": "5", + "ro": "0", + "size": "4294967296", + "start": "2097152", + "stat": " 198 0 9808 13 0 0 0 0 0 120 0 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=252\nMINOR=21\nDEVNAME=vdb5\nDEVTYPE=partition\nPARTN=5\nPARTNAME=primary" + } + }, + "/dev/vdb6": { + "DEVLINKS": "/dev/disk/by-label/home /dev/disk/by-path/virtio-pci-0000:00:05.0-part6 /dev/disk/by-partlabel/primary /dev/disk/by-path/pci-0000:00:05.0-part6 /dev/disk/by-partuuid/05b1c69c-5b00-4d35-85ed-61812ec572f5 /dev/disk/by-uuid/adc43c72-eff5-4ec1-98c4-7dea2a6596c9 /dev/disk/by-id/virtio-serial1-part6", + "DEVNAME": "/dev/vdb6", + "DEVPATH": "/devices/pci0000:00/0000:00:05.0/virtio1/block/vdb/vdb6", + "DEVTYPE": "partition", + "ID_FS_LABEL": "home", + "ID_FS_LABEL_ENC": "home", + "ID_FS_TYPE": "xfs", + "ID_FS_USAGE": "filesystem", + "ID_FS_UUID": "adc43c72-eff5-4ec1-98c4-7dea2a6596c9", + "ID_FS_UUID_ENC": "adc43c72-eff5-4ec1-98c4-7dea2a6596c9", + "ID_PART_ENTRY_DISK": "252:16", + "ID_PART_ENTRY_NAME": "primary", + "ID_PART_ENTRY_NUMBER": "6", + "ID_PART_ENTRY_OFFSET": "10485760", + "ID_PART_ENTRY_SCHEME": "gpt", + "ID_PART_ENTRY_SIZE": "10483713", + "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4", + "ID_PART_ENTRY_UUID": "05b1c69c-5b00-4d35-85ed-61812ec572f5", + "ID_PART_TABLE_TYPE": "gpt", + "ID_PART_TABLE_UUID": "69d0da07-9bea-4aab-a876-219fc2fb6495", + "ID_PATH": "pci-0000:00:05.0", + "ID_PATH_TAG": "pci-0000_00_05_0", + "ID_SCSI": "1", + "ID_SERIAL": "serial1", + "MAJOR": "252", + "MINOR": "22", + "PARTN": "6", + "PARTNAME": "primary", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8436002", + "attrs": { + "alignment_offset": "0", + "dev": "252:22", + "discard_alignment": "0", + "inflight": " 0 0", + "partition": "6", + "ro": "0", + "size": "5367661056", + "start": "10485760", + "stat": " 198 0 8710 13 0 0 0 0 0 100 0 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=252\nMINOR=22\nDEVNAME=vdb6\nDEVTYPE=partition\nPARTN=6\nPARTNAME=primary" + } + }, + "/dev/vdc": { + "DEVLINKS": "/dev/disk/by-path/virtio-pci-0000:00:06.0 /dev/disk/by-path/pci-0000:00:06.0 /dev/disk/by-id/virtio-serial2", + "DEVNAME": "/dev/vdc", + "DEVPATH": "/devices/pci0000:00/0000:00:06.0/virtio2/block/vdc", + "DEVTYPE": "disk", + "ID_PART_TABLE_TYPE": "gpt", + "ID_PART_TABLE_UUID": "7140eecc-47ac-44a0-87ba-90bcb18e3e9f", + "ID_PATH": "pci-0000:00:06.0", + "ID_PATH_TAG": "pci-0000_00_06_0", + "ID_SERIAL": "serial2", + "MAJOR": "252", + "MINOR": "32", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8436366", + "attrs": { + "alignment_offset": "0", + "bdi": null, + "cache_type": "write back", + "capability": "50", + "dev": "252:32", + "device": null, + "discard_alignment": "0", + "ext_range": "256", + "hidden": "0", + "inflight": " 0 0", + "range": "16", + "removable": "0", + "ro": "0", + "serial": "serial2", + "size": "10737418240", + "stat": " 505 0 13936 39 0 0 0 0 0 348 0 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=252\nMINOR=32\nDEVNAME=vdc\nDEVTYPE=disk" + }, + "partitiontable": { + "device": "/dev/vdc", + "firstlba": 34, + "id": "7140EECC-47AC-44A0-87BA-90BCB18E3E9F", + "label": "gpt", + "lastlba": 20971486, + "partitions": [ + { + "name": "primary", + "node": "/dev/vdc1", + "size": 20967425, + "start": 2048, + "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4", + "uuid": "0FE048F5-66FB-4327-835B-17AA5A0A287A" + } + ], + "unit": "sectors" + } + }, + "/dev/vdc1": { + "DEVLINKS": "/dev/disk/by-id/virtio-serial2-part1 /dev/disk/by-path/virtio-pci-0000:00:06.0-part1 /dev/disk/by-partlabel/primary /dev/disk/by-path/pci-0000:00:06.0-part1 /dev/disk/by-partuuid/0fe048f5-66fb-4327-835b-17aa5a0a287a", + "DEVNAME": "/dev/vdc1", + "DEVPATH": "/devices/pci0000:00/0000:00:06.0/virtio2/block/vdc/vdc1", + "DEVTYPE": "partition", + "ID_FS_LABEL": "ringil:foobar", + "ID_FS_LABEL_ENC": "ringil:foobar", + "ID_FS_TYPE": "linux_raid_member", + "ID_FS_USAGE": "raid", + "ID_FS_UUID": "26d43bb7-2b9b-b08e-6912-462ad6572672", + "ID_FS_UUID_ENC": "26d43bb7-2b9b-b08e-6912-462ad6572672", + "ID_FS_UUID_SUB": "dee1d419-9d1e-1649-ba2d-ed472657e7d7", + "ID_FS_UUID_SUB_ENC": "dee1d419-9d1e-1649-ba2d-ed472657e7d7", + "ID_FS_VERSION": "1.2", + "ID_PART_ENTRY_DISK": "252:32", + "ID_PART_ENTRY_NAME": "primary", + "ID_PART_ENTRY_NUMBER": "1", + "ID_PART_ENTRY_OFFSET": "2048", + "ID_PART_ENTRY_SCHEME": "gpt", + "ID_PART_ENTRY_SIZE": "20967425", + "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4", + "ID_PART_ENTRY_UUID": "0fe048f5-66fb-4327-835b-17aa5a0a287a", + "ID_PART_TABLE_TYPE": "gpt", + "ID_PART_TABLE_UUID": "7140eecc-47ac-44a0-87ba-90bcb18e3e9f", + "ID_PATH": "pci-0000:00:06.0", + "ID_PATH_TAG": "pci-0000_00_06_0", + "ID_SCSI": "1", + "ID_SERIAL": "serial2", + "MAJOR": "252", + "MINOR": "33", + "PARTN": "1", + "PARTNAME": "primary", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8488491", + "attrs": { + "alignment_offset": "0", + "dev": "252:33", + "discard_alignment": "0", + "inflight": " 0 0", + "partition": "1", + "ro": "0", + "size": "10735321600", + "start": "2048", + "stat": " 402 0 9680 33 0 0 0 0 0 332 0 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=252\nMINOR=33\nDEVNAME=vdc1\nDEVTYPE=partition\nPARTN=1\nPARTNAME=primary" + } + }, + "/dev/vdd": { + "DEVLINKS": "/dev/disk/by-id/virtio-serial3 /dev/disk/by-path/pci-0000:00:07.0 /dev/disk/by-path/virtio-pci-0000:00:07.0", + "DEVNAME": "/dev/vdd", + "DEVPATH": "/devices/pci0000:00/0000:00:07.0/virtio3/block/vdd", + "DEVTYPE": "disk", + "ID_PART_TABLE_TYPE": "gpt", + "ID_PART_TABLE_UUID": "c89bf1e1-e8fe-44da-9d20-115afc79e1ef", + "ID_PATH": "pci-0000:00:07.0", + "ID_PATH_TAG": "pci-0000_00_07_0", + "ID_SERIAL": "serial3", + "MAJOR": "252", + "MINOR": "48", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8439248", + "attrs": { + "alignment_offset": "0", + "bdi": null, + "cache_type": "write back", + "capability": "50", + "dev": "252:48", + "device": null, + "discard_alignment": "0", + "ext_range": "256", + "hidden": "0", + "inflight": " 0 0", + "range": "16", + "removable": "0", + "ro": "0", + "serial": "serial3", + "size": "10737418240", + "stat": " 212 0 5720 22 0 0 0 0 0 192 0 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=252\nMINOR=48\nDEVNAME=vdd\nDEVTYPE=disk" + }, + "partitiontable": { + "device": "/dev/vdd", + "firstlba": 34, + "id": "C89BF1E1-E8FE-44DA-9D20-115AFC79E1EF", + "label": "gpt", + "lastlba": 20971486, + "partitions": [ + { + "name": "primary", + "node": "/dev/vdd1", + "size": 20967425, + "start": 2048, + "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4", + "uuid": "FB1659A8-5D98-40D1-823B-8507ADA1A1AC" + } + ], + "unit": "sectors" + } + }, + "/dev/vdd1": { + "DEVLINKS": "/dev/disk/by-path/virtio-pci-0000:00:07.0-part1 /dev/disk/by-path/pci-0000:00:07.0-part1 /dev/disk/by-partuuid/fb1659a8-5d98-40d1-823b-8507ada1a1ac /dev/disk/by-id/virtio-serial3-part1 /dev/disk/by-partlabel/primary", + "DEVNAME": "/dev/vdd1", + "DEVPATH": "/devices/pci0000:00/0000:00:07.0/virtio3/block/vdd/vdd1", + "DEVTYPE": "partition", + "ID_FS_LABEL": "ringil:foobar", + "ID_FS_LABEL_ENC": "ringil:foobar", + "ID_FS_TYPE": "linux_raid_member", + "ID_FS_USAGE": "raid", + "ID_FS_UUID": "26d43bb7-2b9b-b08e-6912-462ad6572672", + "ID_FS_UUID_ENC": "26d43bb7-2b9b-b08e-6912-462ad6572672", + "ID_FS_UUID_SUB": "460df2a7-b091-4922-4302-5db1efde510a", + "ID_FS_UUID_SUB_ENC": "460df2a7-b091-4922-4302-5db1efde510a", + "ID_FS_VERSION": "1.2", + "ID_PART_ENTRY_DISK": "252:48", + "ID_PART_ENTRY_NAME": "primary", + "ID_PART_ENTRY_NUMBER": "1", + "ID_PART_ENTRY_OFFSET": "2048", + "ID_PART_ENTRY_SCHEME": "gpt", + "ID_PART_ENTRY_SIZE": "20967425", + "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4", + "ID_PART_ENTRY_UUID": "fb1659a8-5d98-40d1-823b-8507ada1a1ac", + "ID_PART_TABLE_TYPE": "gpt", + "ID_PART_TABLE_UUID": "c89bf1e1-e8fe-44da-9d20-115afc79e1ef", + "ID_PATH": "pci-0000:00:07.0", + "ID_PATH_TAG": "pci-0000_00_07_0", + "ID_SCSI": "1", + "ID_SERIAL": "serial3", + "MAJOR": "252", + "MINOR": "49", + "PARTN": "1", + "PARTNAME": "primary", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8644452", + "attrs": { + "alignment_offset": "0", + "dev": "252:49", + "discard_alignment": "0", + "inflight": " 0 0", + "partition": "1", + "ro": "0", + "size": "10735321600", + "start": "2048", + "stat": " 109 0 1464 15 0 0 0 0 0 188 0 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=252\nMINOR=49\nDEVNAME=vdd1\nDEVTYPE=partition\nPARTN=1\nPARTNAME=primary" + } + }, + "/dev/vde": { + "DEVLINKS": "/dev/disk/by-path/pci-0000:00:08.0 /dev/disk/by-id/virtio-serial4 /dev/disk/by-path/virtio-pci-0000:00:08.0", + "DEVNAME": "/dev/vde", + "DEVPATH": "/devices/pci0000:00/0000:00:08.0/virtio4/block/vde", + "DEVTYPE": "disk", + "ID_PART_TABLE_TYPE": "gpt", + "ID_PART_TABLE_UUID": "e8dc71da-61af-4eb4-a3f9-cc3c49a2e878", + "ID_PATH": "pci-0000:00:08.0", + "ID_PATH_TAG": "pci-0000_00_08_0", + "ID_SERIAL": "serial4", + "MAJOR": "252", + "MINOR": "64", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8435033", + "attrs": { + "alignment_offset": "0", + "bdi": null, + "cache_type": "write back", + "capability": "50", + "dev": "252:64", + "device": null, + "discard_alignment": "0", + "ext_range": "256", + "hidden": "0", + "inflight": " 0 0", + "range": "16", + "removable": "0", + "ro": "0", + "serial": "serial4", + "size": "10737418240", + "stat": " 551 0 14828 587 0 0 0 0 0 296 540 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=252\nMINOR=64\nDEVNAME=vde\nDEVTYPE=disk" + }, + "partitiontable": { + "device": "/dev/vde", + "firstlba": 34, + "id": "E8DC71DA-61AF-4EB4-A3F9-CC3C49A2E878", + "label": "gpt", + "lastlba": 20971486, + "partitions": [ + { + "name": "primary", + "node": "/dev/vde1", + "size": 20967425, + "start": 2048, + "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4", + "uuid": "182CEEE0-1AFA-48D3-8840-B8C998C461B7" + } + ], + "unit": "sectors" + } + }, + "/dev/vde1": { + "DEVLINKS": "/dev/disk/by-partuuid/182ceee0-1afa-48d3-8840-b8c998c461b7 /dev/disk/by-id/virtio-serial4-part1 /dev/disk/by-path/virtio-pci-0000:00:08.0-part1 /dev/disk/by-partlabel/primary /dev/disk/by-id/lvm-pv-uuid-jPz0UV-fakc-37mX-T5aJ-MqZT-IQNR-6Hfq9V /dev/disk/by-path/pci-0000:00:08.0-part1", + "DEVNAME": "/dev/vde1", + "DEVPATH": "/devices/pci0000:00/0000:00:08.0/virtio4/block/vde/vde1", + "DEVTYPE": "partition", + "ID_FS_TYPE": "LVM2_member", + "ID_FS_USAGE": "raid", + "ID_FS_UUID": "jPz0UV-fakc-37mX-T5aJ-MqZT-IQNR-6Hfq9V", + "ID_FS_UUID_ENC": "jPz0UV-fakc-37mX-T5aJ-MqZT-IQNR-6Hfq9V", + "ID_FS_VERSION": "LVM2 001", + "ID_PART_ENTRY_DISK": "252:64", + "ID_PART_ENTRY_NAME": "primary", + "ID_PART_ENTRY_NUMBER": "1", + "ID_PART_ENTRY_OFFSET": "2048", + "ID_PART_ENTRY_SCHEME": "gpt", + "ID_PART_ENTRY_SIZE": "20967425", + "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4", + "ID_PART_ENTRY_UUID": "182ceee0-1afa-48d3-8840-b8c998c461b7", + "ID_PART_TABLE_TYPE": "gpt", + "ID_PART_TABLE_UUID": "e8dc71da-61af-4eb4-a3f9-cc3c49a2e878", + "ID_PATH": "pci-0000:00:08.0", + "ID_PATH_TAG": "pci-0000_00_08_0", + "ID_SCSI": "1", + "ID_SERIAL": "serial4", + "MAJOR": "252", + "MINOR": "65", + "PARTN": "1", + "PARTNAME": "primary", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8457379", + "attrs": { + "alignment_offset": "0", + "dev": "252:65", + "discard_alignment": "0", + "inflight": " 0 0", + "partition": "1", + "ro": "0", + "size": "10735321600", + "start": "2048", + "stat": " 351 0 6340 25 0 0 0 0 0 220 0 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=252\nMINOR=65\nDEVNAME=vde1\nDEVTYPE=partition\nPARTN=1\nPARTNAME=primary" + } + } + }, + "dmcrypt": {}, + "filesystem": { + "/dev/dm-0": { + "LABEL": "lv", + "LABEL_ENC": "lv", + "TYPE": "ext4", + "USAGE": "filesystem", + "UUID": "6a13a61c-51d5-46b8-bb97-02341f79e003", + "UUID_ENC": "6a13a61c-51d5-46b8-bb97-02341f79e003", + "VERSION": "1.0" + }, + "/dev/md127": { + "LABEL": "data", + "LABEL_ENC": "data", + "TYPE": "ext4", + "USAGE": "filesystem", + "UUID": "f59e9a4e-2ffd-4746-8f3c-1a6fd3556ba4", + "UUID_ENC": "f59e9a4e-2ffd-4746-8f3c-1a6fd3556ba4", + "VERSION": "1.0" + }, + "/dev/vda": { + "BOOT_SYSTEM_ID": "EL\\x20TORITO\\x20SPECIFICATION", + "LABEL": "Ubuntu_custom_amd64", + "LABEL_ENC": "Ubuntu\\x20custom\\x20amd64", + "TYPE": "iso9660", + "USAGE": "filesystem", + "UUID": "2019-05-23-03-04-53-00", + "UUID_ENC": "2019-05-23-03-04-53-00", + "VERSION": "Joliet Extension" + }, + "/dev/vda1": { + "BOOT_SYSTEM_ID": "EL\\x20TORITO\\x20SPECIFICATION", + "LABEL": "Ubuntu_custom_amd64", + "LABEL_ENC": "Ubuntu\\x20custom\\x20amd64", + "TYPE": "iso9660", + "USAGE": "filesystem", + "UUID": "2019-05-23-03-04-53-00", + "UUID_ENC": "2019-05-23-03-04-53-00", + "VERSION": "Joliet Extension" + }, + "/dev/vda2": { + "BOOT_SYSTEM_ID": "EL\\x20TORITO\\x20SPECIFICATION", + "LABEL": "Ubuntu_custom_amd64", + "LABEL_ENC": "Ubuntu\\x20custom\\x20amd64", + "TYPE": "vfat", + "USAGE": "filesystem", + "UUID": "039E-EF17", + "UUID_ENC": "039E-EF17", + "VERSION": "FAT12" + }, + "/dev/vdb2": { + "TYPE": "vfat", + "USAGE": "filesystem", + "UUID": "6A43-2198", + "UUID_ENC": "6A43-2198", + "VERSION": "FAT32" + }, + "/dev/vdb4": { + "TYPE": "swap", + "USAGE": "other", + "UUID": "adc9a936-80b3-4988-b2b2-57f0b5eaf169", + "UUID_ENC": "adc9a936-80b3-4988-b2b2-57f0b5eaf169", + "VERSION": "1" + }, + "/dev/vdb5": { + "LABEL": "root", + "LABEL_ENC": "root", + "TYPE": "ext4", + "USAGE": "filesystem", + "UUID": "70115965-56dd-4de3-bdb2-8ecdb9a5c715", + "UUID_ENC": "70115965-56dd-4de3-bdb2-8ecdb9a5c715", + "VERSION": "1.0" + }, + "/dev/vdb6": { + "LABEL": "home", + "LABEL_ENC": "home", + "TYPE": "xfs", + "USAGE": "filesystem", + "UUID": "adc43c72-eff5-4ec1-98c4-7dea2a6596c9", + "UUID_ENC": "adc43c72-eff5-4ec1-98c4-7dea2a6596c9" + } + }, + "lvm": { + "logical_volumes": { + "amazing-vg/my-lv1": { + "fullname": "amazing-vg/my-lv1", + "name": "my-lv1", + "size": "5364514816B", + "volgroup": "amazing-vg" + } + }, + "physical_volumes": { + "amazing-vg": [ + "/dev/vde1" + ] + }, + "volume_groups": { + "amazing-vg": { + "devices": [ + "/dev/vde1" + ], + "name": "amazing-vg", + "size": "10733223936B" + } + } + }, + "mount": [ + { + "children": [ + { + "children": [ + { + "fstype": "securityfs", + "options": "rw,nosuid,nodev,noexec,relatime", + "source": "securityfs", + "target": "/sys/kernel/security" + }, + { + "children": [ + { + "fstype": "cgroup2", + "options": "rw,nosuid,nodev,noexec,relatime,nsdelegate", + "source": "cgroup2", + "target": "/sys/fs/cgroup/unified" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,xattr,name=systemd", + "source": "cgroup", + "target": "/sys/fs/cgroup/systemd" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,freezer", + "source": "cgroup", + "target": "/sys/fs/cgroup/freezer" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,hugetlb", + "source": "cgroup", + "target": "/sys/fs/cgroup/hugetlb" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,pids", + "source": "cgroup", + "target": "/sys/fs/cgroup/pids" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,cpu,cpuacct", + "source": "cgroup", + "target": "/sys/fs/cgroup/cpu,cpuacct" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,net_cls,net_prio", + "source": "cgroup", + "target": "/sys/fs/cgroup/net_cls,net_prio" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,cpuset", + "source": "cgroup", + "target": "/sys/fs/cgroup/cpuset" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,blkio", + "source": "cgroup", + "target": "/sys/fs/cgroup/blkio" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,devices", + "source": "cgroup", + "target": "/sys/fs/cgroup/devices" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,memory", + "source": "cgroup", + "target": "/sys/fs/cgroup/memory" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,rdma", + "source": "cgroup", + "target": "/sys/fs/cgroup/rdma" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,perf_event", + "source": "cgroup", + "target": "/sys/fs/cgroup/perf_event" + } + ], + "fstype": "tmpfs", + "options": "ro,nosuid,nodev,noexec,mode=755", + "source": "tmpfs", + "target": "/sys/fs/cgroup" + }, + { + "fstype": "pstore", + "options": "rw,nosuid,nodev,noexec,relatime", + "source": "pstore", + "target": "/sys/fs/pstore" + }, + { + "fstype": "bpf", + "options": "rw,nosuid,nodev,noexec,relatime,mode=700", + "source": "bpf", + "target": "/sys/fs/bpf" + }, + { + "fstype": "debugfs", + "options": "rw,relatime", + "source": "debugfs", + "target": "/sys/kernel/debug" + }, + { + "fstype": "configfs", + "options": "rw,relatime", + "source": "configfs", + "target": "/sys/kernel/config" + }, + { + "fstype": "fusectl", + "options": "rw,relatime", + "source": "fusectl", + "target": "/sys/fs/fuse/connections" + } + ], + "fstype": "sysfs", + "options": "rw,nosuid,nodev,noexec,relatime", + "source": "sysfs", + "target": "/sys" + }, + { + "children": [ + { + "fstype": "autofs", + "options": "rw,relatime,fd=25,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=13916", + "source": "systemd-1", + "target": "/proc/sys/fs/binfmt_misc" + } + ], + "fstype": "proc", + "options": "rw,nosuid,nodev,noexec,relatime", + "source": "proc", + "target": "/proc" + }, + { + "children": [ + { + "fstype": "devpts", + "options": "rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000", + "source": "devpts", + "target": "/dev/pts" + }, + { + "fstype": "tmpfs", + "options": "rw,nosuid,nodev", + "source": "tmpfs", + "target": "/dev/shm" + }, + { + "fstype": "hugetlbfs", + "options": "rw,relatime,pagesize=2M", + "source": "hugetlbfs", + "target": "/dev/hugepages" + }, + { + "fstype": "mqueue", + "options": "rw,relatime", + "source": "mqueue", + "target": "/dev/mqueue" + } + ], + "fstype": "devtmpfs", + "options": "rw,nosuid,relatime,size=467220k,nr_inodes=116805,mode=755", + "source": "udev", + "target": "/dev" + }, + { + "children": [ + { + "fstype": "tmpfs", + "options": "rw,nosuid,nodev,noexec,relatime,size=5120k", + "source": "tmpfs", + "target": "/run/lock" + }, + { + "fstype": "tmpfs", + "options": "rw,nosuid,nodev,relatime,size=100540k,mode=700,uid=999,gid=999", + "source": "tmpfs", + "target": "/run/user/999" + } + ], + "fstype": "tmpfs", + "options": "rw,nosuid,noexec,relatime,size=100544k,mode=755", + "source": "tmpfs", + "target": "/run" + }, + { + "fstype": "iso9660", + "options": "ro,noatime,nojoliet,check=s,map=n,blocksize=2048", + "source": "/dev/vda", + "target": "/cdrom" + }, + { + "fstype": "squashfs", + "options": "ro,noatime", + "source": "/dev/loop0", + "target": "/rofs" + }, + { + "fstype": "squashfs", + "options": "ro,relatime", + "source": "/dev/loop2", + "target": "/usr/lib/modules" + }, + { + "fstype": "squashfs", + "options": "ro,relatime", + "source": "/dev/loop3", + "target": "/media/region.lower" + }, + { + "fstype": "squashfs", + "options": "ro,relatime", + "source": "/dev/loop0", + "target": "/media/filesystem" + }, + { + "fstype": "tmpfs", + "options": "rw,nosuid,nodev,relatime", + "source": "tmpfs", + "target": "/tmp" + }, + { + "fstype": "squashfs", + "options": "ro,relatime", + "source": "/dev/loop4", + "target": "/media/rack.lower" + }, + { + "fstype": "overlay", + "options": "ro,relatime,lowerdir=/media/region.lower:/media/rack.lower:/media/filesystem", + "source": "overlay", + "target": "/media/region" + }, + { + "fstype": "overlay", + "options": "ro,relatime,lowerdir=/media/rack.lower:/media/filesystem", + "source": "overlay", + "target": "/media/rack" + }, + { + "fstype": "squashfs", + "options": "ro,nodev,relatime", + "source": "/dev/loop5", + "target": "/snap/core/6673" + }, + { + "fstype": "squashfs", + "options": "ro,nodev,relatime", + "source": "/dev/loop6", + "target": "/snap/subiquity/x1" + } + ], + "fstype": "overlay", + "options": "rw,relatime,lowerdir=//installer.squashfs://filesystem.squashfs,upperdir=/cow/upper,workdir=/cow/work", + "source": "/cow", + "target": "/" + } + ], + "multipath": {}, + "raid": { + "/dev/md127": { + "DEVLINKS": "/dev/disk/by-uuid/f59e9a4e-2ffd-4746-8f3c-1a6fd3556ba4 /dev/disk/by-label/data /dev/disk/by-id/md-uuid-26d43bb7:2b9bb08e:6912462a:d6572672 /dev/disk/by-id/md-name-ringil:foobar /dev/md/ringil:foobar", + "DEVNAME": "/dev/md127", + "DEVPATH": "/devices/virtual/block/md127", + "DEVTYPE": "disk", + "ID_FS_LABEL": "data", + "ID_FS_LABEL_ENC": "data", + "ID_FS_TYPE": "ext4", + "ID_FS_USAGE": "filesystem", + "ID_FS_UUID": "f59e9a4e-2ffd-4746-8f3c-1a6fd3556ba4", + "ID_FS_UUID_ENC": "f59e9a4e-2ffd-4746-8f3c-1a6fd3556ba4", + "ID_FS_VERSION": "1.0", + "MAJOR": "9", + "MD_DEVICES": "2", + "MD_DEVICE_ev_vdc1_DEV": "/dev/vdc1", + "MD_DEVICE_ev_vdc1_ROLE": "0", + "MD_DEVICE_ev_vdd1_DEV": "/dev/vdd1", + "MD_DEVICE_ev_vdd1_ROLE": "1", + "MD_DEVNAME": "ringil:foobar", + "MD_LEVEL": "raid1", + "MD_METADATA": "1.2", + "MD_NAME": "ringil:foobar", + "MD_UUID": "26d43bb7:2b9bb08e:6912462a:d6572672", + "MINOR": "127", + "SUBSYSTEM": "block", + "SYSTEMD_WANTS": "mdmonitor.service", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "8488818", + "devices": [ + "/dev/vdc1", + "/dev/vdd1" + ], + "raidlevel": "raid1", + "spare_devices": [] + } + }, + "zfs": { + "zpools": {} + } + } +} diff --git a/examples/simple.json b/examples/simple.json new file mode 100644 index 00000000..b6e75850 --- /dev/null +++ b/examples/simple.json @@ -0,0 +1,697 @@ +{ + "network": { + "links": [ + { + "addresses": [ + { + "address": "10.0.2.15/24", + "family": 2, + "scope": "global", + "source": "dhcp" + }, + { + "address": "fec0::5054:ff:fe12:3456/64", + "family": 10, + "scope": "site", + "source": "dhcp" + }, + { + "address": "fe80::5054:ff:fe12:3456/64", + "family": 10, + "scope": "link", + "source": "static" + } + ], + "bond": { + "is_master": false, + "is_slave": false, + "lacp_rate": null, + "master": null, + "mode": null, + "slaves": [], + "xmit_hash_policy": null + }, + "bridge": { + "interfaces": [], + "is_bridge": false, + "is_port": false, + "options": {} + }, + "netlink_data": { + "arptype": 1, + "family": 0, + "flags": 69699, + "ifindex": 2, + "is_vlan": false, + "name": "ens3" + }, + "type": "eth", + "udev_data": { + "DEVPATH": "/devices/pci0000:00/0000:00:03.0/net/ens3", + "ID_BUS": "pci", + "ID_MM_CANDIDATE": "1", + "ID_MODEL_FROM_DATABASE": "82540EM Gigabit Ethernet Controller (QEMU Virtual Machine)", + "ID_MODEL_ID": "0x100e", + "ID_NET_NAME_MAC": "enx525400123456", + "ID_NET_NAME_PATH": "enp0s3", + "ID_NET_NAME_SLOT": "ens3", + "ID_NET_NAMING_SCHEME": "v240", + "ID_PATH": "pci-0000:00:03.0", + "ID_PATH_TAG": "pci-0000_00_03_0", + "ID_PCI_CLASS_FROM_DATABASE": "Network controller", + "ID_PCI_SUBCLASS_FROM_DATABASE": "Ethernet controller", + "ID_VENDOR_FROM_DATABASE": "Intel Corporation", + "ID_VENDOR_ID": "0x8086", + "IFINDEX": "2", + "INTERFACE": "ens3", + "SUBSYSTEM": "net", + "SYSTEMD_ALIAS": "/sys/subsystem/net/devices/ens3", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "82651806", + "attrs": { + "addr_assign_type": "0", + "addr_len": "6", + "address": "52:54:00:12:34:56", + "broadcast": "ff:ff:ff:ff:ff:ff", + "carrier": "1", + "carrier_changes": "2", + "carrier_down_count": "1", + "carrier_up_count": "1", + "dev_id": "0x0", + "dev_port": "0", + "device": null, + "dormant": "0", + "duplex": "full", + "flags": "0x1003", + "gro_flush_timeout": "0", + "ifalias": "", + "ifindex": "2", + "iflink": "2", + "link_mode": "0", + "mtu": "1500", + "name_assign_type": "4", + "netdev_group": "0", + "operstate": "up", + "phys_port_id": null, + "phys_port_name": null, + "phys_switch_id": null, + "proto_down": "0", + "speed": "1000", + "subsystem": "net", + "tx_queue_len": "1000", + "type": "1", + "uevent": "INTERFACE=ens3\nIFINDEX=2" + } + } + }, + { + "addresses": [ + { + "address": "127.0.0.1/8", + "family": 2, + "scope": "host", + "source": "static" + }, + { + "address": "::1/128", + "family": 10, + "scope": "host", + "source": "static" + } + ], + "bond": { + "is_master": false, + "is_slave": false, + "lacp_rate": null, + "master": null, + "mode": null, + "slaves": [], + "xmit_hash_policy": null + }, + "bridge": { + "interfaces": [], + "is_bridge": false, + "is_port": false, + "options": {} + }, + "netlink_data": { + "arptype": 772, + "family": 0, + "flags": 65609, + "ifindex": 1, + "is_vlan": false, + "name": "lo" + }, + "type": "lo", + "udev_data": { + "DEVPATH": "/devices/virtual/net/lo", + "ID_MM_CANDIDATE": "1", + "IFINDEX": "1", + "INTERFACE": "lo", + "SUBSYSTEM": "net", + "USEC_INITIALIZED": "89206115", + "attrs": { + "addr_assign_type": "0", + "addr_len": "6", + "address": "00:00:00:00:00:00", + "broadcast": "00:00:00:00:00:00", + "carrier": "1", + "carrier_changes": "0", + "carrier_down_count": "0", + "carrier_up_count": "0", + "dev_id": "0x0", + "dev_port": "0", + "dormant": "0", + "duplex": null, + "flags": "0x9", + "gro_flush_timeout": "0", + "ifalias": "", + "ifindex": "1", + "iflink": "1", + "link_mode": "0", + "mtu": "65536", + "name_assign_type": null, + "netdev_group": "0", + "operstate": "unknown", + "phys_port_id": null, + "phys_port_name": null, + "phys_switch_id": null, + "proto_down": "0", + "speed": null, + "subsystem": "net", + "tx_queue_len": "1000", + "type": "772", + "uevent": "INTERFACE=lo\nIFINDEX=1" + } + } + } + ], + "routes": [ + { + "dst": "default", + "family": 2, + "ifindex": 2, + "table": 254, + "type": 1 + }, + { + "dst": "10.0.2.0/24", + "family": 2, + "ifindex": 2, + "table": 254, + "type": 1 + }, + { + "dst": "10.0.2.2", + "family": 2, + "ifindex": 2, + "table": 254, + "type": 1 + }, + { + "dst": "10.0.2.0", + "family": 2, + "ifindex": 2, + "table": 255, + "type": 3 + }, + { + "dst": "10.0.2.15", + "family": 2, + "ifindex": 2, + "table": 255, + "type": 2 + }, + { + "dst": "10.0.2.255", + "family": 2, + "ifindex": 2, + "table": 255, + "type": 3 + }, + { + "dst": "127.0.0.0", + "family": 2, + "ifindex": 1, + "table": 255, + "type": 3 + }, + { + "dst": "127.0.0.0/8", + "family": 2, + "ifindex": 1, + "table": 255, + "type": 2 + }, + { + "dst": "127.0.0.1", + "family": 2, + "ifindex": 1, + "table": 255, + "type": 2 + }, + { + "dst": "127.255.255.255", + "family": 2, + "ifindex": 1, + "table": 255, + "type": 3 + }, + { + "dst": "::1", + "family": 10, + "ifindex": 1, + "table": 254, + "type": 1 + }, + { + "dst": "fe80::/64", + "family": 10, + "ifindex": 2, + "table": 254, + "type": 1 + }, + { + "dst": "fec0::/64", + "family": 10, + "ifindex": 2, + "table": 254, + "type": 1 + }, + { + "dst": "default", + "family": 10, + "ifindex": 2, + "table": 254, + "type": 1 + }, + { + "dst": "::1", + "family": 10, + "ifindex": 1, + "table": 255, + "type": 2 + }, + { + "dst": "fe80::5054:ff:fe12:3456", + "family": 10, + "ifindex": 2, + "table": 255, + "type": 2 + }, + { + "dst": "fec0::5054:ff:fe12:3456", + "family": 10, + "ifindex": 2, + "table": 255, + "type": 2 + }, + { + "dst": "ff00::/8", + "family": 10, + "ifindex": 2, + "table": 255, + "type": 1 + } + ] + }, + "storage": { + "bcache": { + "backing": {}, + "caching": {} + }, + "blockdev": { + "/dev/fd0": { + "DEVNAME": "/dev/fd0", + "DEVPATH": "/devices/platform/floppy.0/block/fd0", + "DEVTYPE": "disk", + "MAJOR": "2", + "MINOR": "0", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "82216378", + "attrs": { + "alignment_offset": "0", + "bdi": null, + "capability": "11", + "dev": "2:0", + "device": null, + "discard_alignment": "0", + "events": "", + "events_async": "", + "events_poll_msecs": "-1", + "ext_range": "1", + "hidden": "0", + "inflight": " 0 0", + "range": "1", + "removable": "1", + "ro": "0", + "size": "4096", + "stat": " 1 0 8 68 0 0 0 0 0 8 68 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=2\nMINOR=0\nDEVNAME=fd0\nDEVTYPE=disk" + } + }, + "/dev/sda": { + "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", + "DEVNAME": "/dev/sda", + "DEVPATH": "/devices/pci0000:00/0000:00:01.1/ata1/host0/target0:0:0/0:0:0:0/block/sda", + "DEVTYPE": "disk", + "ID_ATA": "1", + "ID_BUS": "ata", + "ID_MODEL": "QEMU_HARDDISK", + "ID_MODEL_ENC": "QEMU\\x20HARDDISK\\x20\\x20\\x20", + "ID_PATH": "pci-0000:00:01.1-ata-1", + "ID_PATH_TAG": "pci-0000_00_01_1-ata-1", + "ID_REVISION": "2.5+", + "ID_SCSI": "1", + "ID_SCSI_DI": "1", + "ID_SCSI_SN": "1", + "ID_SERIAL": "QEMU_HARDDISK_QM00001", + "ID_SERIAL_SHORT": "QM00001", + "ID_TYPE": "disk", + "ID_VENDOR": "ATA", + "ID_VENDOR_ENC": "ATA\\x20\\x20\\x20\\x20\\x20", + "MAJOR": "8", + "MINOR": "0", + "MPATH_SBIN_PATH": "/sbin", + "SCSI_IDENT_LUN_ATA": "QEMU_HARDDISK_QM00001", + "SCSI_IDENT_LUN_T10": "ATA_QEMU_HARDDISK_QM00001", + "SCSI_IDENT_LUN_VENDOR": "QM00001", + "SCSI_IDENT_SERIAL": "QM00001", + "SCSI_MODEL": "QEMU_HARDDISK", + "SCSI_MODEL_ENC": "QEMU\\x20HARDDISK\\x20\\x20\\x20", + "SCSI_REVISION": "2.5+", + "SCSI_TPGS": "0", + "SCSI_TYPE": "disk", + "SCSI_VENDOR": "ATA", + "SCSI_VENDOR_ENC": "ATA\\x20\\x20\\x20\\x20\\x20", + "SUBSYSTEM": "block", + "TAGS": ":systemd:", + "USEC_INITIALIZED": "82301144", + "attrs": { + "alignment_offset": "0", + "bdi": null, + "capability": "50", + "dev": "8:0", + "device": null, + "discard_alignment": "0", + "events": "", + "events_async": "", + "events_poll_msecs": "-1", + "ext_range": "256", + "hidden": "0", + "inflight": " 0 0", + "range": "16", + "removable": "0", + "ro": "0", + "size": "10737418240", + "stat": " 411 0 16968 119 0 0 0 0 0 264 0 0 0 0 0", + "subsystem": "block", + "uevent": "MAJOR=8\nMINOR=0\nDEVNAME=sda\nDEVTYPE=disk" + } + } + }, + "dmcrypt": {}, + "filesystem": { + }, + "lvm": {}, + "mount": [ + { + "children": [ + { + "children": [ + { + "fstype": "securityfs", + "options": "rw,nosuid,nodev,noexec,relatime", + "source": "securityfs", + "target": "/sys/kernel/security" + }, + { + "children": [ + { + "fstype": "cgroup2", + "options": "rw,nosuid,nodev,noexec,relatime,nsdelegate", + "source": "cgroup2", + "target": "/sys/fs/cgroup/unified" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,xattr,name=systemd", + "source": "cgroup", + "target": "/sys/fs/cgroup/systemd" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,rdma", + "source": "cgroup", + "target": "/sys/fs/cgroup/rdma" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,hugetlb", + "source": "cgroup", + "target": "/sys/fs/cgroup/hugetlb" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,pids", + "source": "cgroup", + "target": "/sys/fs/cgroup/pids" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,freezer", + "source": "cgroup", + "target": "/sys/fs/cgroup/freezer" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,memory", + "source": "cgroup", + "target": "/sys/fs/cgroup/memory" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,cpu,cpuacct", + "source": "cgroup", + "target": "/sys/fs/cgroup/cpu,cpuacct" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,cpuset", + "source": "cgroup", + "target": "/sys/fs/cgroup/cpuset" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,blkio", + "source": "cgroup", + "target": "/sys/fs/cgroup/blkio" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,perf_event", + "source": "cgroup", + "target": "/sys/fs/cgroup/perf_event" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,devices", + "source": "cgroup", + "target": "/sys/fs/cgroup/devices" + }, + { + "fstype": "cgroup", + "options": "rw,nosuid,nodev,noexec,relatime,net_cls,net_prio", + "source": "cgroup", + "target": "/sys/fs/cgroup/net_cls,net_prio" + } + ], + "fstype": "tmpfs", + "options": "ro,nosuid,nodev,noexec,mode=755", + "source": "tmpfs", + "target": "/sys/fs/cgroup" + }, + { + "fstype": "pstore", + "options": "rw,nosuid,nodev,noexec,relatime", + "source": "pstore", + "target": "/sys/fs/pstore" + }, + { + "fstype": "efivarfs", + "options": "rw,nosuid,nodev,noexec,relatime", + "source": "efivarfs", + "target": "/sys/firmware/efi/efivars" + }, + { + "fstype": "bpf", + "options": "rw,nosuid,nodev,noexec,relatime,mode=700", + "source": "bpf", + "target": "/sys/fs/bpf" + }, + { + "fstype": "debugfs", + "options": "rw,relatime", + "source": "debugfs", + "target": "/sys/kernel/debug" + }, + { + "fstype": "fusectl", + "options": "rw,relatime", + "source": "fusectl", + "target": "/sys/fs/fuse/connections" + }, + { + "fstype": "configfs", + "options": "rw,relatime", + "source": "configfs", + "target": "/sys/kernel/config" + } + ], + "fstype": "sysfs", + "options": "rw,nosuid,nodev,noexec,relatime", + "source": "sysfs", + "target": "/sys" + }, + { + "children": [ + { + "fstype": "autofs", + "options": "rw,relatime,fd=44,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=14037", + "source": "systemd-1", + "target": "/proc/sys/fs/binfmt_misc" + } + ], + "fstype": "proc", + "options": "rw,nosuid,nodev,noexec,relatime", + "source": "proc", + "target": "/proc" + }, + { + "children": [ + { + "fstype": "devpts", + "options": "rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000", + "source": "devpts", + "target": "/dev/pts" + }, + { + "fstype": "tmpfs", + "options": "rw,nosuid,nodev", + "source": "tmpfs", + "target": "/dev/shm" + }, + { + "fstype": "mqueue", + "options": "rw,relatime", + "source": "mqueue", + "target": "/dev/mqueue" + }, + { + "fstype": "hugetlbfs", + "options": "rw,relatime,pagesize=2M", + "source": "hugetlbfs", + "target": "/dev/hugepages" + } + ], + "fstype": "devtmpfs", + "options": "rw,nosuid,relatime,size=465256k,nr_inodes=116314,mode=755", + "source": "udev", + "target": "/dev" + }, + { + "children": [ + { + "fstype": "tmpfs", + "options": "rw,nosuid,nodev,noexec,relatime,size=5120k", + "source": "tmpfs", + "target": "/run/lock" + }, + { + "fstype": "tmpfs", + "options": "rw,nosuid,nodev,relatime,size=100148k,mode=700,uid=999,gid=999", + "source": "tmpfs", + "target": "/run/user/999" + } + ], + "fstype": "tmpfs", + "options": "rw,nosuid,noexec,relatime,size=100152k,mode=755", + "source": "tmpfs", + "target": "/run" + }, + { + "fstype": "squashfs", + "options": "ro,noatime", + "source": "/dev/loop0", + "target": "/rofs" + }, + { + "fstype": "squashfs", + "options": "ro,relatime", + "source": "/dev/loop2", + "target": "/usr/lib/modules" + }, + { + "fstype": "tmpfs", + "options": "rw,nosuid,nodev,relatime", + "source": "tmpfs", + "target": "/tmp" + }, + { + "fstype": "squashfs", + "options": "ro,relatime", + "source": "/dev/loop3", + "target": "/media/rack.lower" + }, + { + "fstype": "squashfs", + "options": "ro,relatime", + "source": "/dev/loop4", + "target": "/media/region.lower" + }, + { + "fstype": "squashfs", + "options": "ro,relatime", + "source": "/dev/loop0", + "target": "/media/filesystem" + }, + { + "fstype": "overlay", + "options": "ro,relatime,lowerdir=/media/region.lower:/media/rack.lower:/media/filesystem", + "source": "overlay", + "target": "/media/region" + }, + { + "fstype": "overlay", + "options": "ro,relatime,lowerdir=/media/rack.lower:/media/filesystem", + "source": "overlay", + "target": "/media/rack" + }, + { + "fstype": "squashfs", + "options": "ro,nodev,relatime", + "source": "/dev/loop5", + "target": "/snap/core/6673" + }, + { + "fstype": "squashfs", + "options": "ro,nodev,relatime", + "source": "/dev/loop6", + "target": "/snap/subiquity/1012" + } + ], + "fstype": "overlay", + "options": "rw,relatime,lowerdir=//installer.squashfs://filesystem.squashfs,upperdir=/cow/upper,workdir=/cow/work", + "source": "/cow", + "target": "/" + } + ], + "multipath": {}, + "raid": {}, + "zfs": { + "zpools": {} + } + } +} From 620d7b1973c0dba9330f5dff8fd84dce1d0d782a Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Tue, 28 May 2019 22:35:15 +1200 Subject: [PATCH 02/23] call extract_storage_config with probert config to create actions --- subiquity/controllers/filesystem.py | 8 +- subiquity/models/filesystem.py | 119 ++++++++++-------- .../views/filesystem/tests/test_filesystem.py | 15 +-- 3 files changed, 74 insertions(+), 68 deletions(-) diff --git a/subiquity/controllers/filesystem.py b/subiquity/controllers/filesystem.py index 03808370..6aa780b6 100644 --- a/subiquity/controllers/filesystem.py +++ b/subiquity/controllers/filesystem.py @@ -16,8 +16,6 @@ import enum import logging -from probert.storage import StorageInfo - from subiquitycore.controller import BaseController from subiquity.models.filesystem import ( @@ -75,11 +73,7 @@ class FilesystemController(BaseController): 5.0, lambda loop, ud: self._check_probe_timeout()) def _bg_probe(self, probe_types=None): - probed_data = self.prober.get_storage(probe_types=probe_types) - storage = {} - for path, data in probed_data["blockdev"].items(): - storage[path] = StorageInfo({path: data}) - return storage + return self.prober.get_storage(probe_types=probe_types) def _probed(self, fut, restricted=False): if not restricted and self._probe_state != ProbeState.PROBING: diff --git a/subiquity/models/filesystem.py b/subiquity/models/filesystem.py index e7af440d..b93335e0 100644 --- a/subiquity/models/filesystem.py +++ b/subiquity/models/filesystem.py @@ -17,15 +17,17 @@ from abc import ABC, abstractmethod import attr import collections import enum -import glob +import itertools import logging import math import os import pathlib import platform -import sys from curtin.util import human2bytes +from curtin import storage_config + +from probert.storage import StorageInfo log = logging.getLogger('subiquity.models.filesystem') @@ -70,6 +72,9 @@ def _remove_backlinks(obj): setattr(vv, backlink, None) +_type_to_cls = {} + + def fsobj(typ): def wrapper(c): c.__attrs_post_init__ = _set_backlinks @@ -77,6 +82,7 @@ def fsobj(typ): c.id = attributes.idfield(typ) c._m = attr.ib(repr=None, default=None) c = attr.s(cmp=False)(c) + _type_to_cls[typ] = c return c return wrapper @@ -554,14 +560,6 @@ class Disk(_Device): _info = attr.ib(default=None) - @classmethod - def from_info(self, model, info): - d = Disk(m=model, info=info) - d.serial = info.serial - d.path = info.name - d.model = info.model - return d - def info_for_display(self): bus = self._info.raw.get('ID_BUS', None) major = self._info.raw.get('MAJOR', None) @@ -1003,14 +1001,67 @@ class FilesystemModel(object): def __init__(self): self.bootloader = self._probe_bootloader() - self._disk_info = [] + self._probe_data = None self.reset() def reset(self): - self._actions = [ - Disk.from_info(self, info) for info in self._disk_info] + if self._probe_data is not None: + config = storage_config.extract_storage_config(self._probe_data) + self._actions = self._actions_from_config( + config["storage"]["config"], + self._probe_data['blockdev']) + else: + self._actions = [] self.grub_install_device = None + def _actions_from_config(self, config, blockdevs): + byid = {} + objs = [] + exclusions = set() + for action in config: + if action['type'] == 'mount': + exclusions.add(byid[action['device']]) + continue + c = _type_to_cls.get(action['type'], None) + if c is None: + # Ignore any action we do not know how to process yet + # (e.g. bcache) + continue + kw = {} + for f in attr.fields(c): + n = f.name + if n not in action: + continue + v = action[n] + if f.metadata.get('ref', False): + kw[n] = byid[v] + elif f.metadata.get('reflist', False): + kw[n] = [byid[id] for id in v] + else: + kw[n] = v + if kw['type'] == 'disk': + path = kw['path'] + kw['info'] = StorageInfo({path: blockdevs[path]}) + kw['preserve'] = True + obj = byid[action['id']] = c(m=self, **kw) + objs.append(obj) + + # We filter out anything that can be reached from a currently + # mounted device. The motivation here is only to exclude the + # media subiquity is mounted from, so this might be a bit + # excessive but hey it works. + while True: + log.debug("exclusions %s", {e.id for e in exclusions}) + next_exclusions = exclusions.copy() + for e in exclusions: + next_exclusions.update(itertools.chain( + dependencies(e), reverse_dependencies(e))) + if len(exclusions) == len(next_exclusions): + break + exclusions = next_exclusions + + return [o for o in objs if o not in exclusions] + def _render_actions(self): # The curtin storage config has the constraint that an action must be # preceded by all the things that it depends on. We handle this by @@ -1086,45 +1137,9 @@ class FilesystemModel(object): } return config - def _get_system_mounted_disks(self): - # This assumes a fairly vanilla setup. It won't list as - # mounted a disk that is only mounted via lvm, for example. - mounted_devs = [] - with open('/proc/mounts', encoding=sys.getfilesystemencoding()) as pm: - for line in pm: - if line.startswith('/dev/'): - mounted_devs.append(line.split()[0][5:]) - mounted_disks = set() - for dev in mounted_devs: - if os.path.exists('/sys/block/{}'.format(dev)): - mounted_disks.add('/dev/' + dev) - else: - paths = glob.glob('/sys/block/*/{}/partition'.format(dev)) - if len(paths) == 1: - mounted_disks.add('/dev/' + paths[0].split('/')[3]) - return mounted_disks - - def load_probe_data(self, storage): - currently_mounted = self._get_system_mounted_disks() - for path, info in storage.items(): - log.debug("fs probe %s", path) - if path in currently_mounted: - continue - if info.type == 'disk': - if info.is_virtual: - continue - if info.raw["MAJOR"] in ("2", "11"): # serial and cd devices - continue - if info.raw['attrs'].get('ro') == "1": - continue - if "ID_CDROM" in info.raw: - continue - # log.debug('disk={}\n{}'.format( - # path, json.dumps(data, indent=4, sort_keys=True))) - if info.size < self.lower_size_limit: - continue - self._disk_info.append(info) - self._actions.append(Disk.from_info(self, info)) + def load_probe_data(self, probe_data): + self._probe_data = probe_data + self.reset() def disk_by_path(self, path): for a in self._actions: diff --git a/subiquity/ui/views/filesystem/tests/test_filesystem.py b/subiquity/ui/views/filesystem/tests/test_filesystem.py index b97b09dc..c931529c 100644 --- a/subiquity/ui/views/filesystem/tests/test_filesystem.py +++ b/subiquity/ui/views/filesystem/tests/test_filesystem.py @@ -1,6 +1,5 @@ import unittest from unittest import mock -from collections import namedtuple import urwid @@ -12,14 +11,12 @@ from subiquity.models.filesystem import ( Disk, FilesystemModel, ) +from subiquity.models.tests.test_filesystem import ( + FakeStorageInfo, + ) from subiquity.ui.views.filesystem.filesystem import FilesystemView -FakeStorageInfo = namedtuple( - 'FakeStorageInfo', ['name', 'size', 'free', 'serial', 'model']) -FakeStorageInfo.__new__.__defaults__ = (None,) * len(FakeStorageInfo._fields) - - class FilesystemViewTests(unittest.TestCase): def make_view(self, model, devices=[]): @@ -35,9 +32,9 @@ class FilesystemViewTests(unittest.TestCase): def test_one_disk(self): model = mock.create_autospec(spec=FilesystemModel) - disk = Disk.from_info(model, FakeStorageInfo( - name='disk-name', size=100*(2**20), free=50*(2**20), - serial="DISK-SERIAL")) + disk = Disk( + m=model, serial="DISK-SERIAL", + info=FakeStorageInfo(size=100*(2**20), free=50*(2**20))) view = self.make_view(model, [disk]) w = view_helpers.find_with_pred( view, From 628758811eae2a02e6fbd6e95afc2edf2cd5e939 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Tue, 28 May 2019 22:59:30 +1200 Subject: [PATCH 03/23] support for editing existing partitions --- subiquity/controllers/filesystem.py | 25 ++++++---- subiquity/models/filesystem.py | 15 +++++- subiquity/ui/views/filesystem/partition.py | 49 ++++++++++++++----- .../views/filesystem/tests/test_partition.py | 20 ++++++++ subiquitycore/testing/view_helpers.py | 4 +- 5 files changed, 91 insertions(+), 22 deletions(-) diff --git a/subiquity/controllers/filesystem.py b/subiquity/controllers/filesystem.py index 6aa780b6..f3d7ea25 100644 --- a/subiquity/controllers/filesystem.py +++ b/subiquity/controllers/filesystem.py @@ -267,8 +267,12 @@ class FilesystemController(BaseController): def create_filesystem(self, volume, spec): if spec['fstype'] is None: - return - fs = self.model.add_filesystem(volume, spec['fstype']) + fs = volume.original_fs() + if fs is None: + return + self.model.readd_filesystem(fs) + else: + fs = self.model.add_filesystem(volume, spec['fstype']) if isinstance(volume, Partition): if spec['fstype'] == "swap": volume.flag = "swap" @@ -390,9 +394,10 @@ class FilesystemController(BaseController): log.debug('disk.freespace: {}'.format(disk.free_for_partitions)) if partition is not None: - partition.size = align_up(spec['size']) - if disk.free_for_partitions < 0: - raise Exception("partition size too large") + if 'size' in spec: + partition.size = align_up(spec['size']) + if disk.free_for_partitions < 0: + raise Exception("partition size too large") self.delete_filesystem(partition.fs()) self.create_filesystem(partition, spec) return @@ -420,10 +425,12 @@ class FilesystemController(BaseController): log.debug('vg.freespace: {}'.format(vg.free_for_partitions)) if lv is not None: - lv.name = spec['name'] - lv.size = align_up(spec['size']) - if vg.free_for_partitions < 0: - raise Exception("lv size too large") + if 'name' in spec: + lv.name = spec['name'] + if 'size' in spec: + lv.size = align_up(spec['size']) + if vg.free_for_partitions < 0: + raise Exception("lv size too large") self.delete_filesystem(lv.fs()) self.create_filesystem(lv, spec) return diff --git a/subiquity/models/filesystem.py b/subiquity/models/filesystem.py index b93335e0..a822a7ae 100644 --- a/subiquity/models/filesystem.py +++ b/subiquity/models/filesystem.py @@ -389,6 +389,7 @@ class _Formattable(ABC): # Filesystem _fs = attributes.backlink() + _original_fs = attributes.backlink() # Raid or LVM_VolGroup for now, but one day ZPool, BCache... _constructed_device = attributes.backlink() @@ -420,6 +421,9 @@ class _Formattable(ABC): def fs(self): return self._fs + def original_fs(self): + return self._original_fs + def constructed_device(self, skip_dm_crypt=True): cd = self._constructed_device if cd is None: @@ -937,7 +941,10 @@ class Filesystem: def _available(self): # False if mounted or if fs does not require a mount, True otherwise. if self._mount is None: - return FilesystemModel.is_mounted_filesystem(self.fstype) + if self.preserve: + return True + else: + return FilesystemModel.is_mounted_filesystem(self.fstype) else: return False @@ -1044,6 +1051,8 @@ class FilesystemModel(object): kw['info'] = StorageInfo({path: blockdevs[path]}) kw['preserve'] = True obj = byid[action['id']] = c(m=self, **kw) + if action['type'] == "format": + obj.volume._original_fs = obj objs.append(obj) # We filter out anything that can be reached from a currently @@ -1267,6 +1276,10 @@ class FilesystemModel(object): self._actions.append(fs) return fs + def readd_filesystem(self, fs): + _set_backlinks(fs) + self._actions.append(fs) + def remove_filesystem(self, fs): if fs._mount: raise Exception("can only remove unmounted filesystem") diff --git a/subiquity/ui/views/filesystem/partition.py b/subiquity/ui/views/filesystem/partition.py index f87ef471..735f0d63 100644 --- a/subiquity/ui/views/filesystem/partition.py +++ b/subiquity/ui/views/filesystem/partition.py @@ -57,14 +57,23 @@ class FSTypeField(FormField): # This will need to do something different for editing an # existing partition that is already formatted. options = [ - ('ext4', True), - ('xfs', True), - ('btrfs', True), - ('---', False), - ('swap', True), - ('---', False), - ('leave unformatted', True, None), + ('ext4', True), + ('xfs', True), + ('btrfs', True), + ('---', False), + ('swap', True), ] + if form.existing_fs_type is None: + options = options + [ + ('---', False), + (_('Leave unformatted'), True, None), + ] + else: + label = _('Leave formatted as {}').format(form.existing_fs_type) + options = [ + (label, True, None), + ('---', False), + ] + options sel = Selector(opts=options) sel.value = None return sel @@ -128,8 +137,14 @@ LVNameField = simple_field(LVNameEditor) class PartitionForm(Form): - def __init__(self, model, max_size, initial, lvm_names): + def __init__(self, model, max_size, initial, lvm_names, device): self.model = model + self.device = device + self.existing_fs_type = None + if device: + existing_fs = device.original_fs() + if existing_fs: + self.existing_fs_type = existing_fs.fstype initial_path = initial.get('mount') self.mountpoints = { m.path: m.device.volume for m in self.model.all_mounts() @@ -146,6 +161,8 @@ class PartitionForm(Form): self.select_fstype(None, self.fstype.widget.value) def select_fstype(self, sender, fstype): + if fstype is None: + fstype = self.existing_fs_type self.mount.enabled = self.model.is_mounted_filesystem(fstype) name = LVNameField(_("Name: ")) @@ -253,7 +270,9 @@ class PartitionStretchy(Stretchy): max_size += self.partition.size fs = self.partition.fs() if fs is not None: - if partition.flag != "boot": + if fs.preserve: + initial['fstype'] = None + elif partition.flag != "boot": initial['fstype'] = fs.fstype if self.model.is_mounted_filesystem(fs.fstype): mount = fs.mount() @@ -275,7 +294,8 @@ class PartitionStretchy(Stretchy): x += 1 initial['name'] = name - self.form = PartitionForm(self.model, max_size, initial, lvm_names) + self.form = PartitionForm( + self.model, max_size, initial, lvm_names, partition) if not isinstance(disk, LVM_VolGroup): self.form.remove_field('name') @@ -297,6 +317,9 @@ class PartitionStretchy(Stretchy): self.form.mount.enabled = False self.form.fstype.enabled = False self.form.size.enabled = False + if partition.preserve: + self.form.name.enabled = False + self.form.size.enabled = False connect_signal(self.form, 'submit', self.done) connect_signal(self.form, 'cancel', self.cancel) @@ -373,6 +396,10 @@ class FormatEntireStretchy(Stretchy): initial = {} fs = device.fs() if fs is not None: + if fs.preserve: + initial['fstype'] = None + else: + initial['fstype'] = fs.fstype initial['fstype'] = fs.fstype if self.model.is_mounted_filesystem(fs.fstype): mount = fs.mount() @@ -380,7 +407,7 @@ class FormatEntireStretchy(Stretchy): initial['mount'] = mount.path elif not isinstance(device, Disk): initial['fstype'] = 'ext4' - self.form = PartitionForm(self.model, 0, initial, None) + self.form = PartitionForm(self.model, 0, initial, None, device) self.form.remove_field('size') self.form.remove_field('name') diff --git a/subiquity/ui/views/filesystem/tests/test_partition.py b/subiquity/ui/views/filesystem/tests/test_partition.py index f5edd88a..4ba8247b 100644 --- a/subiquity/ui/views/filesystem/tests/test_partition.py +++ b/subiquity/ui/views/filesystem/tests/test_partition.py @@ -73,6 +73,26 @@ class PartitionViewTests(unittest.TestCase): view.controller.partition_disk_handler.assert_called_once_with( stretchy.disk, stretchy.partition, expected_data) + def test_edit_existing_partition(self): + form_data = { + 'fstype': "xfs", + } + model, disk = make_model_and_disk() + partition = model.add_partition(disk, 512*(2**20)) + partition.preserve = True + model.add_filesystem(partition, "ext4") + view, stretchy = make_view(model, disk, partition) + self.assertFalse(stretchy.form.size.enabled) + self.assertTrue(stretchy.form.done_btn.enabled) + view_helpers.enter_data(stretchy.form, form_data) + view_helpers.click(stretchy.form.done_btn.base_widget) + expected_data = { + 'fstype': 'xfs', + 'mount': None, + } + view.controller.partition_disk_handler.assert_called_once_with( + stretchy.disk, stretchy.partition, expected_data) + def test_edit_boot_partition(self): form_data = { 'size': "256M", diff --git a/subiquitycore/testing/view_helpers.py b/subiquitycore/testing/view_helpers.py index 6ca257e1..ae66aab4 100644 --- a/subiquitycore/testing/view_helpers.py +++ b/subiquitycore/testing/view_helpers.py @@ -82,4 +82,6 @@ def get_focus_path(w): def enter_data(form, data): for k, v in data.items(): - getattr(form, k).value = v + bf = getattr(form, k) + assert bf.enabled, "%s is not enabled" % (k,) + bf.value = v From f3ffd9b8e9babe68db24081ba6d5666cce11f8da Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Tue, 28 May 2019 23:25:32 +1200 Subject: [PATCH 04/23] add new/existing annotations --- subiquity/models/filesystem.py | 12 ++++++++++- subiquity/models/tests/test_filesystem.py | 26 +++++++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/subiquity/models/filesystem.py b/subiquity/models/filesystem.py index a822a7ae..e76bc999 100644 --- a/subiquity/models/filesystem.py +++ b/subiquity/models/filesystem.py @@ -385,7 +385,13 @@ class _Formattable(ABC): @property def annotations(self): - return [] + preserve = getattr(self, 'preserve', None) + if preserve is None: + return [] + elif preserve: + return [_("existing")] + else: + return [_("new")] # Filesystem _fs = attributes.backlink() @@ -604,6 +610,10 @@ class Disk(_Device): def size(self): return align_down(self._info.size) + @property + def annotations(self): + return [] + def desc(self): return _("local disk") diff --git a/subiquity/models/tests/test_filesystem.py b/subiquity/models/tests/test_filesystem.py index bc7bf575..70e54865 100644 --- a/subiquity/models/tests/test_filesystem.py +++ b/subiquity/models/tests/test_filesystem.py @@ -180,16 +180,38 @@ def make_model_and_lv(bootloader=None): class TestFilesystemModel(unittest.TestCase): + def test_disk_annotations(self): + # disks never have annotations + model, disk = make_model_and_disk() + self.assertEqual(disk.annotations, []) + disk.preserve = True + self.assertEqual(disk.annotations, []) + + def test_partition_annotations(self): + model, disk = make_model_and_disk() + part = model.add_partition(disk, size=disk.free_for_partitions) + self.assertEqual(part.annotations, ['new']) + part.preserve = True + self.assertEqual(part.annotations, ['existing']) + part.flag = "boot" + self.assertEqual(part.annotations, ['existing', 'ESP']) + part.flag = "prep" + self.assertEqual(part.annotations, ['existing', 'PReP']) + part.flag = "bios_grub" + self.assertEqual(part.annotations, ['existing', 'bios_grub']) + def test_vg_default_annotations(self): model, disk = make_model_and_disk() vg = model.add_volgroup('vg-0', {disk}) - self.assertEqual(vg.annotations, []) + self.assertEqual(vg.annotations, ['new']) + vg.preserve = True + self.assertEqual(vg.annotations, ['existing']) def test_vg_encrypted_annotations(self): model, disk = make_model_and_disk() dm_crypt = model.add_dm_crypt(disk, key='passw0rd') vg = model.add_volgroup('vg-0', {dm_crypt}) - self.assertEqual(vg.annotations, ['encrypted']) + self.assertEqual(vg.annotations, ['new', 'encrypted']) def _test_ok_for_xxx(self, model, make_new_device, attr, test_partitions=True): From 4b45d02f730a59dfd29b32cc0ee06ed632585fbe Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Wed, 29 May 2019 16:07:03 +1200 Subject: [PATCH 05/23] adjust usage labels --- subiquity/models/filesystem.py | 10 +++++++++- subiquity/models/tests/test_filesystem.py | 19 ++++++++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/subiquity/models/filesystem.py b/subiquity/models/filesystem.py index e76bc999..1e95caa3 100644 --- a/subiquity/models/filesystem.py +++ b/subiquity/models/filesystem.py @@ -410,13 +410,21 @@ class _Formattable(ABC): ] fs = self.fs() if fs is not None: - r = [_("formatted as {fstype}").format(fstype=fs.fstype)] + if fs.preserve: + format_desc = _("already formatted as {fstype}") + elif self.original_fs() is not None: + format_desc = _("to be reformatted as {fstype}") + else: + format_desc = _("to be formatted as {fstype}") + r = [format_desc.format(fstype=fs.fstype)] if self._m.is_mounted_filesystem(fs.fstype): m = fs.mount() if m: r.append(_("mounted at {path}").format(path=m.path)) else: r.append(_("not mounted")) + elif fs.preserve and fs.mount() is not None: + r.append(_("unused")) return r else: return [_("unused")] diff --git a/subiquity/models/tests/test_filesystem.py b/subiquity/models/tests/test_filesystem.py index 70e54865..ce571b09 100644 --- a/subiquity/models/tests/test_filesystem.py +++ b/subiquity/models/tests/test_filesystem.py @@ -273,10 +273,23 @@ class TestFilesystemModel(unittest.TestCase): self.assertEqual(partition.usage_labels(), ["unused"]) fs = model.add_filesystem(partition, 'ext4') self.assertEqual( - partition.usage_labels(), ["formatted as ext4", "not mounted"]) - model.add_mount(fs, '/') + partition.usage_labels(), + ["to be formatted as ext4", "not mounted"]) + partition._original_fs = fs + fs.preserve = True + partition.preserve = True self.assertEqual( - partition.usage_labels(), ["formatted as ext4", "mounted at /"]) + partition.usage_labels(), + ["already formatted as ext4", "not mounted"]) + model.remove_filesystem(fs) + fs2 = model.add_filesystem(partition, 'ext4') + self.assertEqual( + partition.usage_labels(), + ["to be reformatted as ext4", "not mounted"]) + model.add_mount(fs2, '/') + self.assertEqual( + partition.usage_labels(), + ["to be reformatted as ext4", "mounted at /"]) def assertActionNotSupported(self, obj, action): self.assertNotIn(action, obj.supported_actions) From 4c3a46669bafa7e914ef2efb7b1419b22971cc94 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Wed, 29 May 2019 12:58:45 +1200 Subject: [PATCH 06/23] fix up enabling of actions in face of preexisting things --- subiquity/models/filesystem.py | 84 ++++++++++++- subiquity/models/tests/test_filesystem.py | 143 ++++++++++++++++++++-- 2 files changed, 209 insertions(+), 18 deletions(-) diff --git a/subiquity/models/filesystem.py b/subiquity/models/filesystem.py index 1e95caa3..af3265eb 100644 --- a/subiquity/models/filesystem.py +++ b/subiquity/models/filesystem.py @@ -338,6 +338,12 @@ def _generic_can_REMOVE(obj): cd = obj.constructed_device() if cd is None: return False + if cd.preserve: + return _("Cannot remove selflabel from pre-exsting {cdtype} " + "{cdlabel}").format( + selflabel=obj.label, + cdtype=cd.desc(), + cdlabel=cd.label) if isinstance(cd, Raid): if obj in cd.spare_devices: return True @@ -535,6 +541,13 @@ class _Device(_Formattable, ABC): return True return False + def _has_preexisting_partition(self): + for p in self._partitions: + if p.preserve: + return True + else: + return False + @property def _can_DELETE(self): mounted_partitions = 0 @@ -631,6 +644,33 @@ class Disk(_Device): return self.serial return self.path + def _potential_boot_partition(self): + if self._m.bootloader == Bootloader.NONE: + return None + if not self._partitions: + return None + if self._m.bootloader == Bootloader.BIOS: + if self._partitions[0].flag == "bios_grub": + return self._partitions[0] + else: + return None + flag = { + Bootloader.UEFI: "boot", + Bootloader.PREP: "prep", + }[self._m.bootloader] + for p in self._partitions: + # XXX should check not extended in the UEFI case too (until we fix + # that bug) + if p.flag == flag: + return p + return None + + def _can_be_boot_disk(self): + if self._m.bootloader == Bootloader.BIOS and self.ptable == "msdos": + return True + else: + return self._potential_boot_partition() is not None + @property def supported_actions(self): actions = [ @@ -644,7 +684,21 @@ class Disk(_Device): return actions _can_INFO = True - _can_PARTITION = property(lambda self: self.free_for_partitions > 0) + + @property + def _can_REFORMAT(self): + if not self.preserve: + return False + if len(self._partitions) == 0: + return False + for p in self._partitions: + if p._constructed_device is not None: + return False + return True + + _can_PARTITION = property( + lambda self: not self._has_preexisting_partition() and + self.free_for_partitions > 0) _can_FORMAT = property( lambda self: len(self._partitions) == 0 and self._constructed_device is None) @@ -664,7 +718,10 @@ class Disk(_Device): install_dev = self._m.grub_install_device if install_dev is not None and install_dev.device is self: return False - return self._fs is None and self._constructed_device is None + if self._has_preexisting_partition(): + return self._can_be_boot_disk() + else: + return self._fs is None and self._constructed_device is None @property def ok_for_raid(self): @@ -735,10 +792,14 @@ class Partition(_Formattable): ] _can_EDIT = property(_generic_can_EDIT) + _can_REMOVE = property(_generic_can_REMOVE) @property def _can_DELETE(self): + if self.device._has_preexisting_partition(): + return _("Cannot delete a single partition from a device that " + "already has partitions.") if self.flag in ('boot', 'bios_grub', 'prep'): return _("Cannot delete required bootloader partition") return _generic_can_DELETE(self) @@ -794,7 +855,9 @@ class Raid(_Device): @property def _can_EDIT(self): - if len(self._partitions) > 0: + if self.preserve: + return _("Cannot edit pre-existing RAIDs.") + elif len(self._partitions) > 0: return _( "Cannot edit {selflabel} because it has partitions.").format( selflabel=self.label) @@ -861,7 +924,9 @@ class LVM_VolGroup(_Device): @property def _can_EDIT(self): - if len(self._partitions) > 0: + if self.preserve: + return _("Cannot edit pre-existing volume groups.") + elif len(self._partitions) > 0: return _( "Cannot edit {selflabel} because it has logical " "volumes.").format( @@ -869,7 +934,8 @@ class LVM_VolGroup(_Device): else: return _generic_can_EDIT(self) - _can_CREATE_LV = Disk._can_PARTITION + _can_CREATE_LV = property( + lambda self: not self.preserve and self.free_for_partitions > 0) ok_for_raid = False ok_for_lvm_vg = False @@ -915,7 +981,13 @@ class LVM_LogicalVolume(_Formattable): ] _can_EDIT = True - _can_DELETE = True + + @property + def _can_DELETE(self): + if self.volgroup._has_preexisting_partition(): + return _("Cannot delete a single logical volume from a volume " + "group that already has logical volumes.") + return True ok_for_raid = False ok_for_lvm_vg = False diff --git a/subiquity/models/tests/test_filesystem.py b/subiquity/models/tests/test_filesystem.py index ce571b09..44598cbb 100644 --- a/subiquity/models/tests/test_filesystem.py +++ b/subiquity/models/tests/test_filesystem.py @@ -117,12 +117,14 @@ def make_model(bootloader=None): return model -def make_disk(model): +def make_disk(model, **kw): serial = 'serial%s' % len(model._actions) model._actions.append(Disk( m=model, serial=serial, - info=FakeStorageInfo(size=100*(2**30)))) - return model._actions[-1] + info=FakeStorageInfo(size=100*(2**30)), + **kw)) + disk = model._actions[-1] + return disk def make_model_and_disk(bootloader=None): @@ -130,12 +132,12 @@ def make_model_and_disk(bootloader=None): return model, make_disk(model) -def make_partition(model, device=None, *, size=None, flag=""): +def make_partition(model, device=None, *, size=None, **kw): if device is None: device = make_disk(model) if size is None: size = device.free_for_partitions//2 - partition = Partition(m=model, device=device, size=size, flag=flag) + partition = Partition(m=model, device=device, size=size, **kw) model._actions.append(partition) return partition @@ -307,12 +309,24 @@ class TestFilesystemModel(unittest.TestCase): vg = model.add_volgroup('vg1', {objects[0], objects[1]}) self.assertActionPossible(objects[0], DeviceAction.REMOVE) + + # Cannot remove a device from a preexisting VG + vg.preserve = True + self.assertActionNotPossible(objects[0], DeviceAction.REMOVE) + vg.preserve = False + # Probably this removal should be a model method? vg.devices.remove(objects[1]) objects[1]._constructed_device = None self.assertActionNotPossible(objects[0], DeviceAction.REMOVE) raid = model.add_raid('md0', 'raid1', set(objects[2:]), set()) self.assertActionPossible(objects[2], DeviceAction.REMOVE) + + # Cannot remove a device from a preexisting RAID + raid.preserve = True + self.assertActionNotPossible(objects[2], DeviceAction.REMOVE) + raid.preserve = False + # Probably this removal should be a model method? raid.devices.remove(objects[4]) objects[4]._constructed_device = None @@ -334,6 +348,14 @@ class TestFilesystemModel(unittest.TestCase): make_partition(model, disk, size=disk.free_for_partitions) self.assertActionNotPossible(disk, DeviceAction.PARTITION) + # Can partition a disk with .preserve=True + disk2 = make_disk(model) + disk2.preserve = True + self.assertActionPossible(disk2, DeviceAction.PARTITION) + # But not if it has a partition. + make_partition(model, disk2, preserve=True) + self.assertActionNotPossible(disk2, DeviceAction.PARTITION) + def test_disk_action_CREATE_LV(self): model, disk = make_model_and_disk() self.assertActionNotSupported(disk, DeviceAction.CREATE_LV) @@ -356,13 +378,81 @@ class TestFilesystemModel(unittest.TestCase): model, disk = make_model_and_disk() self.assertActionNotSupported(disk, DeviceAction.DELETE) - def test_disk_action_MAKE_BOOT(self): - for bl in Bootloader: - model, disk = make_model_and_disk(bl) - if bl == Bootloader.NONE: - self.assertActionNotSupported(disk, DeviceAction.MAKE_BOOT) - else: - self.assertActionPossible(disk, DeviceAction.MAKE_BOOT) + def test_disk_action_MAKE_BOOT_NONE(self): + model, disk = make_model_and_disk(Bootloader.NONE) + self.assertActionNotSupported(disk, DeviceAction.MAKE_BOOT) + + def test_disk_action_MAKE_BOOT_BIOS(self): + model = make_model(Bootloader.BIOS) + # Disks with msdos partition tables can always be the BIOS boot disk. + dos_disk = make_disk(model, ptable='msdos', preserve=True) + self.assertActionPossible(dos_disk, DeviceAction.MAKE_BOOT) + # Even if they have existing partitions + make_partition( + model, dos_disk, size=dos_disk.free_for_partitions, preserve=True) + self.assertActionPossible(dos_disk, DeviceAction.MAKE_BOOT) + # (we never create dos partition tables so no need to test + # preserve=False case). + + # GPT disks with new partition tables can always be the BIOS boot disk + gpt_disk = make_disk(model, ptable='gpt', preserve=False) + self.assertActionPossible(gpt_disk, DeviceAction.MAKE_BOOT) + # Even if they are filled with partitions (we resize partitions to fit) + make_partition(model, gpt_disk, size=dos_disk.free_for_partitions) + self.assertActionPossible(gpt_disk, DeviceAction.MAKE_BOOT) + + # GPT disks with existing partition tables but no partitions can be the + # BIOS boot disk (in general we ignore existing empty partition tables) + gpt_disk2 = make_disk(model, ptable='gpt', preserve=True) + self.assertActionPossible(gpt_disk2, DeviceAction.MAKE_BOOT) + # If there is an existing *partition* though, it cannot be the boot + # disk + make_partition(model, gpt_disk2, preserve=True) + self.assertActionNotPossible(gpt_disk2, DeviceAction.MAKE_BOOT) + # Unless there is already a bios_grub partition we can reuse + gpt_disk3 = make_disk(model, ptable='gpt', preserve=True) + make_partition( + model, gpt_disk3, flag="bios_grub", preserve=True) + make_partition( + model, gpt_disk3, preserve=True) + self.assertActionPossible(gpt_disk3, DeviceAction.MAKE_BOOT) + # Edge case city: the bios_grub partition has to be first + gpt_disk4 = make_disk(model, ptable='gpt', preserve=True) + make_partition( + model, gpt_disk4, preserve=True) + make_partition( + model, gpt_disk4, flag="bios_grub", preserve=True) + self.assertActionNotPossible(gpt_disk4, DeviceAction.MAKE_BOOT) + + def _test_MAKE_BOOT_boot_partition(self, bl, flag): + # The logic for when MAKE_BOOT is enabled for both UEFI and PREP + # bootloaders turns out to be the same, modulo the special flag that + # has to be present on a partition. + model = make_model(bl) + # A disk with a new partition table can always be the UEFI/PREP boot + # disk. + new_disk = make_disk(model, preserve=False) + self.assertActionPossible(new_disk, DeviceAction.MAKE_BOOT) + # Even if they are filled with partitions (we resize partitions to fit) + make_partition(model, new_disk, size=new_disk.free_for_partitions) + self.assertActionPossible(new_disk, DeviceAction.MAKE_BOOT) + + # A disk with an existing but empty partitions can also be the + # UEFI/PREP boot disk. + old_disk = make_disk(model, preserve=True) + self.assertActionPossible(old_disk, DeviceAction.MAKE_BOOT) + # If there is an existing partition though, it cannot. + make_partition(model, old_disk, preserve=True) + self.assertActionNotPossible(old_disk, DeviceAction.MAKE_BOOT) + # If there is an existing ESP/PReP partition though, fine! + make_partition(model, old_disk, flag=flag, preserve=True) + self.assertActionPossible(old_disk, DeviceAction.MAKE_BOOT) + + def test_disk_action_MAKE_BOOT_UEFI(self): + self._test_MAKE_BOOT_boot_partition(Bootloader.UEFI, "boot") + + def test_disk_action_MAKE_BOOT_PREP(self): + self._test_MAKE_BOOT_boot_partition(Bootloader.PREP, "prep") def test_partition_action_INFO(self): model, part = make_model_and_partition() @@ -413,6 +503,12 @@ class TestFilesystemModel(unittest.TestCase): part = make_partition(model, flag=flag) self.assertActionNotPossible(part, DeviceAction.DELETE) + # You cannot delete a partition from a disk that has + # pre-existing partitions (only reformat) + disk2 = make_disk(model, preserve=True) + disk2p1 = make_partition(model, disk2, preserve=True) + self.assertActionNotPossible(disk2p1, DeviceAction.DELETE) + def test_partition_action_MAKE_BOOT(self): model, part = make_model_and_partition() self.assertActionNotSupported(part, DeviceAction.MAKE_BOOT) @@ -431,6 +527,10 @@ class TestFilesystemModel(unittest.TestCase): make_partition(model, raid2) self.assertActionNotPossible(raid2, DeviceAction.EDIT) + raid3 = make_raid(model) + raid3.preserve = True + self.assertActionNotPossible(raid3, DeviceAction.EDIT) + def test_raid_action_PARTITION(self): model, raid = make_model_and_raid() self.assertActionPossible(raid, DeviceAction.PARTITION) @@ -439,6 +539,14 @@ class TestFilesystemModel(unittest.TestCase): make_partition(model, raid, size=raid.free_for_partitions) self.assertActionNotPossible(raid, DeviceAction.PARTITION) + # Can partition a raid with .preserve=True + raid2 = make_raid(model) + raid2.preserve = True + self.assertActionPossible(raid2, DeviceAction.PARTITION) + # But not if it has a partition. + make_partition(model, raid2, preserve=True) + self.assertActionNotPossible(raid2, DeviceAction.PARTITION) + def test_raid_action_CREATE_LV(self): model, raid = make_model_and_raid() self.assertActionNotSupported(raid, DeviceAction.CREATE_LV) @@ -494,6 +602,10 @@ class TestFilesystemModel(unittest.TestCase): model.add_logical_volume(vg, 'lv1', size=vg.free_for_partitions//2) self.assertActionNotPossible(vg, DeviceAction.EDIT) + vg2 = make_vg(model) + vg2.preserve = True + self.assertActionNotPossible(vg2, DeviceAction.EDIT) + def test_vg_action_PARTITION(self): model, vg = make_model_and_vg() self.assertActionNotSupported(vg, DeviceAction.PARTITION) @@ -505,6 +617,9 @@ class TestFilesystemModel(unittest.TestCase): self.assertActionPossible(vg, DeviceAction.CREATE_LV) model.add_logical_volume(vg, 'lv2', size=vg.free_for_partitions) self.assertActionNotPossible(vg, DeviceAction.CREATE_LV) + vg2 = make_vg(model) + vg2.preserve = True + self.assertActionNotPossible(vg2, DeviceAction.CREATE_LV) def test_vg_action_FORMAT(self): model, vg = make_model_and_vg() @@ -562,6 +677,10 @@ class TestFilesystemModel(unittest.TestCase): model.add_mount(fs, '/') self.assertActionPossible(lv, DeviceAction.DELETE) + lv2 = make_lv(model) + lv2.preserve = lv2.volgroup.preserve = True + self.assertActionNotPossible(lv2, DeviceAction.DELETE) + def test_lv_action_MAKE_BOOT(self): model, lv = make_model_and_lv() self.assertActionNotSupported(lv, DeviceAction.MAKE_BOOT) From 2f844d09d38150006232c93411732277f79e068a Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Wed, 29 May 2019 13:01:21 +1200 Subject: [PATCH 07/23] the REFORMAT action --- subiquity/controllers/filesystem.py | 5 ++ subiquity/models/filesystem.py | 2 + subiquity/models/tests/test_filesystem.py | 33 +++++++++++ subiquity/ui/views/filesystem/delete.py | 63 +++++++++++++++++++++ subiquity/ui/views/filesystem/filesystem.py | 6 +- 5 files changed, 107 insertions(+), 2 deletions(-) diff --git a/subiquity/controllers/filesystem.py b/subiquity/controllers/filesystem.py index f3d7ea25..b230532e 100644 --- a/subiquity/controllers/filesystem.py +++ b/subiquity/controllers/filesystem.py @@ -389,6 +389,11 @@ class FilesystemController(BaseController): for subobj in obj.fs(), obj.constructed_device(): self.delete(subobj) + def reformat(self, disk): + self.clear(disk) + for p in list(disk.partitions()): + self.delete(p) + def partition_disk_handler(self, disk, partition, spec): log.debug('partition_disk_handler: %s %s %s', disk, partition, spec) log.debug('disk.freespace: {}'.format(disk.free_for_partitions)) diff --git a/subiquity/models/filesystem.py b/subiquity/models/filesystem.py index af3265eb..beac0937 100644 --- a/subiquity/models/filesystem.py +++ b/subiquity/models/filesystem.py @@ -314,6 +314,7 @@ def asdict(inst): class DeviceAction(enum.Enum): INFO = _("Info") EDIT = _("Edit") + REFORMAT = _("Reformat") PARTITION = _("Add Partition") CREATE_LV = _("Create Logical Volume") FORMAT = _("Format") @@ -675,6 +676,7 @@ class Disk(_Device): def supported_actions(self): actions = [ DeviceAction.INFO, + DeviceAction.REFORMAT, DeviceAction.PARTITION, DeviceAction.FORMAT, DeviceAction.REMOVE, diff --git a/subiquity/models/tests/test_filesystem.py b/subiquity/models/tests/test_filesystem.py index 44598cbb..ea1e9416 100644 --- a/subiquity/models/tests/test_filesystem.py +++ b/subiquity/models/tests/test_filesystem.py @@ -340,6 +340,23 @@ class TestFilesystemModel(unittest.TestCase): model, disk = make_model_and_disk() self.assertActionNotSupported(disk, DeviceAction.EDIT) + def test_disk_action_REFORMAT(self): + model = make_model() + + disk1 = make_disk(model, preserve=False) + self.assertActionNotPossible(disk1, DeviceAction.REFORMAT) + + disk2 = make_disk(model, preserve=True) + self.assertActionNotPossible(disk2, DeviceAction.REFORMAT) + disk2p1 = make_partition(model, disk2, preserve=True) + self.assertActionPossible(disk2, DeviceAction.REFORMAT) + model.add_volgroup('vg0', {disk2p1}) + self.assertActionNotPossible(disk2, DeviceAction.REFORMAT) + + disk3 = make_disk(model, preserve=True) + model.add_volgroup('vg1', {disk3}) + self.assertActionNotPossible(disk3, DeviceAction.REFORMAT) + def test_disk_action_PARTITION(self): model, disk = make_model_and_disk() self.assertActionPossible(disk, DeviceAction.PARTITION) @@ -464,6 +481,10 @@ class TestFilesystemModel(unittest.TestCase): model.add_volgroup('vg1', {part}) self.assertActionNotPossible(part, DeviceAction.EDIT) + def test_partition_action_REFORMAT(self): + model, part = make_model_and_partition() + self.assertActionNotSupported(part, DeviceAction.REFORMAT) + def test_partition_action_PARTITION(self): model, part = make_model_and_partition() self.assertActionNotSupported(part, DeviceAction.PARTITION) @@ -531,6 +552,10 @@ class TestFilesystemModel(unittest.TestCase): raid3.preserve = True self.assertActionNotPossible(raid3, DeviceAction.EDIT) + def test_raid_action_REFORMAT(self): + model, raid = make_model_and_raid() + self.assertActionNotSupported(raid, DeviceAction.REFORMAT) + def test_raid_action_PARTITION(self): model, raid = make_model_and_raid() self.assertActionPossible(raid, DeviceAction.PARTITION) @@ -606,6 +631,10 @@ class TestFilesystemModel(unittest.TestCase): vg2.preserve = True self.assertActionNotPossible(vg2, DeviceAction.EDIT) + def test_vg_action_REFORMAT(self): + model, vg = make_model_and_vg() + self.assertActionNotSupported(vg, DeviceAction.REFORMAT) + def test_vg_action_PARTITION(self): model, vg = make_model_and_vg() self.assertActionNotSupported(vg, DeviceAction.PARTITION) @@ -653,6 +682,10 @@ class TestFilesystemModel(unittest.TestCase): model, lv = make_model_and_lv() self.assertActionPossible(lv, DeviceAction.EDIT) + def test_lv_action_REFORMAT(self): + model, lv = make_model_and_lv() + self.assertActionNotSupported(lv, DeviceAction.REFORMAT) + def test_lv_action_PARTITION(self): model, lv = make_model_and_lv() self.assertActionNotSupported(lv, DeviceAction.PARTITION) diff --git a/subiquity/ui/views/filesystem/delete.py b/subiquity/ui/views/filesystem/delete.py index affc7a85..b1fd4da6 100644 --- a/subiquity/ui/views/filesystem/delete.py +++ b/subiquity/ui/views/filesystem/delete.py @@ -96,3 +96,66 @@ class ConfirmDeleteStretchy(Stretchy): def cancel(self, sender=None): self.parent.remove_overlay() + + +class ConfirmReformatStretchy(Stretchy): + + def __init__(self, parent, obj): + self.parent = parent + self.obj = obj + + fs = obj.fs() + if fs is not None: + title = _("Remove filesystem from {}").format(obj.desc()) + lines = [ + _( + "Do you really want to remove the existing filesystem " + "from {}?" + ).format(obj.label), + "", + ] + m = fs.mount() + if m is not None: + lines.append(_( + "It is formatted as {fstype} and mounted at " + "{path}").format( + fstype=fs.fstype, + path=m.path)) + else: + lines.append(_( + "It is formatted as {fstype} and not mounted.").format( + fstype=fs.fstype)) + else: + if obj.type == "lvm_volgroup": + things = _("logical volumes") + else: + things = _("partitions") + title = _("Remove all {things} from {obj}").format( + things=things, obj=obj.desc()) + lines = [ + _( + "Do you really want to remove all {things} from " + "{obj}?").format( + things=things, obj=obj.label), + "", + ] + # XXX summarize partitions here? + + delete_btn = danger_btn(label=_("Reformat"), on_press=self.confirm) + widgets = [ + Text("\n".join(lines)), + Text(""), + button_pile([ + delete_btn, + other_btn(label=_("Cancel"), on_press=self.cancel), + ]), + ] + super().__init__(title, widgets, 0, 2) + + def confirm(self, sender=None): + self.parent.controller.reformat(self.obj) + self.parent.refresh_model_inputs() + self.parent.remove_overlay() + + def cancel(self, sender=None): + self.parent.remove_overlay() diff --git a/subiquity/ui/views/filesystem/filesystem.py b/subiquity/ui/views/filesystem/filesystem.py index dc1a55a1..b1c17b58 100644 --- a/subiquity/ui/views/filesystem/filesystem.py +++ b/subiquity/ui/views/filesystem/filesystem.py @@ -67,7 +67,7 @@ from subiquity.models.filesystem import ( humanize_size, ) -from .delete import ConfirmDeleteStretchy +from .delete import ConfirmDeleteStretchy, ConfirmReformatStretchy from .disk_info import DiskInfoStretchy from .helpers import summarize_device from .lvm import VolGroupStretchy @@ -289,6 +289,7 @@ class DeviceList(WidgetWrap): super().__init__(self.table) _disk_INFO = _stretchy_shower(DiskInfoStretchy) + _disk_REFORMAT = _stretchy_shower(ConfirmReformatStretchy) _disk_PARTITION = _stretchy_shower(PartitionStretchy) _disk_FORMAT = _stretchy_shower(FormatEntireStretchy) @@ -353,7 +354,8 @@ class DeviceList(WidgetWrap): else: meth_name = '_{}_{}'.format(device.type, action.name) meth = getattr(self, meth_name) - if not whynot and action == DeviceAction.DELETE: + if not whynot and action in [DeviceAction.DELETE, + DeviceAction.REFORMAT]: label = Color.danger_button(ActionMenuOpenButton(label)) device_actions.append(Action( label=label, From 97952ef9bebe64702ac4a0dc49665dab3c1b3108 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Wed, 29 May 2019 15:46:03 +1200 Subject: [PATCH 08/23] adapt make_boot_disk for existing boot partitions --- subiquity/controllers/filesystem.py | 60 ++++++++++---- .../controllers/tests/test_filesystem.py | 80 +++++++++++++++++-- 2 files changed, 117 insertions(+), 23 deletions(-) diff --git a/subiquity/controllers/filesystem.py b/subiquity/controllers/filesystem.py index b230532e..d21c9440 100644 --- a/subiquity/controllers/filesystem.py +++ b/subiquity/controllers/filesystem.py @@ -484,21 +484,47 @@ class FilesystemController(BaseController): def make_boot_disk(self, new_boot_disk): boot_partition = None - for disk in self.model.all_disks(): - for part in disk.partitions(): - if part.flag in ("bios_grub", "boot", "prep"): - boot_partition = part + if self.model.bootloader == Bootloader.BIOS: + install_dev = self.model.grub_install_device + if install_dev: + boot_partition = install_dev._potential_boot_partition() + elif self.model.bootloader == Bootloader.UEFI: + mount = self.model._mount_for_path("/boot/efi") + if mount is not None: + boot_partition = mount.device.volume + elif self.model.bootloader == Bootloader.PREP: + boot_partition = self.model.grub_install_device if boot_partition is not None: - boot_disk = boot_partition.device - full = boot_disk.free_for_partitions == 0 - self.delete_partition(boot_partition) - if full: - largest_part = max( - boot_disk.partitions(), key=lambda p: p.size) - largest_part.size += boot_partition.size - if new_boot_disk.free_for_partitions < boot_partition.size: - largest_part = max( - new_boot_disk.partitions(), key=lambda p: p.size) - largest_part.size -= ( - boot_partition.size - new_boot_disk.free_for_partitions) - self._create_boot_partition(new_boot_disk) + if boot_partition.preserve: + if self.model.bootloader == Bootloader.PREP: + boot_partition.wipe = None + elif self.model.bootloader == Bootloader.UEFI: + self.delete_mount(boot_partition.fs().mount()) + else: + boot_disk = boot_partition.device + full = boot_disk.free_for_partitions == 0 + self.delete_partition(boot_partition) + if full: + largest_part = max( + boot_disk.partitions(), key=lambda p: p.size) + largest_part.size += boot_partition.size + if new_boot_disk.free_for_partitions < boot_partition.size: + largest_part = max( + new_boot_disk.partitions(), key=lambda p: p.size) + largest_part.size -= ( + boot_partition.size - + new_boot_disk.free_for_partitions) + if new_boot_disk._has_preexisting_partition(): + if self.model.bootloader == Bootloader.BIOS: + self.model.grub_install_device = new_boot_disk + elif self.model.bootloader == Bootloader.UEFI: + part = new_boot_disk._potential_boot_partition() + if part.fs() is None: + self.model.add_filesystem(part, 'fat32') + self.model.add_mount(part.fs(), '/boot/efi') + elif self.model.bootloader == Bootloader.PREP: + part = new_boot_disk._potential_boot_partition() + part.wipe = 'zero' + self.model.grub_install_device = part + else: + self._create_boot_partition(new_boot_disk) diff --git a/subiquity/controllers/tests/test_filesystem.py b/subiquity/controllers/tests/test_filesystem.py index e302e9a1..055ed3e9 100644 --- a/subiquity/controllers/tests/test_filesystem.py +++ b/subiquity/controllers/tests/test_filesystem.py @@ -83,8 +83,8 @@ class TestFilesystemController(unittest.TestCase): def test_make_boot_disk_BIOS(self): controller = make_controller(Bootloader.BIOS) - disk1 = make_disk(controller.model) - disk2 = make_disk(controller.model) + disk1 = make_disk(controller.model, preserve=False) + disk2 = make_disk(controller.model, preserve=False) disk2p1 = controller.model.add_partition( disk2, size=disk2.free_for_partitions) @@ -103,10 +103,28 @@ class TestFilesystemController(unittest.TestCase): self.assertEqual(disk2.partitions()[0].flag, "bios_grub") self.assertEqual(controller.model.grub_install_device, disk2) + def test_make_boot_disk_BIOS_existing(self): + controller = make_controller(Bootloader.BIOS) + disk1 = make_disk(controller.model, preserve=True) + disk1p1 = controller.model.add_partition( + disk1, size=1 << 20, flag="bios_grub") + disk1p1.preserve = True + disk2 = make_disk(controller.model, preserve=False) + + self.assertEqual(disk1.partitions(), [disk1p1]) + self.assertEqual(controller.model.grub_install_device, None) + controller.make_boot_disk(disk1) + self.assertEqual(disk1.partitions(), [disk1p1]) + self.assertEqual(controller.model.grub_install_device, disk1) + + controller.make_boot_disk(disk2) + self.assertEqual(disk1.partitions(), [disk1p1]) + self.assertEqual(controller.model.grub_install_device, disk2) + def test_make_boot_disk_UEFI(self): controller = make_controller(Bootloader.UEFI) - disk1 = make_disk(controller.model) - disk2 = make_disk(controller.model) + disk1 = make_disk(controller.model, preserve=False) + disk2 = make_disk(controller.model, preserve=False) disk2p1 = controller.model.add_partition( disk2, size=disk2.free_for_partitions) @@ -130,10 +148,35 @@ class TestFilesystemController(unittest.TestCase): efi_mnt = controller.model._mount_for_path("/boot/efi") self.assertEqual(efi_mnt.device.volume, disk2.partitions()[0]) + def test_make_boot_disk_UEFI_existing(self): + controller = make_controller(Bootloader.UEFI) + disk1 = make_disk(controller.model, preserve=True) + disk1p1 = controller.model.add_partition( + disk1, size=512 << 20, flag="boot") + disk1p1.preserve = True + disk2 = make_disk(controller.model, preserve=True) + + self.assertEqual(disk1.partitions(), [disk1p1]) + self.assertEqual(controller.model.grub_install_device, None) + efi_mnt = controller.model._mount_for_path("/boot/efi") + self.assertEqual(efi_mnt, None) + controller.make_boot_disk(disk1) + self.assertEqual(disk1.partitions(), [disk1p1]) + self.assertEqual(controller.model.grub_install_device, None) + efi_mnt = controller.model._mount_for_path("/boot/efi") + self.assertEqual(efi_mnt.device.volume, disk1p1) + self.assertEqual(disk1p1.fs().fstype, "fat32") + + controller.make_boot_disk(disk2) + self.assertEqual(disk1.partitions(), [disk1p1]) + self.assertEqual(controller.model.grub_install_device, None) + efi_mnt = controller.model._mount_for_path("/boot/efi") + self.assertEqual(efi_mnt.device.volume, disk2.partitions()[0]) + def test_make_boot_disk_PREP(self): controller = make_controller(Bootloader.PREP) - disk1 = make_disk(controller.model) - disk2 = make_disk(controller.model) + disk1 = make_disk(controller.model, preserve=False) + disk2 = make_disk(controller.model, preserve=False) disk2p1 = controller.model.add_partition( disk2, size=disk2.free_for_partitions) @@ -157,3 +200,28 @@ class TestFilesystemController(unittest.TestCase): self.assertEqual( controller.model.grub_install_device, disk2.partitions()[0]) + + def test_make_boot_disk_PREP_existing(self): + controller = make_controller(Bootloader.PREP) + disk1 = make_disk(controller.model, preserve=True) + disk1p1 = controller.model.add_partition( + disk1, size=8 << 20, flag="prep") + disk1p1.preserve = True + disk2 = make_disk(controller.model, preserve=False) + + self.assertEqual(disk1.partitions(), [disk1p1]) + self.assertEqual(controller.model.grub_install_device, None) + controller.make_boot_disk(disk1) + self.assertEqual(disk1.partitions(), [disk1p1]) + self.assertEqual(controller.model.grub_install_device, disk1p1) + self.assertEqual(disk1p1.wipe, 'zero') + + controller.make_boot_disk(disk2) + self.assertEqual(disk1.partitions(), [disk1p1]) + self.assertEqual(disk1p1.wipe, None) + self.assertEqual( + controller.model.grub_install_device, disk2.partitions()[0]) + self.assertEqual(disk2.partitions()[0].flag, "prep") + self.assertEqual( + controller.model.grub_install_device, + disk2.partitions()[0]) From 52ee6cdde1c0583bc64bf06e26143ddc7ea06339 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Wed, 29 May 2019 15:56:17 +1200 Subject: [PATCH 09/23] use reformat instead of reset in guided disk selection --- subiquity/controllers/filesystem.py | 2 +- subiquity/ui/views/filesystem/guided.py | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/subiquity/controllers/filesystem.py b/subiquity/controllers/filesystem.py index d21c9440..f31c0f9c 100644 --- a/subiquity/controllers/filesystem.py +++ b/subiquity/controllers/filesystem.py @@ -235,7 +235,7 @@ class FilesystemController(BaseController): if self.answers['guided']: index = self.answers['guided-index'] disk = self.model.all_disks()[index] - v.choose_disk(None, disk.path) + v.choose_disk(None, disk) def reset(self): log.info("Resetting Filesystem model") diff --git a/subiquity/ui/views/filesystem/guided.py b/subiquity/ui/views/filesystem/guided.py index 032f9dca..ce1e8689 100644 --- a/subiquity/ui/views/filesystem/guided.py +++ b/subiquity/ui/views/filesystem/guided.py @@ -126,7 +126,7 @@ class GuidedDiskSelectionView(BaseView): if disk.size >= dehumanize_size("6G"): arrow = ClickableIcon(arrow) connect_signal( - arrow, 'click', self.choose_disk, disk.path) + arrow, 'click', self.choose_disk, disk) wrap = _wrap_button_row else: start, arrow, end = '', '', '' @@ -152,9 +152,8 @@ class GuidedDiskSelectionView(BaseView): def cancel(self, btn=None): self.controller.default() - def choose_disk(self, btn, disk_path): - self.model.reset() - disk = self.model.disk_by_path(disk_path) + def choose_disk(self, btn, disk): + self.controller.reformat(disk) if self.method == "direct": result = { "size": disk.free_for_partitions, From e63204afa992c2b868081af702b3b575a856f744 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Wed, 29 May 2019 15:57:55 +1200 Subject: [PATCH 10/23] mounting a partition of a disk that can be the boot disk makes it the boot disk --- subiquity/controllers/filesystem.py | 5 +++++ subiquity/controllers/tests/test_filesystem.py | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/subiquity/controllers/filesystem.py b/subiquity/controllers/filesystem.py index f31c0f9c..86fcbf5f 100644 --- a/subiquity/controllers/filesystem.py +++ b/subiquity/controllers/filesystem.py @@ -258,6 +258,11 @@ class FilesystemController(BaseController): if spec.get('mount') is None: return mount = self.model.add_mount(fs, spec['mount']) + if self.model.needs_bootloader_partition(): + vol = fs.volume + if vol.type == "partition" and vol.device.type == "disk": + if vol.device._can_be_boot_disk(): + self.make_boot_disk(vol.device) return mount def delete_mount(self, mount): diff --git a/subiquity/controllers/tests/test_filesystem.py b/subiquity/controllers/tests/test_filesystem.py index 055ed3e9..7274d0ed 100644 --- a/subiquity/controllers/tests/test_filesystem.py +++ b/subiquity/controllers/tests/test_filesystem.py @@ -225,3 +225,17 @@ class TestFilesystemController(unittest.TestCase): self.assertEqual( controller.model.grub_install_device, disk2.partitions()[0]) + + def test_mounting_partition_makes_boot_disk(self): + controller = make_controller(Bootloader.UEFI) + disk1 = make_disk(controller.model, preserve=True) + disk1p1 = controller.model.add_partition( + disk1, size=512 << 20, flag="boot") + disk1p1.preserve = True + disk1p2 = controller.model.add_partition( + disk1, size=disk1.free_for_partitions) + disk1p2.preserve = True + controller.partition_disk_handler( + disk1, disk1p2, {'fstype': 'ext4', 'mount': '/'}) + efi_mnt = controller.model._mount_for_path("/boot/efi") + self.assertEqual(efi_mnt.device.volume, disk1p1) From 83574fbc0be3907ea2256a9548138fc9be24ff5b Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Thu, 30 May 2019 10:13:21 +1200 Subject: [PATCH 11/23] mark formatted existing partions as ok_for_{raid,lvm_vg} as we do not support removing an exisiting format, this is required to be able to reuse these partitions! --- subiquity/models/filesystem.py | 6 ++++++ subiquity/models/tests/test_filesystem.py | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/subiquity/models/filesystem.py b/subiquity/models/filesystem.py index beac0937..d636d7dc 100644 --- a/subiquity/models/filesystem.py +++ b/subiquity/models/filesystem.py @@ -728,6 +728,8 @@ class Disk(_Device): @property def ok_for_raid(self): if self._fs is not None: + if self._fs.preserve: + return self._fs._mount is None return False if self._constructed_device is not None: return False @@ -811,6 +813,8 @@ class Partition(_Formattable): if self.flag in ('boot', 'bios_grub', 'prep'): return False if self._fs is not None: + if self._fs.preserve: + return self._fs._mount is None return False if self._constructed_device is not None: return False @@ -875,6 +879,8 @@ class Raid(_Device): @property def ok_for_raid(self): if self._fs is not None: + if self._fs.preserve: + return self._fs._mount is None return False if self._constructed_device is not None: return False diff --git a/subiquity/models/tests/test_filesystem.py b/subiquity/models/tests/test_filesystem.py index ea1e9416..d5300b88 100644 --- a/subiquity/models/tests/test_filesystem.py +++ b/subiquity/models/tests/test_filesystem.py @@ -229,6 +229,20 @@ class TestFilesystemModel(unittest.TestCase): dev3 = make_new_device() make_partition(model, dev3) self.assertFalse(getattr(dev3, attr)) + # Empty existing devices are ok + dev4 = make_new_device() + dev4.preserve = True + self.assertTrue(getattr(dev4, attr)) + # A dev with an existing filesystem is ok (there is no + # way to remove the format) + dev5 = make_new_device() + dev5.preserve = True + fs = model.add_filesystem(dev5, 'ext4') + fs.preserve = True + self.assertTrue(dev5.ok_for_raid) + # But a existing, *mounted* filesystem is not. + model.add_mount(fs, '/') + self.assertFalse(dev5.ok_for_raid) def test_disk_ok_for_xxx(self): model = make_model() From aef842a11f4874268460d3f009c5bf0cbcd19f16 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Thu, 30 May 2019 11:39:01 +1200 Subject: [PATCH 12/23] allow the user to choose whether to reformat the ESP --- subiquity/ui/mount.py | 4 +- subiquity/ui/views/filesystem/partition.py | 51 ++++++++++++++++++---- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/subiquity/ui/mount.py b/subiquity/ui/mount.py index 7f8349a0..54a63208 100644 --- a/subiquity/ui/mount.py +++ b/subiquity/ui/mount.py @@ -58,9 +58,9 @@ class MountSelector(WidgetWrap): opts.append((mnt, False)) if first_opt is None: first_opt = len(opts) - opts.append((_('other'), True, OTHER)) + opts.append((_('Other'), True, OTHER)) opts.append(('---', False)), - opts.append((_('leave unmounted'), True, LEAVE_UNMOUNTED)) + opts.append((_('Leave unmounted'), True, LEAVE_UNMOUNTED)) self._selector = Selector(opts, first_opt) connect_signal(self._selector, 'select', self._select_mount) self._other = _MountEditor() diff --git a/subiquity/ui/views/filesystem/partition.py b/subiquity/ui/views/filesystem/partition.py index 735f0d63..3f890ee7 100644 --- a/subiquity/ui/views/filesystem/partition.py +++ b/subiquity/ui/views/filesystem/partition.py @@ -163,7 +163,8 @@ class PartitionForm(Form): def select_fstype(self, sender, fstype): if fstype is None: fstype = self.existing_fs_type - self.mount.enabled = self.model.is_mounted_filesystem(fstype) + if getattr(self.device, 'flag', None) != "boot": + self.mount.enabled = self.model.is_mounted_filesystem(fstype) name = LVNameField(_("Name: ")) size = SizeField() @@ -234,8 +235,14 @@ boot_partition_description = _( "Required bootloader partition\n" "\n" 'This is the ESP / "EFI system partition" required by UEFI. Grub will be ' - 'installed onto this partition, which must be formatted as fat32. The ' - 'only aspect of this partition that can be edited is the size.') + 'installed onto this partition, which must be formatted as fat32.') + +boot_partition_description_size = _( + ' The only aspect of this partition that can be edited is the size.') + +boot_partition_description_reformat = _( + ' You can choose whether to use the existing filesystem on this ' + 'partition or reformat it.') prep_partition_description = _( "Required bootloader partition\n" @@ -308,11 +315,32 @@ class PartitionStretchy(Stretchy): if partition is not None: if partition.flag == "boot": - opts = [Option(("fat32", True))] - self.form.fstype.widget.options = opts - self.form.fstype.widget.index = 0 - self.form.mount.enabled = False - self.form.fstype.enabled = False + if partition.original_fs(): + opts = [ + Option(( + _("Use existing fat32 filesystem"), + True, + None + )), + Option(("---", False)), + Option(( + _("Reformat as fresh fat32 filesystem"), + True, + "fat32" + )), + ] + self.form.fstype.widget.options = opts + if partition.fs().preserve: + self.form.fstype.widget.index = 0 + else: + self.form.fstype.widget.index = 2 + self.form.mount.enabled = False + else: + opts = [Option(("fat32", True))] + self.form.fstype.widget.options = opts + self.form.fstype.widget.index = 0 + self.form.mount.enabled = False + self.form.fstype.enabled = False elif partition.flag in ["bios_grub", "prep"]: self.form.mount.enabled = False self.form.fstype.enabled = False @@ -328,8 +356,13 @@ class PartitionStretchy(Stretchy): focus_index = 0 if partition is not None: if self.partition.flag == "boot": + desc = boot_partition_description + if self.partition.preserve: + desc += boot_partition_description_reformat + else: + desc += boot_partition_description_size rows.extend([ - Text(_(boot_partition_description)), + Text(_(desc)), Text(""), ]) elif self.partition.flag == "bios_grub": From c99227a310ab812f1097a028e634f0e0a1320811 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Thu, 30 May 2019 12:15:47 +1200 Subject: [PATCH 13/23] support for reusing an existing swap partition the showing and hiding of fields is fairly horrible, but not *too* horrible. --- subiquity/controllers/filesystem.py | 2 ++ subiquity/models/filesystem.py | 17 ++++++++-- subiquity/ui/views/filesystem/partition.py | 34 +++++++++++++++++-- .../views/filesystem/tests/test_partition.py | 4 +++ 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/subiquity/controllers/filesystem.py b/subiquity/controllers/filesystem.py index 86fcbf5f..ccf85807 100644 --- a/subiquity/controllers/filesystem.py +++ b/subiquity/controllers/filesystem.py @@ -285,6 +285,8 @@ class FilesystemController(BaseController): volume.flag = "" if spec['fstype'] == "swap": self.model.add_mount(fs, "") + if spec['fstype'] is None and spec['use_swap']: + self.model.add_mount(fs, "") self.create_mount(fs, spec) return fs diff --git a/subiquity/models/filesystem.py b/subiquity/models/filesystem.py index d636d7dc..a6871e36 100644 --- a/subiquity/models/filesystem.py +++ b/subiquity/models/filesystem.py @@ -430,8 +430,11 @@ class _Formattable(ABC): r.append(_("mounted at {path}").format(path=m.path)) else: r.append(_("not mounted")) - elif fs.preserve and fs.mount() is not None: - r.append(_("unused")) + elif fs.preserve: + if fs.mount() is None: + r.append(_("unused")) + else: + r.append(_("used")) return r else: return [_("unused")] @@ -1167,7 +1170,15 @@ class FilesystemModel(object): break exclusions = next_exclusions - return [o for o in objs if o not in exclusions] + objs = [o for o in objs if o not in exclusions] + + for o in objs: + if o.type == "partition" and o.flag == "swap" and o._fs is None: + fs = Filesystem(m=self, fstype="swap", volume=o, preserve=True) + o._original_fs = fs + objs.append(fs) + + return objs def _render_actions(self): # The curtin storage config has the constraint that an action must be diff --git a/subiquity/ui/views/filesystem/partition.py b/subiquity/ui/views/filesystem/partition.py index 3f890ee7..f4e948d2 100644 --- a/subiquity/ui/views/filesystem/partition.py +++ b/subiquity/ui/views/filesystem/partition.py @@ -25,6 +25,7 @@ import re from urwid import connect_signal, Text from subiquitycore.ui.form import ( + BooleanField, Form, FormField, simple_field, @@ -158,11 +159,21 @@ class PartitionForm(Form): if max_size is None: self.remove_field('size') connect_signal(self.fstype.widget, 'select', self.select_fstype) + self.form_pile = None self.select_fstype(None, self.fstype.widget.value) def select_fstype(self, sender, fstype): + show_use = False if fstype is None: + if self.existing_fs_type == "swap": + show_use = True fstype = self.existing_fs_type + if self.form_pile is not None: + for i, (w, o) in enumerate(self.form_pile.contents): + if w is self.mount._table and show_use: + self.form_pile.contents[i] = (self.use_swap._table, o) + elif w is self.use_swap._table and not show_use: + self.form_pile.contents[i] = (self.mount._table, o) if getattr(self.device, 'flag', None) != "boot": self.mount.enabled = self.model.is_mounted_filesystem(fstype) @@ -170,6 +181,9 @@ class PartitionForm(Form): size = SizeField() fstype = FSTypeField(_("Format:")) mount = MountField(_("Mount:")) + use_swap = BooleanField( + _("Use as swap"), + help=_("Use this swap partition in the installed system.")) def clean_size(self, val): if not val: @@ -220,6 +234,16 @@ class PartitionForm(Form): return _("{} is already mounted at {}.").format( dev.label.title(), mount) + def as_rows(self): + r = super().as_rows() + if self.existing_fs_type == "swap": + exclude = self.mount._table + else: + exclude = self.use_swap._table + i = r.index(exclude) + del r[i-1:i+1] + return r + bios_grub_partition_description = _( "Required bootloader partition\n" @@ -279,6 +303,8 @@ class PartitionStretchy(Stretchy): if fs is not None: if fs.preserve: initial['fstype'] = None + if fs.fstype == "swap": + initial['use_swap'] = fs.mount() is not None elif partition.flag != "boot": initial['fstype'] = fs.fstype if self.model.is_mounted_filesystem(fs.fstype): @@ -378,8 +404,9 @@ class PartitionStretchy(Stretchy): ]) focus_index = 2 rows.extend(self.form.as_rows()) + self.form.form_pile = Pile(rows) widgets = [ - Pile(rows), + self.form.form_pile, Text(""), self.form.buttons, ] @@ -431,6 +458,8 @@ class FormatEntireStretchy(Stretchy): if fs is not None: if fs.preserve: initial['fstype'] = None + if fs.fstype == "swap": + initial['use_swap'] = fs.mount() is not None else: initial['fstype'] = fs.fstype initial['fstype'] = fs.fstype @@ -455,8 +484,9 @@ class FormatEntireStretchy(Stretchy): Text(""), ] rows.extend(self.form.as_rows()) + self.form.form_pile = Pile(rows) widgets = [ - Pile(rows), + self.form.form_pile, Text(""), self.form.buttons, ] diff --git a/subiquity/ui/views/filesystem/tests/test_partition.py b/subiquity/ui/views/filesystem/tests/test_partition.py index 4ba8247b..3b077600 100644 --- a/subiquity/ui/views/filesystem/tests/test_partition.py +++ b/subiquity/ui/views/filesystem/tests/test_partition.py @@ -50,6 +50,7 @@ class PartitionViewTests(unittest.TestCase): view_helpers.click(stretchy.form.done_btn.base_widget) valid_data['mount'] = '/' valid_data['size'] = dehumanize_size(valid_data['size']) + valid_data['use_swap'] = False view.controller.partition_disk_handler.assert_called_once_with( stretchy.disk, None, valid_data) @@ -69,6 +70,7 @@ class PartitionViewTests(unittest.TestCase): 'size': dehumanize_size(form_data['size']), 'fstype': 'xfs', 'mount': None, + 'use_swap': False, } view.controller.partition_disk_handler.assert_called_once_with( stretchy.disk, stretchy.partition, expected_data) @@ -89,6 +91,7 @@ class PartitionViewTests(unittest.TestCase): expected_data = { 'fstype': 'xfs', 'mount': None, + 'use_swap': False, } view.controller.partition_disk_handler.assert_called_once_with( stretchy.disk, stretchy.partition, expected_data) @@ -108,6 +111,7 @@ class PartitionViewTests(unittest.TestCase): 'size': dehumanize_size(form_data['size']), 'fstype': "fat32", 'mount': '/boot/efi', + 'use_swap': False, } view.controller.partition_disk_handler.assert_called_once_with( stretchy.disk, stretchy.partition, expected_data) From f188a4a4b019a2ad655bfb544f643329bd0823ce Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Thu, 30 May 2019 13:09:27 +1200 Subject: [PATCH 14/23] clear disk.preserve when needed also never set disk.wipe: setting preserve=False/ptable=gpt is equivalent anyay. --- subiquity/controllers/filesystem.py | 7 +++++++ subiquity/models/filesystem.py | 4 +--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/subiquity/controllers/filesystem.py b/subiquity/controllers/filesystem.py index ccf85807..eaf108b9 100644 --- a/subiquity/controllers/filesystem.py +++ b/subiquity/controllers/filesystem.py @@ -397,6 +397,8 @@ class FilesystemController(BaseController): self.delete(subobj) def reformat(self, disk): + if disk.type == "disk": + disk.preserve = False self.clear(disk) for p in list(disk.partitions()): self.delete(p) @@ -414,6 +416,10 @@ class FilesystemController(BaseController): self.create_filesystem(partition, spec) return + if len(disk.partitions()) == 0: + if disk.type == "disk": + disk.preserve = False + needs_boot = self.model.needs_bootloader_partition() log.debug('model needs a bootloader partition? {}'.format(needs_boot)) can_be_boot = DeviceAction.MAKE_BOOT in disk.supported_actions @@ -534,4 +540,5 @@ class FilesystemController(BaseController): part.wipe = 'zero' self.model.grub_install_device = part else: + new_boot_disk.preserve = False self._create_boot_partition(new_boot_disk) diff --git a/subiquity/models/filesystem.py b/subiquity/models/filesystem.py index a6871e36..f5b3b84f 100644 --- a/subiquity/models/filesystem.py +++ b/subiquity/models/filesystem.py @@ -588,7 +588,7 @@ class Disk(_Device): serial = attr.ib(default=None) path = attr.ib(default=None) model = attr.ib(default=None) - wipe = attr.ib(default='superblock') + wipe = attr.ib(default=None) preserve = attr.ib(default=False) name = attr.ib(default="") grub_device = attr.ib(default=False) @@ -1192,8 +1192,6 @@ class FilesystemModel(object): emitted_ids = set() def emit(obj): - if obj.type == 'disk' and not obj.used: - return r.append(asdict(obj)) emitted_ids.add(obj.id) From 0c55149c31bc2efee288fd2dc5947e3b2a6dfaf2 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Thu, 30 May 2019 13:11:36 +1200 Subject: [PATCH 15/23] run integration tests with simple sample data --- examples/answers-raid-lvm.yaml | 2 +- scripts/runtests.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/answers-raid-lvm.yaml b/examples/answers-raid-lvm.yaml index cdf7af08..49be08f3 100644 --- a/examples/answers-raid-lvm.yaml +++ b/examples/answers-raid-lvm.yaml @@ -18,7 +18,7 @@ Filesystem: obj: [disk index 0] action: PARTITION data: - size: 1G + size: 0.5G fstype: null - *newpart - *newpart diff --git a/scripts/runtests.sh b/scripts/runtests.sh index bb1453f4..601d30ef 100755 --- a/scripts/runtests.sh +++ b/scripts/runtests.sh @@ -7,7 +7,7 @@ for answers in examples/answers*.yaml; do rm -f .subiquity/subiquity-debug.log rm -f .subiquity/run/subiquity/updating # The --foreground is important to avoid subiquity getting SIGTTOU-ed. - timeout --foreground 60 sh -c "LANG=C.UTF-8 python3 -m subiquity.cmd.tui --answers $answers --dry-run --snaps-from-examples --machine-config examples/mwhudson.json" + timeout --foreground 60 sh -c "LANG=C.UTF-8 python3 -m subiquity.cmd.tui --answers $answers --dry-run --snaps-from-examples --machine-config examples/simple.json" python3 scripts/validate-yaml.py .subiquity/subiquity-curtin-install.conf if grep passw0rd .subiquity/subiquity-debug.log | grep -v "Loaded answers" | grep -v "answers_action"; then echo "password leaked into log file" From 8c7dbb21f4ae09f78c8fd4ef3393e4b82ebcea08 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Thu, 30 May 2019 13:43:05 +1200 Subject: [PATCH 16/23] log block discovery stuff in separate directory so we can tell people to send us /var/log/installer/block when odd things happen. --- subiquity/cmd/tui.py | 14 +++++++++++++- subiquity/controllers/filesystem.py | 21 +++++++++++++++++---- subiquity/core.py | 3 ++- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/subiquity/cmd/tui.py b/subiquity/cmd/tui.py index dc3060d2..3a1a1390 100755 --- a/subiquity/cmd/tui.py +++ b/subiquity/cmd/tui.py @@ -110,10 +110,22 @@ def main(): if opts.snaps_from_examples is None: opts.snaps_from_examples = True LOGFILE = setup_logger(dir=LOGDIR) + logger = logging.getLogger('subiquity') logger.info("Starting SUbiquity v{}".format(VERSION)) logger.info("Arguments passed: {}".format(sys.argv)) + block_log_dir = os.path.join(LOGDIR, "block") + os.makedirs(block_log_dir, exist_ok=True) + handler = logging.FileHandler(os.path.join(block_log_dir, 'discover.log')) + handler.setLevel('DEBUG') + handler.setFormatter( + logging.Formatter("%(asctime)s %(name)s:%(lineno)d %(message)s")) + logging.getLogger('probert').addHandler(handler) + handler.addFilter(lambda rec: rec.name != 'probert.network') + logging.getLogger('curtin').addHandler(handler) + logging.getLogger('block-discover').addHandler(handler) + signal.signal(signal.SIGINT, signal.SIG_IGN) signal.signal(signal.SIGQUIT, signal.SIG_IGN) @@ -140,7 +152,7 @@ def main(): ui = SubiquityUI() try: - subiquity_interface = Subiquity(ui, opts) + subiquity_interface = Subiquity(ui, opts, block_log_dir) except ApplicationError as e: logger.exception('Failed to load Subiquity interface') print(e) diff --git a/subiquity/controllers/filesystem.py b/subiquity/controllers/filesystem.py index eaf108b9..e09ac0e4 100644 --- a/subiquity/controllers/filesystem.py +++ b/subiquity/controllers/filesystem.py @@ -14,7 +14,9 @@ # along with this program. If not, see . import enum +import json import logging +import os from subiquitycore.controller import BaseController @@ -37,6 +39,7 @@ from subiquity.ui.views.filesystem.probing import ( log = logging.getLogger("subiquitycore.controller.filesystem") +block_discover_log = logging.getLogger('block-discover') BIOS_GRUB_SIZE_BYTES = 1 * 1024 * 1024 # 1MiB PREP_GRUB_SIZE_BYTES = 8 * 1024 * 1024 # 8MiB @@ -55,6 +58,7 @@ class FilesystemController(BaseController): def __init__(self, common): super().__init__(common) + self.block_log_dir = common.get('block_log_dir') self.model = self.base_model.filesystem if self.opts.dry_run and self.opts.bootloader: name = self.opts.bootloader.upper() @@ -67,6 +71,7 @@ class FilesystemController(BaseController): self._probe_state = ProbeState.NOT_STARTED def start(self): + block_discover_log.info("starting probe") self._probe_state = ProbeState.PROBING self.run_in_bg(self._bg_probe, self._probed) self.loop.set_alarm_in( @@ -77,14 +82,23 @@ class FilesystemController(BaseController): def _probed(self, fut, restricted=False): if not restricted and self._probe_state != ProbeState.PROBING: - log.debug("ignoring result %s for timed out probe", fut) + block_discover_log.debug( + "ignoring result %s for timed out probe", fut) return try: storage = fut.result() + if restricted: + fname = 'probe-data-restricted.json' + else: + fname = 'probe-data.json' + with open(os.path.join(self.block_log_dir, fname), 'w') as fp: + json.dump(storage, fp) + self.model.load_probe_data(storage) except Exception: - log.exception("probing failed restricted=%s", restricted) + block_discover_log.exception( + "probing failed restricted=%s", restricted) if not restricted: - log.info("reprobing for blockdev only") + block_discover_log.info("reprobing for blockdev only") # Should make a crash file for apport, arrange for it to be # copied onto the installed system and tell user all this # happened! @@ -94,7 +108,6 @@ class FilesystemController(BaseController): if self.showing: self.default() else: - self.model.load_probe_data(storage) self._probe_state = ProbeState.DONE # Should do something here if probing found no devices. if self.showing: diff --git a/subiquity/core.py b/subiquity/core.py index 36af4039..e1c35602 100644 --- a/subiquity/core.py +++ b/subiquity/core.py @@ -57,9 +57,10 @@ class Subiquity(Application): "InstallProgress", ] - def __init__(self, ui, opts): + def __init__(self, ui, opts, block_log_dir): super().__init__(ui, opts) self.common['ui'].progress_completion += 1 + self.common['block_log_dir'] = block_log_dir if opts.snaps_from_examples: connection = FakeSnapdConnection( os.path.join( From 118a11cfa68a629a2cc0630e8fb39cca79b6656a Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Thu, 30 May 2019 13:46:39 +1200 Subject: [PATCH 17/23] remove old sample machine data --- README.md | 2 +- examples/mwhudson.json | 1656 ---------------------------------------- 2 files changed, 1 insertion(+), 1657 deletions(-) delete mode 100644 examples/mwhudson.json diff --git a/README.md b/README.md index 6bfce43a..58641913 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ installer without having access to the machine. A few sample machine profiles are available in the repository at ./examples/ and can be loaded via the MACHINE make variable: -`make dryrun MACHINE=examples/mwhudson.json` +`make dryrun MACHINE=examples/simple.json` # Generating machine profiles Machine profiles are generated from the probert tool. To collect a machine profile: diff --git a/examples/mwhudson.json b/examples/mwhudson.json deleted file mode 100644 index 4d0c9712..00000000 --- a/examples/mwhudson.json +++ /dev/null @@ -1,1656 +0,0 @@ -{ - "storage": { - "blockdev": { - "/dev/sdh1": { - "ID_ATA_WRITE_CACHE_ENABLED": "1", - "ID_SERIAL_SHORT": "S1KHNYAG105196", - "DEVPATH": "/devices/pci0000:00/0000:00:1f.2/ata4/host3/target3:0:0/3:0:0:0/block/sdh/sdh1", - "UDISKS_IGNORE": "1", - "ID_ATA_SATA_SIGNAL_RATE_GEN1": "1", - "ID_SERIAL": "SAMSUNG_MZNTE256HMHP-000L7_S1KHNYAG105196", - "ID_ATA_WRITE_CACHE": "1", - "ID_ATA_FEATURE_SET_PM_ENABLED": "1", - "ID_ATA_FEATURE_SET_SECURITY_FROZEN": "1", - "ID_ATA_FEATURE_SET_SMART_ENABLED": "1", - "ID_PART_ENTRY_SIZE": "1048576", - "ID_ATA_FEATURE_SET_SECURITY_ENABLED": "0", - "ID_ATA_FEATURE_SET_SMART": "1", - "ID_ATA_FEATURE_SET_HPA": "1", - "DEVLINKS": "/dev/disk/by-partlabel/EFI\\x20System\\x20Partition /dev/disk/by-id/wwn-0x5002538844584d30-part1 /dev/disk/by-uuid/ADF1-28D1 /dev/disk/by-path/pci-0000:00:1f.2-ata-4-part1 /dev/disk/by-partuuid/6eb13469-d6db-4d29-b41a-a7f358b5a04c /dev/disk/by-id/ata-SAMSUNG_MZNTE256HMHP-000L7_S1KHNYAG105196-part1", - "ID_BUS": "ata", - "ID_MODEL_ENC": "SAMSUNG\\x20MZNTE256HMHP-000L7\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20", - "ID_MODEL": "SAMSUNG_MZNTE256HMHP-000L7", - "ID_PART_TABLE_UUID": "22d008b2-df49-4ebc-9bc3-2d52631a77b0", - "ID_ATA": "1", - "ID_FS_UUID_ENC": "ADF1-28D1", - "ID_WWN": "0x5002538844584d30", - "ID_FS_TYPE": "vfat", - "ID_PART_ENTRY_TYPE": "c12a7328-f81f-11d2-ba4b-00a0c93ec93b", - "attrs": { - "stat": " 539 791 17511 376 3 0 10 0 0 272 376", - "uevent": "MAJOR=8\nMINOR=1\nDEVNAME=sdh1\nDEVTYPE=partition", - "dev": "8:1", - "size": "536870912", - "start": "2048", - "partition": "1", - "discard_alignment": "0", - "subsystem": "block", - "inflight": " 0 0", - "ro": "0", - "alignment_offset": "0" - }, - "ID_PART_ENTRY_DISK": "8:0", - "ID_FS_UUID": "ADF1-28D1", - "ID_PART_ENTRY_OFFSET": "2048", - "ID_PATH_TAG": "pci-0000_00_1f_2-ata-4", - "ID_PART_TABLE_TYPE": "gpt", - "ID_ATA_SATA": "1", - "ID_REVISION": "EXT28L6Q", - "ID_WWN_WITH_EXTENSION": "0x5002538844584d30", - "SUBSYSTEM": "block", - "ID_ATA_FEATURE_SET_PM": "1", - "TAGS": ":systemd:", - "ID_ATA_FEATURE_SET_SECURITY": "1", - "ID_ATA_ROTATION_RATE_RPM": "0", - "MINOR": "1", - "ID_ATA_FEATURE_SET_SECURITY_ENHANCED_ERASE_UNIT_MIN": "8", - "ID_FS_VERSION": "FAT32", - "ID_PART_ENTRY_NUMBER": "1", - "ID_PART_ENTRY_UUID": "6eb13469-d6db-4d29-b41a-a7f358b5a04c", - "ID_PART_ENTRY_SCHEME": "gpt", - "DEVTYPE": "partition", - "ID_PART_ENTRY_NAME": "EFI\\x20System\\x20Partition", - "DEVNAME": "/dev/sdh1", - "ID_ATA_FEATURE_SET_SECURITY_ERASE_UNIT_MIN": "2", - "ID_TYPE": "disk", - "ID_PATH": "pci-0000:00:1f.2-ata-4", - "ID_ATA_FEATURE_SET_HPA_ENABLED": "1", - "USEC_INITIALIZED": "1448235", - "MAJOR": "8", - "ID_ATA_SATA_SIGNAL_RATE_GEN2": "1", - "ID_ATA_DOWNLOAD_MICROCODE": "1", - "ID_FS_USAGE": "filesystem" - }, - "/dev/dm-0": { - "DM_NAME": "sdh3_crypt", - "DEVPATH": "/devices/virtual/block/dm-0", - "SUBSYSTEM": "block", - "DM_UUID": "CRYPT-LUKS1-16f614f4ce404f4f8479ecd8c6eeb65a-sdh3_crypt", - "USEC_INITIALIZED": "11269171", - "MINOR": "0", - "TAGS": ":systemd:", - "DM_UDEV_PRIMARY_SOURCE_FLAG": "1", - "DEVLINKS": "/dev/disk/by-id/dm-uuid-CRYPT-LUKS1-16f614f4ce404f4f8479ecd8c6eeb65a-sdh3_crypt /dev/disk/by-id/lvm-pv-uuid-zYd1a2-VhHn-95vf-B2GD-12ON-h9vn-De6l0g /dev/mapper/sdh3_crypt /dev/disk/by-id/dm-name-sdh3_crypt", - "ID_FS_TYPE": "LVM2_member", - "ID_FS_UUID_ENC": "zYd1a2-VhHn-95vf-B2GD-12ON-h9vn-De6l0g", - "SYSTEMD_READY": "1", - "DEVNAME": "/dev/dm-0", - "DEVTYPE": "disk", - "ID_FS_VERSION": "LVM2 001", - "DM_STATE": "ACTIVE", - "DM_TABLE_STATE": "LIVE", - "DM_UDEV_RULES": "1", - "DM_SUSPENDED": "0", - "DM_ACTIVATION": "1", - "attrs": { - "stat": " 6448590 0 116244122 14424164 7478652 0 120095992 2039869820 0 1844212 2077291472", - "removable": "0", - "capability": "10", - "subsystem": "block", - "ext_range": "1", - "inflight": " 0 0", - "ro": "0", - "bdi": null, - "uevent": "MAJOR=252\nMINOR=0\nDEVNAME=dm-0\nDEVTYPE=disk", - "dev": "252:0", - "size": "255008440320", - "range": "1", - "discard_alignment": "0", - "alignment_offset": "0" - }, - "DM_TYPE": "raid", - "MAJOR": "252", - "ID_FS_UUID": "zYd1a2-VhHn-95vf-B2GD-12ON-h9vn-De6l0g", - "LVM_SCANNED": "1", - "ID_FS_USAGE": "raid" - }, - "/dev/dm-2": { - "DM_NAME": "ubuntu--vg-swap_1", - "DEVPATH": "/devices/virtual/block/dm-2", - "MINOR": "2", - "attrs": { - "stat": " 4060007 0 32490616 4764196 6016088 0 48128704 1977997412 0 1070252 2003886640", - "removable": "0", - "capability": "10", - "subsystem": "block", - "ext_range": "1", - "inflight": " 0 0", - "ro": "0", - "bdi": null, - "uevent": "MAJOR=252\nMINOR=2\nDEVNAME=dm-2\nDEVTYPE=disk", - "dev": "252:2", - "size": "8459911168", - "range": "1", - "discard_alignment": "0", - "alignment_offset": "0" - }, - "SUBSYSTEM": "block", - "DM_UUID": "LVM-o1HQ3NO1UJykD3nwyjNBwFB7Sr1Fxva5QkLSXkM6RRTOr1xxA4DtVKkrCIfL4OOd", - "USEC_INITIALIZED": "11617382", - "ID_FS_TYPE": "swap", - "TAGS": ":systemd:", - "DEVLINKS": "/dev/disk/by-uuid/69eae475-b6a4-4528-b908-e1374b39416c /dev/ubuntu-vg/swap_1 /dev/mapper/ubuntu--vg-swap_1 /dev/disk/by-id/dm-name-ubuntu--vg-swap_1 /dev/disk/by-id/dm-uuid-LVM-o1HQ3NO1UJykD3nwyjNBwFB7Sr1Fxva5QkLSXkM6RRTOr1xxA4DtVKkrCIfL4OOd", - "DM_UDEV_PRIMARY_SOURCE_FLAG": "1", - "ID_FS_UUID_ENC": "69eae475-b6a4-4528-b908-e1374b39416c", - "DEVNAME": "/dev/dm-2", - "DEVTYPE": "disk", - "DM_VG_NAME": "ubuntu-vg", - "ID_FS_VERSION": "1", - "DM_STATE": "ACTIVE", - "DM_TABLE_STATE": "LIVE", - "DM_UDEV_RULES": "1", - "DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG": "1", - "DM_SUSPENDED": "0", - "DM_ACTIVATION": "1", - "DM_LV_NAME": "swap_1", - "DM_TYPE": "raid", - "MAJOR": "252", - "ID_FS_UUID": "69eae475-b6a4-4528-b908-e1374b39416c", - "ID_FS_USAGE": "other" - }, - "/dev/sdh3": { - "ID_ATA_WRITE_CACHE_ENABLED": "1", - "ID_SERIAL_SHORT": "S1KHNYAG105196", - "DEVPATH": "/devices/pci0000:00/0000:00:1f.2/ata4/host3/target3:0:0/3:0:0:0/block/sdh/sdh3", - "ID_ATA_SATA_SIGNAL_RATE_GEN1": "1", - "ID_SERIAL": "SAMSUNG_MZNTE256HMHP-000L7_S1KHNYAG105196", - "ID_ATA_WRITE_CACHE": "1", - "ID_ATA_FEATURE_SET_PM_ENABLED": "1", - "ID_ATA_FEATURE_SET_SECURITY_FROZEN": "1", - "ID_ATA_FEATURE_SET_SMART_ENABLED": "1", - "ID_PART_ENTRY_SIZE": "498067456", - "ID_ATA_FEATURE_SET_SECURITY_ENABLED": "0", - "ID_ATA_FEATURE_SET_SMART": "1", - "ID_ATA_FEATURE_SET_HPA": "1", - "DEVLINKS": "/dev/disk/by-id/wwn-0x5002538844584d30-part3 /dev/disk/by-partuuid/506c05eb-a5bb-4772-add7-4d660871c290 /dev/disk/by-uuid/16f614f4-ce40-4f4f-8479-ecd8c6eeb65a /dev/disk/by-id/ata-SAMSUNG_MZNTE256HMHP-000L7_S1KHNYAG105196-part3 /dev/disk/by-path/pci-0000:00:1f.2-ata-4-part3", - "ID_BUS": "ata", - "ID_MODEL_ENC": "SAMSUNG\\x20MZNTE256HMHP-000L7\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20", - "ID_MODEL": "SAMSUNG_MZNTE256HMHP-000L7", - "ID_PART_TABLE_UUID": "22d008b2-df49-4ebc-9bc3-2d52631a77b0", - "ID_ATA": "1", - "ID_FS_UUID_ENC": "16f614f4-ce40-4f4f-8479-ecd8c6eeb65a", - "ID_WWN": "0x5002538844584d30", - "ID_FS_TYPE": "crypto_LUKS", - "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4", - "attrs": { - "stat": " 4698510 1746892 116246554 7218664 1690971 5716300 120095992 65191132 0 1582520 72443728", - "uevent": "MAJOR=8\nMINOR=3\nDEVNAME=sdh3\nDEVTYPE=partition", - "dev": "8:3", - "size": "255010537472", - "start": "2050048", - "partition": "3", - "discard_alignment": "0", - "subsystem": "block", - "inflight": " 0 0", - "ro": "0", - "alignment_offset": "0" - }, - "ID_PART_ENTRY_DISK": "8:0", - "ID_FS_UUID": "16f614f4-ce40-4f4f-8479-ecd8c6eeb65a", - "ID_PART_ENTRY_OFFSET": "2050048", - "ID_PATH_TAG": "pci-0000_00_1f_2-ata-4", - "ID_PART_TABLE_TYPE": "gpt", - "ID_ATA_SATA": "1", - "ID_WWN_WITH_EXTENSION": "0x5002538844584d30", - "SUBSYSTEM": "block", - "ID_ATA_FEATURE_SET_PM": "1", - "TAGS": ":systemd:", - "ID_ATA_FEATURE_SET_SECURITY": "1", - "ID_ATA_ROTATION_RATE_RPM": "0", - "ID_PART_ENTRY_UUID": "506c05eb-a5bb-4772-add7-4d660871c290", - "ID_ATA_FEATURE_SET_SECURITY_ENHANCED_ERASE_UNIT_MIN": "8", - "ID_FS_VERSION": "1", - "ID_PART_ENTRY_NUMBER": "3", - "ID_REVISION": "EXT28L6Q", - "ID_PART_ENTRY_SCHEME": "gpt", - "DEVTYPE": "partition", - "DEVNAME": "/dev/sdh3", - "ID_ATA_FEATURE_SET_SECURITY_ERASE_UNIT_MIN": "2", - "ID_TYPE": "disk", - "ID_PATH": "pci-0000:00:1f.2-ata-4", - "ID_ATA_FEATURE_SET_HPA_ENABLED": "1", - "USEC_INITIALIZED": "1385677", - "MAJOR": "8", - "MINOR": "3", - "ID_ATA_SATA_SIGNAL_RATE_GEN2": "1", - "ID_ATA_DOWNLOAD_MICROCODE": "1", - "ID_FS_USAGE": "crypto" - }, - "/dev/sdh2": { - "ID_ATA_WRITE_CACHE_ENABLED": "1", - "ID_SERIAL_SHORT": "S1KHNYAG105196", - "DEVPATH": "/devices/pci0000:00/0000:00:1f.2/ata4/host3/target3:0:0/3:0:0:0/block/sdh/sdh2", - "ID_ATA_SATA_SIGNAL_RATE_GEN1": "1", - "ID_SERIAL": "SAMSUNG_MZNTE256HMHP-000L7_S1KHNYAG105196", - "ID_ATA_WRITE_CACHE": "1", - "ID_ATA_FEATURE_SET_PM_ENABLED": "1", - "ID_ATA_FEATURE_SET_SECURITY_FROZEN": "1", - "ID_ATA_FEATURE_SET_SMART_ENABLED": "1", - "ID_PART_ENTRY_SIZE": "999424", - "ID_ATA_FEATURE_SET_SECURITY_ENABLED": "0", - "ID_ATA_FEATURE_SET_SMART": "1", - "ID_ATA_FEATURE_SET_HPA": "1", - "DEVLINKS": "/dev/disk/by-partuuid/fed48b2c-e7c0-4024-bfcc-b79aabb7ab0e /dev/disk/by-id/ata-SAMSUNG_MZNTE256HMHP-000L7_S1KHNYAG105196-part2 /dev/disk/by-uuid/4256e0f5-746e-4e64-949c-67b38a6fa4de /dev/disk/by-path/pci-0000:00:1f.2-ata-4-part2 /dev/disk/by-id/wwn-0x5002538844584d30-part2", - "ID_BUS": "ata", - "ID_MODEL_ENC": "SAMSUNG\\x20MZNTE256HMHP-000L7\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20", - "ID_MODEL": "SAMSUNG_MZNTE256HMHP-000L7", - "ID_PART_TABLE_UUID": "22d008b2-df49-4ebc-9bc3-2d52631a77b0", - "ID_ATA": "1", - "ID_FS_UUID_ENC": "4256e0f5-746e-4e64-949c-67b38a6fa4de", - "ID_WWN": "0x5002538844584d30", - "ID_FS_TYPE": "ext2", - "ID_PART_ENTRY_TYPE": "0fc63daf-8483-4772-8e79-3d69d8477de4", - "attrs": { - "stat": " 1636 1 157056 940 651 418 784962 199124 0 10084 200060", - "uevent": "MAJOR=8\nMINOR=2\nDEVNAME=sdh2\nDEVTYPE=partition", - "dev": "8:2", - "size": "511705088", - "start": "1050624", - "partition": "2", - "discard_alignment": "0", - "subsystem": "block", - "inflight": " 0 0", - "ro": "0", - "alignment_offset": "0" - }, - "ID_PART_ENTRY_DISK": "8:0", - "ID_FS_UUID": "4256e0f5-746e-4e64-949c-67b38a6fa4de", - "ID_PART_ENTRY_OFFSET": "1050624", - "ID_PATH_TAG": "pci-0000_00_1f_2-ata-4", - "ID_PART_TABLE_TYPE": "gpt", - "ID_ATA_SATA": "1", - "ID_WWN_WITH_EXTENSION": "0x5002538844584d30", - "SUBSYSTEM": "block", - "ID_ATA_FEATURE_SET_PM": "1", - "TAGS": ":systemd:", - "ID_ATA_FEATURE_SET_SECURITY": "1", - "ID_ATA_ROTATION_RATE_RPM": "0", - "ID_PART_ENTRY_UUID": "fed48b2c-e7c0-4024-bfcc-b79aabb7ab0e", - "ID_ATA_FEATURE_SET_SECURITY_ENHANCED_ERASE_UNIT_MIN": "8", - "ID_FS_VERSION": "1.0", - "ID_PART_ENTRY_NUMBER": "2", - "ID_REVISION": "EXT28L6Q", - "ID_PART_ENTRY_SCHEME": "gpt", - "DEVTYPE": "partition", - "DEVNAME": "/dev/sdh2", - "ID_ATA_FEATURE_SET_SECURITY_ERASE_UNIT_MIN": "2", - "ID_TYPE": "disk", - "ID_PATH": "pci-0000:00:1f.2-ata-4", - "ID_ATA_FEATURE_SET_HPA_ENABLED": "1", - "USEC_INITIALIZED": "1435135", - "MAJOR": "8", - "MINOR": "2", - "ID_ATA_SATA_SIGNAL_RATE_GEN2": "1", - "ID_ATA_DOWNLOAD_MICROCODE": "1", - "ID_FS_USAGE": "filesystem" - }, - "/dev/sdi": { - "ID_ATA_WRITE_CACHE_ENABLED": "1", - "ID_SERIAL_SHORT": "14250C57FECE", - "DEVPATH": "/devices/pci0000:00/0000:00:14.0/usb3/3-3/3-3.1/3-3.1.1/3-3.1.1:1.0/host5/target5:0:0/5:0:0:0/block/sdi", - "ID_ATA_SATA_SIGNAL_RATE_GEN1": "1", - "ID_SERIAL": "Crucial_CT512MX100SSD1_14250C57FECE", - "ID_ATA_WRITE_CACHE": "1", - "ID_ATA_FEATURE_SET_PM_ENABLED": "1", - "ID_ATA_FEATURE_SET_SMART_ENABLED": "1", - "ID_ATA_FEATURE_SET_SECURITY_ENABLED": "0", - "TAGS": ":systemd:", - "ID_ATA_FEATURE_SET_HPA": "1", - "DEVLINKS": "/dev/disk/by-path/pci-0000:00:14.0-usb-0:3.1.1:1.0-scsi-0:0:0:0 /dev/disk/by-id/wwn-0x500a07510c57fece /dev/disk/by-id/ata-Crucial_CT512MX100SSD1_14250C57FECE", - "ID_BUS": "ata", - "ID_MODEL_ENC": "Crucial_CT512MX100SSD1\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20", - "ID_MODEL": "Crucial_CT512MX100SSD1", - "ID_PART_TABLE_UUID": "20b39872", - "ID_ATA_FEATURE_SET_APM_CURRENT_VALUE": "254", - "ID_ATA": "1", - "ID_WWN": "0x500a07510c57fece", - "attrs": { - "stat": " 219186 109 40219906 336384 317889 1111262 46830968 17779764 104 2029864 18167964", - "device": null, - "removable": "0", - "capability": "50", - "subsystem": "block", - "ext_range": "256", - "inflight": " 0 104", - "events": "", - "bdi": null, - "ro": "0", - "events_async": "", - "dev": "8:16", - "size": "512110190592", - "uevent": "MAJOR=8\nMINOR=16\nDEVNAME=sdi\nDEVTYPE=disk", - "range": "16", - "events_poll_msecs": "-1", - "discard_alignment": "0", - "alignment_offset": "0" - }, - "ID_PATH_TAG": "pci-0000_00_14_0-usb-0_3_1_1_1_0-scsi-0_0_0_0", - "ID_ATA_FEATURE_SET_APM": "1", - "ID_PART_TABLE_TYPE": "dos", - "ID_ATA_SATA": "1", - "ID_WWN_WITH_EXTENSION": "0x500a07510c57fece", - "SUBSYSTEM": "block", - "ID_ATA_FEATURE_SET_PM": "1", - "ID_ATA_FEATURE_SET_SECURITY": "1", - "ID_ATA_ROTATION_RATE_RPM": "0", - "MINOR": "16", - "ID_ATA_FEATURE_SET_SECURITY_ENHANCED_ERASE_UNIT_MIN": "2", - "ID_REVISION": "MU01", - "DEVNAME": "/dev/sdi", - "DEVTYPE": "disk", - "ID_ATA_FEATURE_SET_SECURITY_ERASE_UNIT_MIN": "2", - "ID_TYPE": "disk", - "ID_PATH": "pci-0000:00:14.0-usb-0:3.1.1:1.0-scsi-0:0:0:0", - "ID_ATA_FEATURE_SET_APM_ENABLED": "1", - "ID_ATA_FEATURE_SET_HPA_ENABLED": "1", - "USEC_INITIALIZED": "34247695229", - "MAJOR": "8", - "ID_ATA_SATA_SIGNAL_RATE_GEN2": "1", - "ID_ATA_DOWNLOAD_MICROCODE": "1", - "ID_ATA_FEATURE_SET_SMART": "1" - }, - "/dev/sdi1": { - "ID_ATA_WRITE_CACHE_ENABLED": "1", - "ID_SERIAL_SHORT": "14250C57FECE", - "DEVPATH": "/devices/pci0000:00/0000:00:14.0/usb3/3-3/3-3.1/3-3.1.1/3-3.1.1:1.0/host5/target5:0:0/5:0:0:0/block/sdi/sdi1", - "ID_ATA_SATA_SIGNAL_RATE_GEN1": "1", - "ID_SERIAL": "Crucial_CT512MX100SSD1_14250C57FECE", - "ID_ATA_WRITE_CACHE": "1", - "ID_ATA_FEATURE_SET_PM_ENABLED": "1", - "ID_MODEL": "Crucial_CT512MX100SSD1", - "ID_PART_ENTRY_TYPE": "0x83", - "ID_ATA_FEATURE_SET_SMART_ENABLED": "1", - "ID_PART_ENTRY_SIZE": "1000213168", - "ID_ATA_FEATURE_SET_SECURITY_ENABLED": "0", - "ID_ATA_FEATURE_SET_SMART": "1", - "ID_ATA_FEATURE_SET_HPA": "1", - "DEVLINKS": "/dev/disk/by-label/backup_ssd /dev/disk/by-uuid/4442a585-3ab3-4dad-b690-d85e3a4a0993 /dev/disk/by-id/wwn-0x500a07510c57fece-part1 /dev/disk/by-id/ata-Crucial_CT512MX100SSD1_14250C57FECE-part1 /dev/disk/by-path/pci-0000:00:14.0-usb-0:3.1.1:1.0-scsi-0:0:0:0-part1", - "ID_BUS": "ata", - "ID_MODEL_ENC": "Crucial_CT512MX100SSD1\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20", - "ID_FS_LABEL_ENC": "backup_ssd", - "ID_PART_TABLE_UUID": "20b39872", - "ID_ATA_FEATURE_SET_APM_CURRENT_VALUE": "254", - "ID_ATA": "1", - "ID_FS_UUID_ENC": "4442a585-3ab3-4dad-b690-d85e3a4a0993", - "ID_WWN": "0x500a07510c57fece", - "ID_FS_TYPE": "ext4", - "attrs": { - "stat": " 219172 109 40218866 336380 317030 1111262 46830968 17775568 104 2025908 18163748", - "uevent": "MAJOR=8\nMINOR=17\nDEVNAME=sdi1\nDEVTYPE=partition", - "dev": "8:17", - "size": "512109142016", - "start": "2048", - "partition": "1", - "discard_alignment": "0", - "subsystem": "block", - "inflight": " 0 104", - "ro": "0", - "alignment_offset": "0" - }, - "ID_PART_ENTRY_DISK": "8:16", - "ID_FS_UUID": "4442a585-3ab3-4dad-b690-d85e3a4a0993", - "ID_PART_ENTRY_OFFSET": "2048", - "ID_PATH_TAG": "pci-0000_00_14_0-usb-0_3_1_1_1_0-scsi-0_0_0_0", - "ID_FS_LABEL": "backup_ssd", - "ID_ATA_FEATURE_SET_APM": "1", - "ID_PART_TABLE_TYPE": "dos", - "ID_ATA_SATA": "1", - "ID_REVISION": "MU01", - "ID_WWN_WITH_EXTENSION": "0x500a07510c57fece", - "SUBSYSTEM": "block", - "ID_ATA_FEATURE_SET_PM": "1", - "TAGS": ":systemd:", - "ID_ATA_FEATURE_SET_SECURITY": "1", - "ID_ATA_ROTATION_RATE_RPM": "0", - "MINOR": "17", - "ID_ATA_FEATURE_SET_SECURITY_ENHANCED_ERASE_UNIT_MIN": "2", - "ID_FS_VERSION": "1.0", - "ID_PART_ENTRY_NUMBER": "1", - "ID_PART_ENTRY_UUID": "20b39872-01", - "ID_PART_ENTRY_SCHEME": "dos", - "DEVTYPE": "partition", - "DEVNAME": "/dev/sdi1", - "ID_ATA_FEATURE_SET_SECURITY_ERASE_UNIT_MIN": "2", - "ID_TYPE": "disk", - "ID_PATH": "pci-0000:00:14.0-usb-0:3.1.1:1.0-scsi-0:0:0:0", - "ID_ATA_FEATURE_SET_APM_ENABLED": "1", - "ID_ATA_FEATURE_SET_HPA_ENABLED": "1", - "USEC_INITIALIZED": "34248429328", - "MAJOR": "8", - "ID_ATA_SATA_SIGNAL_RATE_GEN2": "1", - "ID_ATA_DOWNLOAD_MICROCODE": "1", - "ID_FS_USAGE": "filesystem" - }, - "/dev/sdh": { - "ID_ATA_WRITE_CACHE_ENABLED": "1", - "ID_MODEL": "SAMSUNG_MZNTE256HMHP-000L7", - "DEVPATH": "/devices/pci0000:00/0000:00:1f.2/ata4/host3/target3:0:0/3:0:0:0/block/sdh", - "ID_ATA_SATA_SIGNAL_RATE_GEN1": "1", - "attrs": { - "stat": " 4701243 1747687 116448223 7221724 1754696 5716718 120880964 65641044 0 1767420 72897104", - "device": null, - "removable": "0", - "capability": "50", - "subsystem": "block", - "ext_range": "256", - "inflight": " 0 0", - "events": "", - "bdi": null, - "ro": "0", - "events_async": "", - "dev": "8:0", - "size": "256060514304", - "uevent": "MAJOR=8\nMINOR=0\nDEVNAME=sdh\nDEVTYPE=disk", - "range": "16", - "events_poll_msecs": "-1", - "discard_alignment": "0", - "alignment_offset": "0" - }, - "ID_SERIAL": "SAMSUNG_MZNTE256HMHP-000L7_S1KHNYAG105196", - "ID_WWN_WITH_EXTENSION": "0x5002538844584d30", - "ID_ATA_WRITE_CACHE": "1", - "ID_ATA_FEATURE_SET_PM_ENABLED": "1", - "ID_ATA_FEATURE_SET_HPA": "1", - "TAGS": ":systemd:", - "ID_ATA_FEATURE_SET_SECURITY_FROZEN": "1", - "ID_ATA_FEATURE_SET_SECURITY": "1", - "ID_ATA_ROTATION_RATE_RPM": "0", - "DEVLINKS": "/dev/disk/by-path/pci-0000:00:1f.2-ata-4 /dev/disk/by-id/wwn-0x5002538844584d30 /dev/disk/by-id/ata-SAMSUNG_MZNTE256HMHP-000L7_S1KHNYAG105196", - "ID_ATA_FEATURE_SET_SECURITY_ENABLED": "0", - "ID_ATA_FEATURE_SET_SMART": "1", - "ID_ATA_FEATURE_SET_HPA_ENABLED": "1", - "ID_ATA_FEATURE_SET_SMART_ENABLED": "1", - "ID_ATA_FEATURE_SET_SECURITY_ENHANCED_ERASE_UNIT_MIN": "8", - "ID_BUS": "ata", - "ID_MODEL_ENC": "SAMSUNG\\x20MZNTE256HMHP-000L7\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20", - "ID_ATA_SATA": "1", - "ID_REVISION": "EXT28L6Q", - "ID_PART_TABLE_UUID": "22d008b2-df49-4ebc-9bc3-2d52631a77b0", - "DEVNAME": "/dev/sdh", - "ID_ATA": "1", - "ID_PATH_TAG": "pci-0000_00_1f_2-ata-4", - "ID_WWN": "0x5002538844584d30", - "ID_ATA_FEATURE_SET_SECURITY_ERASE_UNIT_MIN": "2", - "ID_TYPE": "disk", - "ID_PATH": "pci-0000:00:1f.2-ata-4", - "DEVTYPE": "disk", - "USEC_INITIALIZED": "1358780", - "ID_SERIAL_SHORT": "S1KHNYAG105196", - "SUBSYSTEM": "block", - "MAJOR": "8", - "MINOR": "0", - "ID_PART_TABLE_TYPE": "gpt", - "ID_ATA_DOWNLOAD_MICROCODE": "1", - "ID_ATA_FEATURE_SET_PM": "1", - "ID_ATA_SATA_SIGNAL_RATE_GEN2": "1" - }, - "/dev/dm-1": { - "DM_NAME": "ubuntu--vg-root", - "DEVPATH": "/devices/virtual/block/dm-1", - "MINOR": "1", - "attrs": { - "stat": " 2388406 0 83742858 9667352 1438524 0 71967288 61879432 0 1376808 71734332", - "removable": "0", - "capability": "10", - "subsystem": "block", - "ext_range": "1", - "inflight": " 0 0", - "ro": "0", - "bdi": null, - "uevent": "MAJOR=252\nMINOR=1\nDEVNAME=dm-1\nDEVTYPE=disk", - "dev": "252:1", - "size": "246536994816", - "range": "1", - "discard_alignment": "0", - "alignment_offset": "0" - }, - "SUBSYSTEM": "block", - "DM_UUID": "LVM-o1HQ3NO1UJykD3nwyjNBwFB7Sr1Fxva5rCRKhfO7jEQeJ4b1YWPc9V4co6FsBh62", - "USEC_INITIALIZED": "11617515", - "ID_FS_TYPE": "ext4", - "TAGS": ":systemd:", - "DEVLINKS": "/dev/disk/by-uuid/febb4cb9-95bc-4973-9163-d50d5f1a320c /dev/disk/by-id/dm-uuid-LVM-o1HQ3NO1UJykD3nwyjNBwFB7Sr1Fxva5rCRKhfO7jEQeJ4b1YWPc9V4co6FsBh62 /dev/disk/by-id/dm-name-ubuntu--vg-root /dev/ubuntu-vg/root /dev/mapper/ubuntu--vg-root", - "DM_UDEV_PRIMARY_SOURCE_FLAG": "1", - "ID_FS_UUID_ENC": "febb4cb9-95bc-4973-9163-d50d5f1a320c", - "DEVNAME": "/dev/dm-1", - "DEVTYPE": "disk", - "DM_VG_NAME": "ubuntu-vg", - "ID_FS_VERSION": "1.0", - "DM_STATE": "ACTIVE", - "DM_TABLE_STATE": "LIVE", - "DM_UDEV_RULES": "1", - "DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG": "1", - "DM_SUSPENDED": "0", - "DM_ACTIVATION": "1", - "DM_LV_NAME": "root", - "DM_TYPE": "raid", - "MAJOR": "252", - "ID_FS_UUID": "febb4cb9-95bc-4973-9163-d50d5f1a320c", - "ID_FS_USAGE": "filesystem" - } - } - }, - "network": { - "links": [ - { - "udev_data": { - "ID_MM_CANDIDATE": "1", - "ID_NET_LINK_FILE": "/lib/systemd/network/99-default.link", - "DEVPATH": "/devices/virtual/net/virbr0-nic", - "USEC_INITIALIZED": "26147973", - "IFINDEX": "8", - "ID_NET_DRIVER": "tun", - "attrs": { - "uevent": "INTERFACE=virbr0-nic\nIFINDEX=8", - "proto_down": "0", - "duplex": null, - "subsystem": "net", - "ifindex": "8", - "dev_port": "0", - "speed": null, - "gro_flush_timeout": "0", - "address": "52:54:00:7b:87:b0", - "operstate": "down", - "name_assign_type": null, - "tx_queue_len": "1000", - "phys_switch_id": null, - "dev_id": "0x0", - "flags": "0x1002", - "type": "1", - "phys_port_id": null, - "ifalias": "", - "carrier_changes": "1", - "mtu": "1500", - "dormant": null, - "addr_len": "6", - "broadcast": "ff:ff:ff:ff:ff:ff", - "group": "-1", - "addr_assign_type": "3", - "link_mode": "0", - "phys_port_name": null, - "tun_flags": "0x1802", - "netdev_group": "0", - "iflink": "8", - "carrier": null, - "owner": "-1" - }, - "SUBSYSTEM": "net", - "INTERFACE": "virbr0-nic", - "SYSTEMD_ALIAS": "/sys/subsystem/net/devices/virbr0-nic", - "TAGS": ":systemd:" - }, - "bond": { - "mode": null, - "slaves": [], - "is_master": false, - "is_slave": false - }, - "netlink_data": { - "flags": 4098, - "name": "virbr0-nic", - "ifindex": 8, - "arptype": 1, - "family": 0 - }, - "type": "tap", - "bridge": { - "is_port": false, - "interfaces": [], - "options": {}, - "is_bridge": false - }, - "addresses": [] - }, - { - "udev_data": { - "ID_MM_CANDIDATE": "1", - "ID_NET_LINK_FILE": "/lib/systemd/network/99-default.link", - "DEVPATH": "/devices/pci0000:00/0000:00:19.0/net/enp0s25", - "ID_PCI_CLASS_FROM_DATABASE": "Network controller", - "SUBSYSTEM": "net", - "IFINDEX": "2", - "ID_OUI_FROM_DATABASE": "Wistron InfoComm(Kunshan)Co.,Ltd.", - "ID_MODEL_FROM_DATABASE": "Ethernet Connection (3) I218-LM", - "ID_VENDOR_ID": "0x8086", - "ID_BUS": "pci", - "ID_PCI_SUBCLASS_FROM_DATABASE": "Ethernet controller", - "INTERFACE": "enp0s25", - "ID_NET_DRIVER": "e1000e", - "ID_PATH": "pci-0000:00:19.0", - "ID_MODEL_ID": "0x15a2", - "USEC_INITIALIZED": "1232122", - "SYSTEMD_ALIAS": "/sys/subsystem/net/devices/enp0s25", - "attrs": { - "uevent": "INTERFACE=enp0s25\nIFINDEX=2", - "device": null, - "proto_down": "0", - "duplex": "unknown", - "subsystem": "net", - "ifindex": "2", - "dev_port": "0", - "speed": "-1", - "gro_flush_timeout": "0", - "address": "54:ee:75:42:e5:85", - "operstate": "down", - "name_assign_type": "4", - "tx_queue_len": "1000", - "phys_switch_id": null, - "dev_id": "0x0", - "flags": "0x1003", - "type": "1", - "phys_port_id": null, - "ifalias": "", - "carrier_changes": "1", - "mtu": "1500", - "dormant": "0", - "addr_len": "6", - "broadcast": "ff:ff:ff:ff:ff:ff", - "addr_assign_type": "0", - "link_mode": "0", - "phys_port_name": null, - "netdev_group": "0", - "iflink": "2", - "carrier": "0" - }, - "ID_VENDOR_FROM_DATABASE": "Intel Corporation", - "ID_NET_NAME_PATH": "enp0s25", - "ID_PATH_TAG": "pci-0000_00_19_0", - "ID_NET_NAME_MAC": "enx54ee7542e585", - "TAGS": ":systemd:" - }, - "bond": { - "mode": null, - "slaves": [], - "is_master": false, - "is_slave": false - }, - "netlink_data": { - "flags": 4099, - "name": "enp0s25", - "ifindex": 2, - "arptype": 1, - "family": 0 - }, - "type": "eth", - "bridge": { - "is_port": false, - "interfaces": [], - "options": {}, - "is_bridge": false - }, - "addresses": [] - }, - { - "udev_data": { - "ID_MM_CANDIDATE": "1", - "ID_NET_LINK_FILE": "/lib/systemd/network/99-default.link", - "DEVPATH": "/devices/virtual/net/docker0", - "ID_NET_DRIVER": "bridge", - "DEVTYPE": "bridge", - "SUBSYSTEM": "net", - "IFINDEX": "6", - "USEC_INITIALIZED": "24337452", - "SYSTEMD_ALIAS": "/sys/subsystem/net/devices/docker0", - "TAGS": ":systemd:", - "attrs": { - "uevent": "DEVTYPE=bridge\nINTERFACE=docker0\nIFINDEX=6", - "proto_down": "0", - "duplex": null, - "subsystem": "net", - "ifindex": "6", - "dev_port": "0", - "speed": null, - "gro_flush_timeout": "0", - "address": "02:42:bf:f1:05:ec", - "operstate": "down", - "name_assign_type": "3", - "tx_queue_len": "0", - "phys_switch_id": null, - "brforward": "", - "flags": "0x1003", - "type": "1", - "phys_port_id": null, - "ifalias": "", - "carrier_changes": "1", - "mtu": "1500", - "dormant": "0", - "addr_len": "6", - "broadcast": "ff:ff:ff:ff:ff:ff", - "addr_assign_type": "3", - "link_mode": "0", - "phys_port_name": null, - "netdev_group": "0", - "dev_id": "0x0", - "iflink": "6", - "carrier": "0" - }, - "INTERFACE": "docker0" - }, - "bond": { - "mode": null, - "slaves": [], - "is_master": false, - "is_slave": false - }, - "netlink_data": { - "flags": 4099, - "name": "docker0", - "ifindex": 6, - "arptype": 1, - "family": 7 - }, - "type": "bridge", - "bridge": { - "is_port": false, - "interfaces": [], - "options": { - "hello_timer": "0", - "hello_time": "200", - "topology_change": "0", - "multicast_router": "1", - "default_pvid": "1", - "root_port": "0", - "topology_change_timer": "0", - "vlan_filtering": "0", - "group_fwd_mask": "0x0", - "stp_state": "0", - "forward_delay": "1500", - "ageing_time": "30000", - "multicast_snooping": "1", - "multicast_query_interval": "12500", - "nf_call_arptables": "0", - "priority": "32768", - "bridge_id": "8000.0242bff105ec", - "hash_max": "512", - "multicast_querier": "0", - "multicast_startup_query_interval": "3124", - "nf_call_iptables": "0", - "multicast_query_use_ifaddr": "0", - "multicast_last_member_count": "2", - "multicast_startup_query_count": "2", - "root_path_cost": "0", - "multicast_membership_interval": "26000", - "multicast_last_member_interval": "100", - "vlan_protocol": "0x8100", - "max_age": "2000", - "multicast_querier_interval": "25500", - "group_addr": "1:80:c2:0:0:0", - "tcn_timer": "0", - "gc_timer": "25913", - "root_id": "8000.0242bff105ec", - "hash_elasticity": "4", - "nf_call_ip6tables": "0", - "multicast_query_response_interval": "1000", - "topology_change_detected": "0" - }, - "is_bridge": true - }, - "addresses": [ - { - "address": "172.17.0.1/16", - "source": "static", - "scope": "global", - "family": 2 - } - ] - }, - { - "udev_data": { - "ID_MM_CANDIDATE": "1", - "ID_NET_LINK_FILE": "/lib/systemd/network/99-default.link", - "DEVPATH": "/devices/virtual/net/lxdbr0", - "ID_NET_DRIVER": "bridge", - "DEVTYPE": "bridge", - "SUBSYSTEM": "net", - "IFINDEX": "5", - "USEC_INITIALIZED": "22571117", - "SYSTEMD_ALIAS": "/sys/subsystem/net/devices/lxdbr0", - "TAGS": ":systemd:", - "attrs": { - "uevent": "DEVTYPE=bridge\nINTERFACE=lxdbr0\nIFINDEX=5", - "proto_down": "0", - "duplex": null, - "subsystem": "net", - "ifindex": "5", - "dev_port": "0", - "speed": null, - "gro_flush_timeout": "0", - "address": "fe:d6:10:53:b4:f0", - "operstate": "up", - "name_assign_type": "3", - "tx_queue_len": "1000", - "phys_switch_id": null, - "brforward": "��\u0010S��\u0001\u0001", - "flags": "0x1003", - "type": "1", - "phys_port_id": null, - "ifalias": "", - "carrier_changes": "2", - "mtu": "1500", - "dormant": "0", - "addr_assign_type": "1", - "broadcast": "ff:ff:ff:ff:ff:ff", - "addr_len": "6", - "lower_vethNH78UK": null, - "link_mode": "0", - "phys_port_name": null, - "netdev_group": "0", - "dev_id": "0x0", - "iflink": "5", - "carrier": "1" - }, - "INTERFACE": "lxdbr0" - }, - "bond": { - "mode": null, - "slaves": [], - "is_master": false, - "is_slave": false - }, - "netlink_data": { - "flags": 69699, - "name": "lxdbr0", - "ifindex": 5, - "arptype": 1, - "family": 7 - }, - "type": "bridge", - "bridge": { - "is_port": false, - "interfaces": [ - "vethNH78UK" - ], - "options": { - "hello_timer": "0", - "hello_time": "200", - "topology_change": "0", - "multicast_router": "1", - "default_pvid": "1", - "root_port": "0", - "topology_change_timer": "0", - "vlan_filtering": "0", - "group_fwd_mask": "0x0", - "stp_state": "0", - "forward_delay": "1500", - "ageing_time": "30000", - "multicast_snooping": "1", - "multicast_query_interval": "12500", - "nf_call_arptables": "0", - "priority": "32768", - "bridge_id": "8000.fed61053b4f0", - "hash_max": "512", - "multicast_querier": "0", - "multicast_startup_query_interval": "3124", - "nf_call_iptables": "0", - "multicast_query_use_ifaddr": "0", - "multicast_last_member_count": "2", - "multicast_startup_query_count": "2", - "root_path_cost": "0", - "multicast_membership_interval": "26000", - "multicast_last_member_interval": "100", - "vlan_protocol": "0x8100", - "max_age": "2000", - "multicast_querier_interval": "25500", - "group_addr": "1:80:c2:0:0:0", - "tcn_timer": "0", - "gc_timer": "1545", - "root_id": "8000.fed61053b4f0", - "hash_elasticity": "4", - "nf_call_ip6tables": "0", - "multicast_query_response_interval": "1000", - "topology_change_detected": "0" - }, - "is_bridge": true - }, - "addresses": [ - { - "address": "fe80::f8ab:30ff:fefd:67d1/64", - "source": "static", - "scope": "link", - "family": 10 - }, - { - "address": "10.144.165.1/24", - "source": "static", - "scope": "global", - "family": 2 - } - ] - }, - { - "udev_data": { - "ID_MM_CANDIDATE": "1", - "ID_NET_LINK_FILE": "/lib/systemd/network/99-default.link", - "DEVPATH": "/devices/virtual/net/virbr0", - "ID_NET_DRIVER": "bridge", - "DEVTYPE": "bridge", - "SUBSYSTEM": "net", - "IFINDEX": "7", - "USEC_INITIALIZED": "26148482", - "SYSTEMD_ALIAS": "/sys/subsystem/net/devices/virbr0", - "TAGS": ":systemd:", - "attrs": { - "uevent": "DEVTYPE=bridge\nINTERFACE=virbr0\nIFINDEX=7", - "proto_down": "0", - "duplex": null, - "subsystem": "net", - "ifindex": "7", - "dev_port": "0", - "speed": null, - "gro_flush_timeout": "0", - "address": "00:00:00:00:00:00", - "operstate": "down", - "name_assign_type": "3", - "tx_queue_len": "1000", - "phys_switch_id": null, - "brforward": "", - "flags": "0x1003", - "type": "1", - "phys_port_id": null, - "ifalias": "", - "carrier_changes": "1", - "mtu": "1500", - "dormant": "0", - "addr_len": "6", - "broadcast": "ff:ff:ff:ff:ff:ff", - "addr_assign_type": "1", - "link_mode": "0", - "phys_port_name": null, - "netdev_group": "0", - "dev_id": "0x0", - "iflink": "7", - "carrier": "0" - }, - "INTERFACE": "virbr0" - }, - "bond": { - "mode": null, - "slaves": [], - "is_master": false, - "is_slave": false - }, - "netlink_data": { - "flags": 4099, - "name": "virbr0", - "ifindex": 7, - "arptype": 1, - "family": 7 - }, - "type": "bridge", - "bridge": { - "is_port": false, - "interfaces": [], - "options": { - "hello_timer": "35", - "hello_time": "200", - "topology_change": "0", - "multicast_router": "1", - "default_pvid": "1", - "root_port": "0", - "topology_change_timer": "0", - "vlan_filtering": "0", - "group_fwd_mask": "0x0", - "stp_state": "1", - "forward_delay": "200", - "ageing_time": "30000", - "multicast_snooping": "1", - "multicast_query_interval": "12500", - "nf_call_arptables": "0", - "priority": "32768", - "bridge_id": "8000.000000000000", - "hash_max": "512", - "multicast_querier": "0", - "multicast_startup_query_interval": "3124", - "nf_call_iptables": "0", - "multicast_query_use_ifaddr": "0", - "multicast_last_member_count": "2", - "multicast_startup_query_count": "2", - "root_path_cost": "0", - "multicast_membership_interval": "26000", - "multicast_last_member_interval": "100", - "vlan_protocol": "0x8100", - "max_age": "2000", - "multicast_querier_interval": "25500", - "group_addr": "1:80:c2:0:0:0", - "tcn_timer": "0", - "gc_timer": "26320", - "root_id": "8000.000000000000", - "hash_elasticity": "4", - "nf_call_ip6tables": "0", - "multicast_query_response_interval": "1000", - "topology_change_detected": "0" - }, - "is_bridge": true - }, - "addresses": [ - { - "address": "192.168.122.1/24", - "source": "static", - "scope": "global", - "family": 2 - } - ] - }, - { - "udev_data": { - "ID_MM_CANDIDATE": "1", - "ID_NET_LINK_FILE": "/lib/systemd/network/99-default.link", - "DEVPATH": "/devices/virtual/net/vethNH78UK", - "ID_NET_DRIVER": "veth", - "SUBSYSTEM": "net", - "IFINDEX": "10", - "USEC_INITIALIZED": "32415842", - "SYSTEMD_ALIAS": "/sys/subsystem/net/devices/vethNH78UK", - "TAGS": ":systemd:", - "attrs": { - "uevent": "INTERFACE=vethNH78UK\nIFINDEX=10", - "proto_down": "0", - "duplex": "full", - "subsystem": "net", - "ifindex": "10", - "dev_port": "0", - "speed": "10000", - "gro_flush_timeout": "0", - "address": "fe:d6:10:53:b4:f0", - "upper_lxdbr0": null, - "operstate": "up", - "name_assign_type": "3", - "tx_queue_len": "1000", - "master": null, - "phys_switch_id": null, - "dev_id": "0x0", - "flags": "0x1303", - "type": "1", - "phys_port_id": null, - "ifalias": "", - "carrier_changes": "2", - "mtu": "1500", - "dormant": "0", - "addr_len": "6", - "broadcast": "ff:ff:ff:ff:ff:ff", - "addr_assign_type": "3", - "link_mode": "0", - "phys_port_name": null, - "netdev_group": "0", - "iflink": "9", - "carrier": "1" - }, - "INTERFACE": "vethNH78UK", - "NM_UNMANAGED": "1" - }, - "bond": { - "mode": null, - "slaves": [], - "is_master": false, - "is_slave": false - }, - "netlink_data": { - "flags": 69699, - "name": "vethNH78UK", - "ifindex": 10, - "arptype": 1, - "family": 0 - }, - "type": "eth", - "bridge": { - "is_port": true, - "interfaces": [], - "options": { - "multicast_router": "1", - "path_cost": "2", - "unicast_flood": "1", - "forward_delay_timer": "0", - "priority": "32", - "designated_bridge": "8000.fed61053b4f0", - "state": "3", - "message_age_timer": "0", - "proxyarp": "0", - "learning": "1", - "designated_cost": "0", - "port_id": "0x8001", - "designated_root": "8000.fed61053b4f0", - "change_ack": "0", - "hold_timer": "0", - "hairpin_mode": "0", - "proxyarp_wifi": "0", - "designated_port": "32769", - "root_block": "0", - "config_pending": "0", - "bpdu_guard": "0", - "port_no": "0x1", - "multicast_fast_leave": "0" - }, - "is_bridge": false - }, - "addresses": [ - { - "address": "fe80::fcd6:10ff:fe53:b4f0/64", - "source": "static", - "scope": "link", - "family": 10 - } - ] - }, - { - "udev_data": { - "ID_MM_CANDIDATE": "1", - "ID_NET_LINK_FILE": "/lib/systemd/network/99-default.link", - "DEVPATH": "/devices/pci0000:00/0000:00:14.0/usb3/3-3/3-3.1/3-3.1.3/3-3.1.3:1.0/net/enx0050b6c11ec4", - "ID_USB_INTERFACE_NUM": "00", - "attrs": { - "uevent": "INTERFACE=enx0050b6c11ec4\nIFINDEX=12", - "device": null, - "proto_down": "0", - "duplex": "full", - "subsystem": "net", - "ifindex": "12", - "dev_port": "0", - "speed": "1000", - "gro_flush_timeout": "0", - "address": "00:50:b6:c1:1e:c4", - "operstate": "up", - "name_assign_type": "4", - "tx_queue_len": "1000", - "phys_switch_id": null, - "dev_id": "0x0", - "flags": "0x1003", - "type": "1", - "phys_port_id": null, - "ifalias": "", - "carrier_changes": "2", - "mtu": "1500", - "dormant": "0", - "addr_len": "6", - "broadcast": "ff:ff:ff:ff:ff:ff", - "addr_assign_type": "0", - "link_mode": "0", - "phys_port_name": null, - "netdev_group": "0", - "iflink": "12", - "carrier": "1" - }, - "ID_SERIAL": "Lenovo_ThinkPad_Dock_Giga_0050B6C11EC4", - "SUBSYSTEM": "net", - "SYSTEMD_ALIAS": "/sys/subsystem/net/devices/enx0050b6c11ec4 /sys/subsystem/net/devices/enx0050b6c11ec4", - "IFINDEX": "12", - "ID_USB_DRIVER": "r8152", - "ID_OUI_FROM_DATABASE": "GOOD WAY IND. CO., LTD.", - "INTERFACE": "enx0050b6c11ec4", - "ID_VENDOR_ID": "17ef", - "ID_BUS": "usb", - "ID_MODEL_ENC": "ThinkPad\\x20Dock\\x20Giga", - "ID_MODEL": "ThinkPad_Dock_Giga", - "ID_REVISION": "3000", - "ID_NET_DRIVER": "r8152", - "ID_VENDOR_ENC": "Lenovo", - "ID_NET_NAME": "enp0s20u3u1u3", - "ID_TYPE": "generic", - "ID_PATH": "pci-0000:00:14.0-usb-0:3.1.3:1.0", - "ID_MODEL_ID": "304f", - "USEC_INITIALIZED": "34248108169", - "ID_VENDOR": "Lenovo", - "ID_SERIAL_SHORT": "0050B6C11EC4", - "ID_VENDOR_FROM_DATABASE": "Lenovo", - "ID_NET_NAME_PATH": "enp0s20u3u1u3", - "ID_PATH_TAG": "pci-0000_00_14_0-usb-0_3_1_3_1_0", - "ID_USB_INTERFACES": ":ffff00:020600:0a0000:", - "ID_NET_NAME_MAC": "enx0050b6c11ec4", - "TAGS": ":systemd:" - }, - "bond": { - "mode": null, - "slaves": [], - "is_master": false, - "is_slave": false - }, - "netlink_data": { - "flags": 69699, - "name": "enx0050b6c11ec4", - "ifindex": 12, - "arptype": 1, - "family": 0 - }, - "type": "eth", - "bridge": { - "is_port": false, - "interfaces": [], - "options": {}, - "is_bridge": false - }, - "addresses": [ - { - "address": "10.100.1.125/22", - "source": "dhcp", - "scope": "global", - "family": 2 - }, - { - "address": "fe80::8761:5fab:f8b:a6fb/64", - "source": "static", - "scope": "link", - "family": 10 - } - ] - }, - { - "udev_data": { - "ID_MM_CANDIDATE": "1", - "ID_NET_LINK_FILE": "/lib/systemd/network/99-default.link", - "DEVPATH": "/devices/pci0000:00/0000:00:1c.1/0000:04:00.0/net/wlp4s0", - "ID_PCI_CLASS_FROM_DATABASE": "Network controller", - "SUBSYSTEM": "net", - "IFINDEX": "4", - "ID_OUI_FROM_DATABASE": "Intel Corporate", - "ID_MODEL_FROM_DATABASE": "Wireless 7265 (Dual Band Wireless-AC 7265)", - "ID_VENDOR_ID": "0x8086", - "ID_BUS": "pci", - "ID_PCI_SUBCLASS_FROM_DATABASE": "Network controller", - "INTERFACE": "wlp4s0", - "ID_NET_DRIVER": "iwlwifi", - "DEVTYPE": "wlan", - "ID_NET_NAME": "wlp4s0", - "ID_PATH": "pci-0000:04:00.0", - "ID_MODEL_ID": "0x095b", - "USEC_INITIALIZED": "20672104", - "SYSTEMD_ALIAS": "/sys/subsystem/net/devices/wlp4s0 /sys/subsystem/net/devices/wlp4s0", - "attrs": { - "uevent": "DEVTYPE=wlan\nINTERFACE=wlp4s0\nIFINDEX=4", - "device": null, - "proto_down": "0", - "duplex": null, - "subsystem": "net", - "ifindex": "4", - "dev_port": "0", - "speed": null, - "gro_flush_timeout": "0", - "address": "60:57:18:9b:a4:bf", - "operstate": "up", - "name_assign_type": "4", - "tx_queue_len": "1000", - "phys_switch_id": null, - "dev_id": "0x0", - "flags": "0x1003", - "type": "1", - "phys_port_id": null, - "ifalias": "", - "carrier_changes": "18", - "mtu": "1500", - "dormant": "0", - "addr_len": "6", - "broadcast": "ff:ff:ff:ff:ff:ff", - "addr_assign_type": "0", - "link_mode": "1", - "phys_port_name": null, - "netdev_group": "0", - "phy80211": null, - "iflink": "4", - "carrier": "1" - }, - "ID_VENDOR_FROM_DATABASE": "Intel Corporation", - "ID_NET_NAME_PATH": "wlp4s0", - "ID_PATH_TAG": "pci-0000_04_00_0", - "ID_NET_NAME_MAC": "wlx6057189ba4bf", - "TAGS": ":systemd:" - }, - "bond": { - "mode": null, - "slaves": [], - "is_master": false, - "is_slave": false - }, - "netlink_data": { - "flags": 69699, - "name": "wlp4s0", - "ifindex": 4, - "arptype": 1, - "family": 0 - }, - "wlan": { - "visible_ssids": [], - "scan_state": null, - "ssid": "BizDojo-5Ghz" - }, - "type": "wlan", - "bridge": { - "is_port": false, - "interfaces": [], - "options": {}, - "is_bridge": false - }, - "addresses": [ - { - "address": "10.100.2.229/22", - "source": "dhcp", - "scope": "global", - "family": 2 - }, - { - "address": "fe80::727c:b9fe:c9e6:b898/64", - "source": "static", - "scope": "link", - "family": 10 - } - ] - }, - { - "udev_data": { - "ID_MM_CANDIDATE": "1", - "ID_NET_LINK_FILE": "/lib/systemd/network/99-default.link", - "DEVPATH": "/devices/virtual/net/lo", - "USEC_INITIALIZED": "958219", - "IFINDEX": "1", - "attrs": { - "uevent": "INTERFACE=lo\nIFINDEX=1", - "proto_down": "0", - "duplex": null, - "subsystem": "net", - "ifindex": "1", - "dev_port": "0", - "speed": null, - "gro_flush_timeout": "0", - "address": "00:00:00:00:00:00", - "operstate": "unknown", - "name_assign_type": null, - "tx_queue_len": "1", - "phys_switch_id": null, - "dev_id": "0x0", - "flags": "0x9", - "type": "772", - "phys_port_id": null, - "ifalias": "", - "carrier_changes": "0", - "mtu": "65536", - "dormant": "0", - "addr_len": "6", - "broadcast": "00:00:00:00:00:00", - "addr_assign_type": "0", - "link_mode": "0", - "phys_port_name": null, - "netdev_group": "0", - "iflink": "1", - "carrier": "1" - }, - "SUBSYSTEM": "net", - "INTERFACE": "lo" - }, - "bond": { - "mode": null, - "slaves": [], - "is_master": false, - "is_slave": false - }, - "netlink_data": { - "flags": 65609, - "name": "lo", - "ifindex": 1, - "arptype": 772, - "family": 0 - }, - "type": "lo", - "bridge": { - "is_port": false, - "interfaces": [], - "options": {}, - "is_bridge": false - }, - "addresses": [ - { - "address": "127.0.0.1/8", - "source": "static", - "scope": "host", - "family": 2 - }, - { - "address": "::1/128", - "source": "static", - "scope": "host", - "family": 10 - } - ] - } - ], - "routes": [ - { - "ifindex": 12, - "table": 254, - "dst": "default", - "family": 2, - "type": 1 - }, - { - "ifindex": 4, - "table": 254, - "dst": "default", - "family": 2, - "type": 1 - }, - { - "ifindex": 12, - "table": 254, - "dst": "10.100.0.0/22", - "family": 2, - "type": 1 - }, - { - "ifindex": 4, - "table": 254, - "dst": "10.100.0.0/22", - "family": 2, - "type": 1 - }, - { - "ifindex": 5, - "table": 254, - "dst": "10.144.165.0/24", - "family": 2, - "type": 1 - }, - { - "ifindex": 5, - "table": 254, - "dst": "169.254.0.0/16", - "family": 2, - "type": 1 - }, - { - "ifindex": 6, - "table": 254, - "dst": "172.17.0.0/16", - "family": 2, - "type": 1 - }, - { - "ifindex": 7, - "table": 254, - "dst": "192.168.122.0/24", - "family": 2, - "type": 1 - }, - { - "ifindex": 4, - "table": 255, - "dst": "10.100.0.0", - "family": 2, - "type": 3 - }, - { - "ifindex": 12, - "table": 255, - "dst": "10.100.1.125", - "family": 2, - "type": 2 - }, - { - "ifindex": 4, - "table": 255, - "dst": "10.100.2.229", - "family": 2, - "type": 2 - }, - { - "ifindex": 4, - "table": 255, - "dst": "10.100.3.255", - "family": 2, - "type": 3 - }, - { - "ifindex": 5, - "table": 255, - "dst": "10.144.165.0", - "family": 2, - "type": 3 - }, - { - "ifindex": 5, - "table": 255, - "dst": "10.144.165.1", - "family": 2, - "type": 2 - }, - { - "ifindex": 5, - "table": 255, - "dst": "10.144.165.255", - "family": 2, - "type": 3 - }, - { - "ifindex": 1, - "table": 255, - "dst": "127.0.0.0", - "family": 2, - "type": 3 - }, - { - "ifindex": 1, - "table": 255, - "dst": "127.0.0.0/8", - "family": 2, - "type": 2 - }, - { - "ifindex": 1, - "table": 255, - "dst": "127.0.0.1", - "family": 2, - "type": 2 - }, - { - "ifindex": 1, - "table": 255, - "dst": "127.255.255.255", - "family": 2, - "type": 3 - }, - { - "ifindex": 6, - "table": 255, - "dst": "172.17.0.0", - "family": 2, - "type": 3 - }, - { - "ifindex": 6, - "table": 255, - "dst": "172.17.0.1", - "family": 2, - "type": 2 - }, - { - "ifindex": 6, - "table": 255, - "dst": "172.17.255.255", - "family": 2, - "type": 3 - }, - { - "ifindex": 7, - "table": 255, - "dst": "192.168.122.0", - "family": 2, - "type": 3 - }, - { - "ifindex": 7, - "table": 255, - "dst": "192.168.122.1", - "family": 2, - "type": 2 - }, - { - "ifindex": 7, - "table": 255, - "dst": "192.168.122.255", - "family": 2, - "type": 3 - }, - { - "ifindex": 5, - "table": 254, - "dst": "fe80::/64", - "family": 10, - "type": 1 - }, - { - "ifindex": 1, - "table": 0, - "dst": "default", - "family": 10, - "type": 7 - }, - { - "ifindex": 1, - "table": 255, - "dst": "::1", - "family": 10, - "type": 2 - }, - { - "ifindex": 1, - "table": 255, - "dst": "fe80::727c:b9fe:c9e6:b898", - "family": 10, - "type": 2 - }, - { - "ifindex": 1, - "table": 255, - "dst": "fe80::8761:5fab:f8b:a6fb", - "family": 10, - "type": 2 - }, - { - "ifindex": 1, - "table": 255, - "dst": "fe80::f8ab:30ff:fefd:67d1", - "family": 10, - "type": 2 - }, - { - "ifindex": 1, - "table": 255, - "dst": "fe80::fcd6:10ff:fe53:b4f0", - "family": 10, - "type": 2 - }, - { - "ifindex": 5, - "table": 255, - "dst": "ff00::/8", - "family": 10, - "type": 1 - } - ] - } -} From 880d23cb75d2d3a4bed97668e871d6ecc83d667e Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Thu, 30 May 2019 14:13:45 +1200 Subject: [PATCH 18/23] use my curtin branch for now --- snapcraft.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snapcraft.yaml b/snapcraft.yaml index 148bcf06..48d445dd 100644 --- a/snapcraft.yaml +++ b/snapcraft.yaml @@ -26,8 +26,8 @@ parts: curtin: plugin: python source-type: git - source: git://git.launchpad.net/curtin - source-branch: ubuntu/devel + source: git://git.launchpad.net/~mwhudson/curtin + source-branch: for-subiquity requirements: requirements.txt organize: 'lib/python*/site-packages/usr/lib/curtin': 'usr/lib/' From 9ef3ce19a18f6b96274c92ee0657c6dea55e370d Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Thu, 30 May 2019 14:20:52 +1200 Subject: [PATCH 19/23] add ppa:mwhudson/devirt to get newer version of curtin for now --- scripts/installdeps.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/installdeps.sh b/scripts/installdeps.sh index ab75efda..075ec8d9 100755 --- a/scripts/installdeps.sh +++ b/scripts/installdeps.sh @@ -2,6 +2,7 @@ set -eux apt-get update DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade +add-apt-repository -u ppa:mwhudson/devirt < /dev/null apt-get install -y --no-install-recommends libnl-3-dev libnl-genl-3-dev libnl-route-3-dev libsystemd-dev python3-distutils-extra pkg-config python3.5 python3-pip git lsb-release python3-setuptools gcc python3-dev python3-wheel curtin pep8 python3-pyflakes pip3 install -r requirements.txt python3 setup.py build From 6fb185647b0568e3b6ebead652268318867a47c6 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Thu, 30 May 2019 14:51:04 +1200 Subject: [PATCH 20/23] tweak _Device.available for existing partitions --- subiquity/models/filesystem.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/subiquity/models/filesystem.py b/subiquity/models/filesystem.py index f5b3b84f..94bf6036 100644 --- a/subiquity/models/filesystem.py +++ b/subiquity/models/filesystem.py @@ -533,7 +533,8 @@ class _Device(_Formattable, ABC): if self._fs is not None: return self._fs._available() if self.free_for_partitions > 0: - return True + if not self._has_preexisting_partition(): + return True for p in self._partitions: if p.available(): return True From 8cf5bacfbbed888104ef89fa8633121341fa3965 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Fri, 31 May 2019 15:03:32 +1200 Subject: [PATCH 21/23] fixup! support for editing existing partitions --- subiquity/controllers/filesystem.py | 2 +- subiquity/models/filesystem.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/subiquity/controllers/filesystem.py b/subiquity/controllers/filesystem.py index e09ac0e4..0834b520 100644 --- a/subiquity/controllers/filesystem.py +++ b/subiquity/controllers/filesystem.py @@ -288,7 +288,7 @@ class FilesystemController(BaseController): fs = volume.original_fs() if fs is None: return - self.model.readd_filesystem(fs) + self.model.re_add_filesystem(fs) else: fs = self.model.add_filesystem(volume, spec['fstype']) if isinstance(volume, Partition): diff --git a/subiquity/models/filesystem.py b/subiquity/models/filesystem.py index 94bf6036..9e42eebc 100644 --- a/subiquity/models/filesystem.py +++ b/subiquity/models/filesystem.py @@ -1384,7 +1384,7 @@ class FilesystemModel(object): self._actions.append(fs) return fs - def readd_filesystem(self, fs): + def re_add_filesystem(self, fs): _set_backlinks(fs) self._actions.append(fs) From 245d562f68bc348180b6012fdfda9cb570466b97 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Fri, 31 May 2019 15:04:30 +1200 Subject: [PATCH 22/23] fixup! the REFORMAT action --- subiquity/models/filesystem.py | 2 -- subiquity/models/tests/test_filesystem.py | 14 +++++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/subiquity/models/filesystem.py b/subiquity/models/filesystem.py index 9e42eebc..edc4f4cb 100644 --- a/subiquity/models/filesystem.py +++ b/subiquity/models/filesystem.py @@ -693,8 +693,6 @@ class Disk(_Device): @property def _can_REFORMAT(self): - if not self.preserve: - return False if len(self._partitions) == 0: return False for p in self._partitions: diff --git a/subiquity/models/tests/test_filesystem.py b/subiquity/models/tests/test_filesystem.py index d5300b88..e71cd0ef 100644 --- a/subiquity/models/tests/test_filesystem.py +++ b/subiquity/models/tests/test_filesystem.py @@ -359,18 +359,26 @@ class TestFilesystemModel(unittest.TestCase): disk1 = make_disk(model, preserve=False) self.assertActionNotPossible(disk1, DeviceAction.REFORMAT) + disk1p1 = make_partition(model, disk1, preserve=False) + self.assertActionPossible(disk1, DeviceAction.REFORMAT) + model.add_volgroup('vg0', {disk1p1}) + self.assertActionNotPossible(disk1, DeviceAction.REFORMAT) disk2 = make_disk(model, preserve=True) self.assertActionNotPossible(disk2, DeviceAction.REFORMAT) disk2p1 = make_partition(model, disk2, preserve=True) self.assertActionPossible(disk2, DeviceAction.REFORMAT) - model.add_volgroup('vg0', {disk2p1}) + model.add_volgroup('vg1', {disk2p1}) self.assertActionNotPossible(disk2, DeviceAction.REFORMAT) - disk3 = make_disk(model, preserve=True) - model.add_volgroup('vg1', {disk3}) + disk3 = make_disk(model, preserve=False) + model.add_volgroup('vg2', {disk3}) self.assertActionNotPossible(disk3, DeviceAction.REFORMAT) + disk4 = make_disk(model, preserve=True) + model.add_volgroup('vg2', {disk4}) + self.assertActionNotPossible(disk4, DeviceAction.REFORMAT) + def test_disk_action_PARTITION(self): model, disk = make_model_and_disk() self.assertActionPossible(disk, DeviceAction.PARTITION) From c1e3ad98b38c48d94d023c026cee68744ad5e406 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Fri, 31 May 2019 15:00:21 +1200 Subject: [PATCH 23/23] fixup! call extract_storage_config with probert config to create actions --- subiquity/models/filesystem.py | 43 ++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/subiquity/models/filesystem.py b/subiquity/models/filesystem.py index edc4f4cb..95484b5f 100644 --- a/subiquity/models/filesystem.py +++ b/subiquity/models/filesystem.py @@ -1122,6 +1122,27 @@ class FilesystemModel(object): self.grub_install_device = None def _actions_from_config(self, config, blockdevs): + """Convert curtin storage config into action instances. + + curtin represents storage "actions" as defined in + https://curtin.readthedocs.io/en/latest/topics/storage.html. We + convert each action (that we know about) into an instance of + Disk, Partition, RAID, etc (unknown actions, e.g. bcache, are + just ignored). + + We also filter out anything that can be reached from a currently + mounted device. The motivation here is only to exclude the media + subiquity is mounted from, so this might be a bit excessive but + hey it works. + + Perhaps surprisingly the order of the returned actions matters. + The devices are presented in the filesystem view in the reverse + of the order they appear in _actions, which means that e.g. a + RAID appears higher up the list than the disks is is composed + of. This is quite important as it makes "unpeeling" existing + compound structures easy, you just delete the top device until + you only have disks left. + """ byid = {} objs = [] exclusions = set() @@ -1140,12 +1161,18 @@ class FilesystemModel(object): if n not in action: continue v = action[n] - if f.metadata.get('ref', False): - kw[n] = byid[v] - elif f.metadata.get('reflist', False): - kw[n] = [byid[id] for id in v] - else: - kw[n] = v + try: + if f.metadata.get('ref', False): + kw[n] = byid[v] + elif f.metadata.get('reflist', False): + kw[n] = [byid[id] for id in v] + else: + kw[n] = v + except KeyError: + # If a dependency of the current action has been + # ignored, we need to ignore the current action too + # (e.g. a bcache's filesystem). + continue if kw['type'] == 'disk': path = kw['path'] kw['info'] = StorageInfo({path: blockdevs[path]}) @@ -1155,10 +1182,6 @@ class FilesystemModel(object): obj.volume._original_fs = obj objs.append(obj) - # We filter out anything that can be reached from a currently - # mounted device. The motivation here is only to exclude the - # media subiquity is mounted from, so this might be a bit - # excessive but hey it works. while True: log.debug("exclusions %s", {e.id for e in exclusions}) next_exclusions = exclusions.copy()