From f5cd5932eb915d160a0b867fa0447f08a398085c Mon Sep 17 00:00:00 2001 From: Philip Guyton Date: Fri, 23 Nov 2018 20:20:11 +0000 Subject: [PATCH] pool resize disk removal unknown internal error and no UI counterpart #1722 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix disk removal timeout failure re "Unknown internal error doing a PUT .../remove" by asynchronously executing 'btrfs dev remove'. The pool_balance model was extending to accommodate for what are arbitrarily named (within Rockstor) 'internal' balances: those automatically initiated upon every 'btrfs dev delete' by the btrfs subsystem itself. A complication of 'internal' balances is  their invisibility via 'btrfs balance status'. An inference mechanism was thus constructed to 'fake' the output of a regular balance status so that our existing Web-UI balance surfacing mechanisms could be extended to serve these 'internal' variants similarly. The new state of device 'in removal' and the above mentioned inference mechanism required that we now track and update devid and per device allocation. These were added as disk model fields and surfaced appropriately at the pool details level within the Web-UI. Akin to regular balances, btrfs dev delete 'internal' balances were found to negatively impact Web-UI interactivity. This was in part alleviated by refactoring the lowest levels of our disk/pool scan mechanisms. In essence this refactoring significantly reduces the number of system and python calls required to attain the same system wide dev / pool info and simplifies low level device name handling. Existing unit tests were employed to aid in this refactoring. Minor additional code was required to account for regressions (predominantly in LUKS device name handling) that were introduced by these low level device name code changes. Summary: - Execute device removal asynchronously. - Monitor the consequent 'internal' balances by existing mechanisms where possible. - Only remove pool members pool associations once their associated 'internal' balance has finished. - Improve low level efficiency/clarity re device/pool scanning by moving to a single call of the lighter get_dev_pool_info() rather than calling the slower get_pool_info() btrfs disk count times; get_pool_info() is retained for pool import duties as it’s structure is ideally suited to that task. Multiple prior temp_name/by-id conversions are also avoided. - Improve user messaging re system performance / Web-UI responsiveness during a balance operation, regular or 'internal'. - Fix bug re reliance on "None" disk label removing a fragility concerning disk pool association within the Web-UI. - Improve auto pool labeling subsystem by abstracting and generalising ready for pool renaming capability. - Improve pool uuid tracking and add related Web-UI element. - Add Web-UI element in balance status tab to identify regular or 'internal' balance type. - Add devid tracking and related Web-UI element. - Use devid Disk model info to ascertain pool info for detached disks. - Add per device allocation tracking and related Web-UI element. - Fix prior TODO: re btrfs in partition failure point introduced in git tag 3.9.2-32. - Fix prior TODO: re unlabeled pools caveat. - Add pool details disks table ‘Page refresh required’ indicator keyed from devid=0. - Add guidance on common detached disk removal reboot requirement. - Remove a low level special case for LUKS dev matching (mapped devices) which affected the performance of all dev name by-id lookups. - Add TODO re removing legacy formatted disk raid role pre openSUSE move. - Update scan_disks() unit tests for new 'path included' output. - Address todo in scan_disks() unit tests and normalise on pre sort method. --- src/rockstor/fs/btrfs.py | 289 ++++++++-- src/rockstor/scripts/flash_optimize.py | 6 +- .../migrations/0008_auto_20190115_1637.py | 29 + src/rockstor/storageadmin/models/disk.py | 8 +- .../storageadmin/models/pool_balance.py | 2 + .../js/templates/pool/pool_info_module.jst | 3 +- .../pool/poolrebalance_table_template.jst | 6 +- .../pool/resize/remove_disks_complete.jst | 13 +- .../js/templates/pool/resize_pool_info.jst | 10 + .../js/views/pool_details_layout_view.js | 25 +- .../js/views/pool_rebalance_table.js | 22 +- src/rockstor/storageadmin/views/command.py | 35 +- src/rockstor/storageadmin/views/disk.py | 133 +++-- src/rockstor/storageadmin/views/pool.py | 75 ++- .../storageadmin/views/pool_balance.py | 14 +- src/rockstor/system/luks.py | 2 +- src/rockstor/system/osi.py | 106 +++- src/rockstor/system/tests/test_osi.py | 507 +++++++++--------- 18 files changed, 871 insertions(+), 414 deletions(-) create mode 100644 src/rockstor/storageadmin/migrations/0008_auto_20190115_1637.py diff --git a/src/rockstor/fs/btrfs.py b/src/rockstor/fs/btrfs.py index 0695fb769..e5c6bd05c 100644 --- a/src/rockstor/fs/btrfs.py +++ b/src/rockstor/fs/btrfs.py @@ -15,13 +15,14 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ +import collections import json import re import time import os from system.osi import run_command, create_tmp_dir, is_share_mounted, \ is_mounted, get_dev_byid_name, convert_to_kib, toggle_path_rw, \ - get_device_path + get_device_path, dev_mount_point from system.exceptions import (CommandException) from pool_scrub import PoolScrub from django_ztask.decorators import task @@ -56,6 +57,15 @@ # Note in the above we have a non symmetrical exclusions entry of '@/.snapshots # this is to help distinguish our .snapshots from snapper's rollback subvol. +# tuple subclass for devices from a btrfs view. +Dev = collections.namedtuple('Dev', 'temp_name is_byid devid size allocated') +# Named Tuple for Device Pool Info. +DevPoolInfo = collections.namedtuple('DevPoolInfo', + 'devid size allocated uuid label') +# Named Tuple for btrfs device usage info. +DevUsageInfo = collections.namedtuple('DevUsageInfo', 'temp_name size ' + 'allocated') + def add_pool(pool, disks): """ @@ -206,12 +216,92 @@ def degraded_pools_found(): return degraded_pool_count -def get_pool_info(disk, root_pool=False): +def set_pool_label(label, dev_temp_name, root_pool=False): + """ + Wrapper around 'btrfs fi label dev|mnt_pt' initially intended to auto label + pools (btrfs vols) that have 'none' as label since a label is assumed. + Could server as more general purpose once we have pool re-naming. + :param dev_temp_name: full_dev_path + :param label: Desired label: overridden if root_pool = True. + :param root_pool: Boolean indicator of system root ('/') pool. + :return: new label if successful or None if command exception. + """ + # we override accessor and label for the system pool. + if root_pool: + # root_pool already mounted so we must use mount point. + accessor = '/' + label = settings.SYS_VOL_LABEL + else: # adapt to mounted or unmounted non system root pools: + mount_point = dev_mount_point(dev_temp_name) + if mount_point is not None: + accessor = mount_point + else: + accessor = dev_temp_name + # This requirement limits importing ro pools with no label. + cmd = [BTRFS, 'fi', 'label', accessor, label] + # Consider udevadm trigger on this device as label changed. + try: + logger.debug('Attempting auto pool label for ({}).'.format(accessor)) + o, e, rc = run_command(cmd, log=True) + except CommandException as e: + logger.error('Pool label attempt on {} to {} failed with ' + 'error: {}'.format(accessor, label, e.err)) + return None + return label + + +def get_dev_pool_info(): + """ + Variant of get_pool_info() intended for low level use where a system wide + view is required with temp_name indexing. Used as a replacement for + get_pool_info in _update_disk_state() and _refresh_pool_state() to allow + for one call to acquire all pool info system wide. Pool counterpart to + osi.py's scan_disks(). Note that there is likely much duplication within + the returned structure but we provide fast / light lookup for each device + member thereafter via it's own named tuple. + :return sys_pool_info: dict indexed by temp_name with DevPoolInfo values. + """ + cmd = [BTRFS, 'fi', 'show', '--raw'] + o, e, rc = run_command(cmd) + # Label: 'rockstor_rockstor' uuid: be5d2c5a-cc86-4c9a-96da-0a2add43f079 + # Total devices 1 FS bytes used 2444705792 + # devid 1 size 14935916544 used 3825205248 path /dev/sda3 + # + # Label: 'rock-pool' uuid: be4814da-a054-4ffe-82e7-b40ec33e4343 + # Total devices 5 FS bytes used 3913490432 + # devid 17 size 5368709120 used 1073741824 path /dev/sdb + # devid 18 size 5368709120 used 2415919104 path /dev/sdd + sys_pool_info = {} + uuid = None # Every pool has one. + label = 'none' # What is shown when there is no label on a pool. + devid = 0 # Real ones start at 1 so this can be a flag of sorts. + for line in o: + if line == '': + continue + fields = line.strip().split() + if fields[0] == 'Label:': # Pool header: set uuid and label + label = fields[1].strip("'") # single quotes present when != none + uuid = fields[3] + elif fields[0] == 'Total': + continue + elif fields[0] == 'devid': + devid = int(fields[1]) + size = int(fields[3]) / 1024 # Bytes to KB + allocated = int(fields[5]) / 1024 # Bytes to KB + temp_name = fields[-1] + dp_info = DevPoolInfo(devid=devid, size=size, allocated=allocated, + uuid=uuid, label=label) + sys_pool_info[temp_name] = dp_info + # logger.debug('get_dev_pool_info() returning {}'.format(sys_pool_info)) + return sys_pool_info + + +def get_pool_info(disk): """ Extracts pool information by running btrfs fi show and collates the results in a property keyed dictionary The disks ('disks' key) names found are translated to the by-id type (/dev/disk/by-id) so that their - counterparts in the db's Disk.name field can be found. + counterparts in the db's Disk.name field can be found. No path is stored. N.B. devices without serial may have no by-id counterpart. Enforces a non 'none' label by substituting the uuid if label = none. Used by CommandView()._refresh_pool_state() and @@ -220,45 +310,42 @@ def get_pool_info(disk, root_pool=False): :param root_pool: Boolean flag to signify root_pool enquiry mode. :return: a dictionary with keys of 'disks', 'label', 'uuid', 'hasMissingDev', 'fullDevCount', and 'missingDevCount'. - 'disks' keys a list of devices, while 'label' and 'uuid' keys are - for strings. 'hasMissingDev' is Boolean and defaults to False. - 'fullDevCount' is taken from the "Total devices" line. + 'disks' keys a dict of Dev named tuples index by their by-id names, while + 'label' and 'uuid' keys are for strings. 'hasMissingDev' is Boolean and + defaults to False. 'fullDevCount' is taken from the "Total devices" line. 'missingDevCount' is derived from fullDevCount - attached devs count. """ dpath = get_device_path(disk) - cmd = [BTRFS, 'fi', 'show', dpath] + cmd = [BTRFS, 'fi', 'show', '--raw', dpath] o, e, rc = run_command(cmd) - pool_info = {'disks': [], 'hasMissingDev': False, 'fullDevCount': 0, + # Label: 'rockstor_rockstor' uuid: be5d2c5a-cc86-4c9a-96da-0a2add43f079 + # Total devices 1 FS bytes used 2465906688 + # devid 1 size 14935916544 used 5406457856 path /dev/sda3 + pool_info = {'disks': {}, 'hasMissingDev': False, 'fullDevCount': 0, 'missingDevCount': 0} - # TODO: Move 'disks' to dictionary with (devid, size, used) tuple values full_dev_count = 0 # Number of devices in non degraded state. attached_dev_count = 0 # Number of currently attached devices. for l in o: if re.match('Label', l) is not None: fields = l.split() pool_info['uuid'] = fields[3] - label = fields[1].strip("'") - if label == 'none': - # Vol/pool has no label. - if root_pool: - # root_pool already mounted so we must use mount point. - accessor = '/' - label = settings.SYS_VOL_LABEL - else: - # Non root pools without label are assumed to be unmounted. - accessor = dpath - label = pool_info['uuid'] - # This requirement limits importing ro pools with no label. - run_command([BTRFS, 'fi', 'label', accessor, label]) - # Consider udevadm trigger on this device as label changed. - pool_info['label'] = label + pool_info['label'] = fields[1].strip("'") elif re.match('\tdevid', l) is not None: - # We have a line starting wth devid, extract the dev name. - # We convert this into the db Disk.name by-id format so that our + # We have a line starting with devid, extract the temp_name, + # devid, is_byid, size, and used. Collect in a named tuple. + # We convert name into the db Disk.name by-id format so that our # caller can locate a drive and update it's pool field reference. attached_dev_count += 1 - dev_byid, is_byid = get_dev_byid_name(l.split()[-1], True) - pool_info['disks'].append(dev_byid) + # Express device info line as a list of line elements. + fields = l.split() + temp_name = fields[-1] + dev_byid, is_byid = get_dev_byid_name(temp_name, remove_path=True) + devid = fields[1] + size = int(fields[3]) / 1024 # Bytes to KB + allocated = int(fields[5]) / 1024 # Bytes to KB + dev_info = Dev(temp_name=temp_name, is_byid=is_byid, devid=devid, + size=size, allocated=allocated) + pool_info['disks'][dev_byid] = dev_info elif re.match('\tTotal devices', l) is not None: fields = l.split() full_dev_count = int(fields[2]) @@ -266,6 +353,7 @@ def get_pool_info(disk, root_pool=False): pool_info['hasMissingDev'] = True pool_info['fullDevCount'] = full_dev_count pool_info['missingDevCount'] = full_dev_count - attached_dev_count + # logger.debug('get_pool_info() returning {}'.format(pool_info)) return pool_info @@ -312,24 +400,20 @@ def cur_devices(mnt_pt): return dev_list_byid -def resize_pool(pool, dev_list_byid, add=True): +def resize_pool_cmd(pool, dev_list_byid, add=True): """ - Acts on a given pool and list of device names by generating and then - executing the appropriate:- - "btrfs add(default)/delete root_mnt_pt(pool)" - command, or returning None if a disk member sanity check fails ie if - all the supplied devices are either not already a member of the pool - (when adding) or are already members of the pool (when deleting). - If any device in the supplied dev_list fails this test then no command is - executed and None is returned. + Given a pool and list of device names, returns the appropriate cmd of type: + "btrfs add(default)/delete root_mnt_pt(pool)", or returns + None if a disk member sanity check fails: ie if all the supplied devices + are either, not pool members (when deleting) or are already pool members + (when adding). If any device in the supplied dev_list fails this test then + no command is generated and None is returned. :param pool: btrfs pool object - :param dev_list_byid: list of devices to add/delete in by-id (without - path). - :param add: when true (default) or not specified then attempt to add - dev_list devices to pool, or when specified as True attempt to delete + :param dev_list_byid: by-id device list to add/delete (without paths). + :param add: when true (default) or not specified then 'device add' + dev_list devices to pool, when specified as True 'device delete' dev_list devices from pool. - :return: Tuple of results from run_command(generated command) or None if - the device member/pool sanity check fails. + :return: appropriate btrfs command, or None if member sanity checks failed. """ if pool.has_missing_dev and not add: if dev_list_byid == []: @@ -345,24 +429,27 @@ def resize_pool(pool, dev_list_byid, add=True): root_mnt_pt = mount_root(pool) cur_dev = cur_devices(root_mnt_pt) resize_flag = 'add' - if (not add): + if not add: resize_flag = 'delete' resize_cmd = [BTRFS, 'device', resize_flag, ] # Until we verify that all devices are or are not already members of the # given pool, depending on if we are adding (default) or removing # (add=False), we set our resize flag to false. resize = False + # TODO: This test looks to pass if only one member passes. Revisit. + # TODO: But we are after a fail if only one member fails. for d in dev_list_byid: if (resize_flag == 'add' and (d not in cur_dev)) or \ (resize_flag == 'delete' and ((d in cur_dev) or d == 'missing')): resize = True # Basic disk member of pool sanity check passed. resize_cmd.append(d) - if (not resize): - logger.debug('Note: resize_pool() taking no action.') + if not resize: + logger.debug('Resize pool - member sanity check failed. ' + 'Retuning None as btrfs add/delete command.') return None resize_cmd.append(root_mnt_pt) - return run_command(resize_cmd) + return resize_cmd def mount_root(pool): @@ -1505,6 +1592,21 @@ def scrub_status(pool): stats[fields[0]] = int(fields[1]) return stats +@task() +def start_resize_pool(cmd): + """ + Note for device add, which is almost instantaneous, we are currently called + without the async function extension (start_resize_pool.async()) which + bypasses our @task() decorator and we are then called directly. + + From https://github.com/dmgctrl/django-ztask we have: + "It is a recommended best practice that instead of passing a Django model + object to a task, you instead pass along the model's + ID or primary key, and re-get the object in the task function." + :param cmd: btrfs dev add/delete command in run_command() format (ie list). + """ + logger.debug('Resize pool command ({}).'.format(cmd)) + run_command(cmd) @task() def start_balance(mnt_pt, force=False, convert=None): @@ -1576,6 +1678,99 @@ def balance_status(pool): return stats +def get_devid_usage(mnt_pt): + """ + Extracts device usage information for a given mount point; includes + detached devices where devid is preserved but device name is replaced by + 'missing': where there can be multiple 'missing' entries. + Wraps 'btrfs device usage -b mnt_pt'. + Used by _update_disk_state() to retrieve detached disk size/allocated info. + :return: btrfs devid indexed dict with DevUsageInfo values + """ + ALLOCATION_TYPES = ['Data', 'Metadata', 'System'] + devid_usage_info = {} + cmd = [BTRFS, 'device', 'usage', '-b', mnt_pt] + o, e, rc = run_command(cmd) + devid = None # None allows for fast comparison for flag use. + temp_name = 'missing' + size = 0 + allocated = 0 + for line in o: + if line == '': + continue + fields = line.replace(',', ' ').split() + if fields[1] == 'slack:': + continue # We are not interested currently so skip for speed. + if fields[1] == 'ID:': # New device section: set devid index + devid = int(fields[2]) + temp_name = fields[0] + elif fields[1] == 'size:': + size = int(fields[2]) / 1024 # Bytes to KB + elif fields[0] in ALLOCATION_TYPES: + allocated += int(fields[2]) / 1024 # Bytes to KB + elif fields[0] == 'Unallocated:': + # End of a legitimate device entry so record our tally so far: + devid_usage_info[devid] = DevUsageInfo(temp_name=temp_name, + size=size, + allocated=allocated) + allocated = 0 # Reset our per device tally prior to next entry. + # logger.debug('get_devid_usage() returning {}.'.format(devid_usage_info)) + return devid_usage_info + + +def balance_status_internal(pool): + """ + As internal balance events, such as are initiated by btrfs dev remove, are + not reported by 'btrfs balance status', we have to devise our own system; + at least until these events, which can last hours, are surfaced otherwise. + Here we parse the output of 'btrfs dev usage -b mnt_pt' and look for a + negative unallocated value. This negative value progressively approaches + zero where upon the task is complete and the associated device disappears: + having had all of it's data removed. + Note that when more than one disk is removed btrfs internally does one at + a time so we need only find a single instance irrespective. + + Until we get a better option this function serves a minimal subset of the + functions provided for regular balances by balance_status(pool) but for + 'internal' balances (our name) that are auto initiated on disk removal. + A future enhancement could be to ascertain partial percent done, which may + be viable by resourcing get_devid_usage(); but since a device size can be + zero, for a detached device, and allocated approaches zero while negative + unallocated does the same this may be tricky as we have no start state + datum: leaving only a whole pool analysis - indicated disks but then the + serial nature of removal hampers this approach. + :param pool: Pool db object. + :return: dictionary containing parsed info about the balance status, + ie indexed by 'status' and 'percent_done'. + """ + stats = {'status': 'unknown', } + try: + mnt_pt = mount_root(pool) + except Exception as e: + logger.error('Exception while refreshing internal balance status for' + 'Pool({}). Returning ' + '"unknown": {}'.format(pool.name, e.__str__())) + return stats + cmd = [BTRFS, 'dev', 'usage', '-b', mnt_pt] + o, err, rc = run_command(cmd, throw=False) + unallocated = None + for line in o: + if line == '': + continue + fields = line.replace(',', ' ').split() + if fields[0] == 'Unallocated:': + unallocated = int(fields[1]) + if unallocated < 0: + stats['status'] = 'running' + break + if unallocated >= 0: + # We have not 'tell' so report a finished balance as there is no + # evidence of one happening. + stats['status'] = 'finished' + stats['percent_done'] = 100 + return stats + + def device_scan(dev_byid_list=['all']): """ When called with no parameters a 'btrfs device scan' is executed, ie a diff --git a/src/rockstor/scripts/flash_optimize.py b/src/rockstor/scripts/flash_optimize.py index ee222a9a5..f0a1efdf5 100644 --- a/src/rockstor/scripts/flash_optimize.py +++ b/src/rockstor/scripts/flash_optimize.py @@ -73,7 +73,7 @@ def trim_support(disk): run_command([YUM, 'install', '-y', 'hdparm']) logging.info('Installed hdparm successfully') - o, e, rc = run_command(['hdparm', '-I', '/dev/%s' % disk]) + o, e, rc = run_command(['hdparm', '-I', '{}'.format(disk)]) for l in o: if (re.search('Data Set Management TRIM supported', l) is not None): logging.debug('TRIM supported. info: %s' % l) @@ -84,7 +84,7 @@ def trim_support(disk): def is_flash(disk): flash = False - o, e, rc = run_command(['udevadm', 'info', '--path=/sys/block/%s' % disk]) + o, e, rc = run_command(['udevadm', 'info', '--name', disk]) for l in o: if (re.search('ID_BUS=', l) is not None): if (l.strip().split()[1].split('=')[1] != 'usb'): @@ -98,6 +98,8 @@ def is_flash(disk): # /sys/block/disk/queue/rotational is not reliable, but if [deadline] is in # /sys/block/disk/queue/scheduler, it's fair to assume flash logging.debug('Checking if scheduler is set to [deadline] for %s' % disk) + disk = disk.split('/')[-1] # strip off the path + # Note that the following may fail for sys on luks dev. with open('/sys/block/%s/queue/scheduler' % disk) as sfo: for l in sfo.readlines(): if (re.search('\[deadline\]', l) is not None): diff --git a/src/rockstor/storageadmin/migrations/0008_auto_20190115_1637.py b/src/rockstor/storageadmin/migrations/0008_auto_20190115_1637.py new file mode 100644 index 000000000..4d473da45 --- /dev/null +++ b/src/rockstor/storageadmin/migrations/0008_auto_20190115_1637.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('storageadmin', '0007_auto_20181210_0740'), + ] + + operations = [ + migrations.AddField( + model_name='disk', + name='allocated', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='disk', + name='devid', + field=models.PositiveSmallIntegerField(default=0), + ), + migrations.AddField( + model_name='poolbalance', + name='internal', + field=models.BooleanField(default=False), + ), + ] diff --git a/src/rockstor/storageadmin/models/disk.py b/src/rockstor/storageadmin/models/disk.py index 34dd0fa6a..68831e579 100644 --- a/src/rockstor/storageadmin/models/disk.py +++ b/src/rockstor/storageadmin/models/disk.py @@ -44,8 +44,14 @@ class Disk(models.Model): mostly derived from model and serial number. """ name = models.CharField(max_length=128, unique=True) - """total size in KB""" + """btrfs devid 0 is place holder as real devids start from 1""" + devid = models.PositiveSmallIntegerField(default=0) # 0 to 32767 + """total size in KB. Zero if btrfs device detached/last stage of delete.""" size = models.BigIntegerField(default=0) + """allocated in KB: ie per device 'used' in 'btrfs fi show' and total + listed per device in 'btrfs fi usage /mnt_pt'. + """ + allocated = models.BigIntegerField(default=0) """true if disk went offline""" offline = models.BooleanField(default=False) """whether the disk is partitioned at the moment. relevent for root disks diff --git a/src/rockstor/storageadmin/models/pool_balance.py b/src/rockstor/storageadmin/models/pool_balance.py index bd873c628..99fb97fbf 100644 --- a/src/rockstor/storageadmin/models/pool_balance.py +++ b/src/rockstor/storageadmin/models/pool_balance.py @@ -30,6 +30,8 @@ class PoolBalance(models.Model): start_time = models.DateTimeField(auto_now=True) end_time = models.DateTimeField(null=True) percent_done = models.IntegerField(default=0) + # Flag to denote internal auto initiated balance ie during dev delete. + internal = models.BooleanField(default=False) class Meta: app_label = 'storageadmin' diff --git a/src/rockstor/storageadmin/static/storageadmin/js/templates/pool/pool_info_module.jst b/src/rockstor/storageadmin/static/storageadmin/js/templates/pool/pool_info_module.jst index 78e7d9859..5a06738bc 100644 --- a/src/rockstor/storageadmin/static/storageadmin/js/templates/pool/pool_info_module.jst +++ b/src/rockstor/storageadmin/static/storageadmin/js/templates/pool/pool_info_module.jst @@ -30,6 +30,7 @@ {{else}} {{model.mount_status}} {{/if}} - +
+ UUID: {{model.uuid}} diff --git a/src/rockstor/storageadmin/static/storageadmin/js/templates/pool/poolrebalance_table_template.jst b/src/rockstor/storageadmin/static/storageadmin/js/templates/pool/poolrebalance_table_template.jst index 6dfcf4e17..4f5fe4692 100644 --- a/src/rockstor/storageadmin/static/storageadmin/js/templates/pool/poolrebalance_table_template.jst +++ b/src/rockstor/storageadmin/static/storageadmin/js/templates/pool/poolrebalance_table_template.jst @@ -26,9 +26,11 @@ Id - Status + Status + Type Start Time - Percent finished + + Percent finished Errors or Notes diff --git a/src/rockstor/storageadmin/static/storageadmin/js/templates/pool/resize/remove_disks_complete.jst b/src/rockstor/storageadmin/static/storageadmin/js/templates/pool/resize/remove_disks_complete.jst index 598de90cd..5cb9b48e8 100644 --- a/src/rockstor/storageadmin/static/storageadmin/js/templates/pool/resize/remove_disks_complete.jst +++ b/src/rockstor/storageadmin/static/storageadmin/js/templates/pool/resize/remove_disks_complete.jst @@ -6,6 +6,17 @@
-

Resize initiated - disk addition or raid change entails a subsequent Rockstor visible balance which may take several hours. Check status in the Balances tab. Disk delete progress is currently unmonitored.

+

Resize initiated - the associated balance can take several hours to complete and usually negatively impacts system performance. +
Check the Balances tab for status. A page refresh will be required. +

+
+
+

+ Expect reduced Web-UI responsiveness until this balance has finished. +
Removed disks will have progressively smaller Allocated GB until they are finally removed. +
Please note: a detached disk removal can fail with status ending: +
"... no missing devices found to remove" +
If you encounter this error see the Maintenance required section for guidance then try again after a reboot. +

diff --git a/src/rockstor/storageadmin/static/storageadmin/js/templates/pool/resize_pool_info.jst b/src/rockstor/storageadmin/static/storageadmin/js/templates/pool/resize_pool_info.jst index e8c81f1fd..b16a2c45d 100644 --- a/src/rockstor/storageadmin/static/storageadmin/js/templates/pool/resize_pool_info.jst +++ b/src/rockstor/storageadmin/static/storageadmin/js/templates/pool/resize_pool_info.jst @@ -42,7 +42,9 @@ Name Temp Name + Btrfs DevID Capacity + Allocated (%) Write I/O errors Read I/O errors Flush I/O errors @@ -66,7 +68,11 @@ {{this.temp_name}} + + {{btrfsDevID this.devid}} + {{humanReadableSize this.size}} + {{humanReadableAllocatedPercent this.allocated this.size}} {{ioErrorStatsTableData this.io_error_stats}} {{/each}} @@ -91,7 +97,11 @@ {{this.temp_name}} + + {{btrfsDevID this.devid}} + {{humanReadableSize this.size}} + {{humanReadableAllocatedPercent this.allocated this.size}} {{ioErrorStatsTableData this.io_error_stats}} {{/each}} diff --git a/src/rockstor/storageadmin/static/storageadmin/js/views/pool_details_layout_view.js b/src/rockstor/storageadmin/static/storageadmin/js/views/pool_details_layout_view.js index ec3639cf5..075ca1bc7 100644 --- a/src/rockstor/storageadmin/static/storageadmin/js/views/pool_details_layout_view.js +++ b/src/rockstor/storageadmin/static/storageadmin/js/views/pool_details_layout_view.js @@ -263,7 +263,7 @@ PoolDetailsLayoutView = RockstorLayoutView.extend({ if (confirm('If any detached members are listed use the Resize/ReRaid button - "Remove disks" option instead. Click OK only if "(Some Missing)" and no "detached-..." appear in the Pool page Disks sub-section?')) { var raid_level = _this.pool.get('raid'); var disk_names = ['missing']; - var delete_missing_msg = ('Delete missing is initiated (can take several hours), a progress report is currently unavailable. Balance attempts are blocked for this period.'); + var delete_missing_msg = ('Delete missing initiated - associated balance can take several hours and negatively impact system performance. Check Balances tab for status.'); $.ajax({ url: url, type: 'PUT', @@ -487,6 +487,29 @@ PoolDetailsLayoutView = RockstorLayoutView.extend({ return humanize.filesize(size * 1024); }); + Handlebars.registerHelper('humanReadableAllocatedPercent', function(allocated, size) { + var html = ''; + html += humanize.filesize(allocated * 1024); + // One decimal place of % = 1 GB per TB = normal allocation unit. + if (size == 0) { + // we likely have a disk delete/removal in operation or a + // missing / detached device so flag. + html += ' Missing or removal in progress ' + } else { + html += ' (' + ((allocated / size) * 100).toFixed(1) + '%)' + + } + return new Handlebars.SafeString(html); + }); + + Handlebars.registerHelper('btrfsDevID', function(devid){ + if (devid !== 0) { + return devid + } + var html = ' Page refresh required '; + return new Handlebars.SafeString(html) + }); + Handlebars.registerHelper('isRoot', function(role){ if (role == 'root') { return true; diff --git a/src/rockstor/storageadmin/static/storageadmin/js/views/pool_rebalance_table.js b/src/rockstor/storageadmin/static/storageadmin/js/views/pool_rebalance_table.js index 6b40d8bb5..b08430468 100644 --- a/src/rockstor/storageadmin/static/storageadmin/js/views/pool_rebalance_table.js +++ b/src/rockstor/storageadmin/static/storageadmin/js/views/pool_rebalance_table.js @@ -115,11 +115,31 @@ PoolRebalanceTableModule = RockstorModuleView.extend({ html += '' + poolrebalance.get('id') + ''; html += '' + poolrebalance.get('status') + ''; html += ''; + internal_balance = poolrebalance.get('internal'); + percent_done = poolrebalance.get('percent_done') + if (internal_balance) { + html += 'Disk Removal' + } else { + html += 'Regular' + } + html += ''; + html += ''; if (poolrebalance.get('start_time')) { html += moment(poolrebalance.get('start_time')).format(RS_DATE_FORMAT); } html += ''; - html += '' + poolrebalance.get('percent_done') + ''; + // html += ''; + // if (poolrebalance.get('end_time')) { + // html += moment(poolrebalance.get('end_time')).format(RS_DATE_FORMAT); + // } + // html += ''; + html += ''; + if (percent_done != 100 && internal_balance) { + html += 'unavailable'; + } else { + html += percent_done; + } + html + ''; html += ''; if (poolrebalance.get('message') != null) { html += poolrebalance.get('message'); diff --git a/src/rockstor/storageadmin/views/command.py b/src/rockstor/storageadmin/views/command.py index 52c2a5f52..caab8dfa2 100644 --- a/src/rockstor/storageadmin/views/command.py +++ b/src/rockstor/storageadmin/views/command.py @@ -23,9 +23,8 @@ from storageadmin.auth import DigestAuthentication from rest_framework.permissions import IsAuthenticated from storageadmin.views import DiskMixin -from system.osi import (uptime, kernel_info, get_dev_byid_name, - get_device_path) -from fs.btrfs import (mount_share, mount_root, get_pool_info, +from system.osi import (uptime, kernel_info, get_device_mapper_map) +from fs.btrfs import (mount_share, mount_root, get_dev_pool_info, pool_raid, mount_snap) from system.ssh import (sftp_mount_map, sftp_mount) from system.services import systemctl @@ -56,6 +55,10 @@ class CommandView(DiskMixin, NFSExportMixin, APIView): @staticmethod @transaction.atomic def _refresh_pool_state(): + # Get map of dm-0 to /dev/mapper members ie luks-.. devices. + mapped_devs = get_device_mapper_map() + # Get temp_names (kernel names) to btrfs pool info for attached devs. + dev_pool_info = get_dev_pool_info() for p in Pool.objects.all(): # If our pool has no disks, detached included, then delete it. # We leave pools with all detached members in place intentionally. @@ -70,22 +73,22 @@ def _refresh_pool_state(): continue try: # Get and save what info we can prior to mount. - first_attached_dev = p.disk_set.attached().first() - is_root_pool = (p.role == 'root') - # Observe any redirect role by using target_name. - byid_disk_name, is_byid = get_dev_byid_name( - get_device_path(first_attached_dev.target_name)) - if is_byid: - pool_info = get_pool_info(first_attached_dev.target_name, - is_root_pool) - pool_name = pool_info['label'] - else: + first_dev = p.disk_set.attached().first() + # Use target_name to account for redirect role. + if first_dev.target_name == first_dev.temp_name: logger.error('Skipping pool ({}) mount as attached disk ' '({}) has no by-id name (no serial # ?)'. - format(p.name, - first_attached_dev.target_name)) + format(p.name, first_dev.target_name)) continue - p.name = pool_name + if first_dev.temp_name in mapped_devs: + dev_tmp_name = '/dev/mapper/{}'.format( + mapped_devs[first_dev.temp_name]) + else: + dev_tmp_name = '/dev/{}'.format(first_dev.temp_name) + # For now we call get_dev_pool_info() once for each pool. + pool_info = dev_pool_info[dev_tmp_name] + p.name = pool_info.label + p.uuid = pool_info.uuid p.save() mount_root(p) p.raid = pool_raid('%s%s' % (settings.MNT_PT, p.name))['data'] diff --git a/src/rockstor/storageadmin/views/disk.py b/src/rockstor/storageadmin/views/disk.py index 4843c76a0..421a70c16 100644 --- a/src/rockstor/storageadmin/views/disk.py +++ b/src/rockstor/storageadmin/views/disk.py @@ -21,7 +21,8 @@ from django.db import transaction from storageadmin.models import (Disk, Pool, Share) from fs.btrfs import (enable_quota, mount_root, - get_pool_info, pool_raid) + get_pool_info, pool_raid, get_dev_pool_info, + set_pool_label, get_devid_usage) from storageadmin.serializers import DiskInfoSerializer from storageadmin.util import handle_exception from share_helpers import (import_shares, import_snapshots) @@ -82,7 +83,7 @@ def _update_disk_state(): serial_numbers_seen = [] # Acquire a dictionary of crypttab entries, dev uuid as indexed. dev_uuids_in_crypttab = get_crypttab_entries() - # Acquire a dictionary of lsblk /dev names to /dev/disk/by-id names + # Acquire a dictionary of temp_names (no path) to /dev/disk/by-id names byid_name_map = get_byid_name_map() # Make sane our db entries in view of what we know we have attached. # Device serial number is only known external unique entry, scan_disks @@ -121,7 +122,8 @@ def _update_disk_state(): do.save() # make sure all updates are flushed to db # Our db now has no device name info: all dev names are place holders. # Iterate over attached drives to update the db's knowledge of them. - # Kernel dev names are unique so safe to overwrite our db unique name. + # Get temp_name (kernel dev names) to btrfs pool info for all attached. + dev_pool_info = get_dev_pool_info() for d in disks: # start with an empty disk object dob = None @@ -131,7 +133,9 @@ def _update_disk_state(): disk_roles_identified = {} # Convert our transient but just scanned so current sda type name # to a more useful by-id type name as found in /dev/disk/by-id - byid_disk_name, is_byid = get_dev_byid_name(d.name, True) + # Note path is removed as we store, ideally, byid in Disk.name. + byid_disk_name, is_byid = get_dev_byid_name(d.name, + remove_path=True) # If the db has an entry with this disk's serial number then # use this db entry and update the device name from our new scan. if (Disk.objects.filter(serial=d.serial).exists()): @@ -159,10 +163,14 @@ def _update_disk_state(): # non btrfs uuids to track filesystems or LUKS containers. # Leaving as is for now to avoid db changes. dob.btrfs_uuid = d.uuid - # If attached disk has an fs and it isn't btrfs - if (d.fstype is not None and d.fstype != 'btrfs'): - # blank any btrfs_uuid it may have had previously. + # If attached disk isn't btrfs: + if d.fstype != 'btrfs': + # blank any btrfs related info it may have had previously. + # Pool affiliation addressed later in this loop. + # TODO: Consider moving later 'else dob.pool = None' to here. dob.btrfs_uuid = None + dob.devid = 0 + dob.allocated = 0 # ### BEGINNING OF ROLE FIELD UPDATE ### # Update the role field with scan_disks findings. # SCAN_DISKS_KNOWN_ROLES a list of scan_disks identifiable roles. @@ -170,7 +178,8 @@ def _update_disk_state(): # N.B. We have a minor legacy issue in that prior to using json # format for the db role field we stored one of 2 strings. # If either of these 2 strings are found reset to db default of - # None + # None. + # TODO: Can be removed post openSUSE as then no legacy installs. if dob.role == 'isw_raid_member'\ or dob.role == 'linux_raid_member': # These are the only legacy non json formatted roles used. @@ -288,8 +297,8 @@ def _update_disk_state(): # In the above we fail over to "" on failed index for now. disk_roles_identified['partitions'] = byid_partitions # Now we join the previous non scan_disks identified roles dict - # with those we have identified from our fresh scan_disks() data - # and return the result to our db entry in json format. + # with those we have identified/updated from our fresh scan_disks() + # data and return the result to our db entry in json format. # Note that dict of {} isn't None if (non_scan_disks_roles != {}) or (disk_roles_identified != {}): combined_roles = dict(non_scan_disks_roles, @@ -297,22 +306,35 @@ def _update_disk_state(): dob.role = json.dumps(combined_roles) else: dob.role = None - # END OF ROLE FIELD UPDATE - # If our existing Pool db knows of this disk's pool: - # First find pool association if any: - if is_byid and d.fstype == 'btrfs': - # use the canonical reference from get_pool_info() - # TODO: The following breaks with btrfs in partition, needs: - # TODO: if d.parted then extract the dev from d.partitions that - # TODO: has value 'btrfs' and get it's byid_disk_name. - # TODO: Added in pr #1949 commit a608d18 released (3.9.2-32) - p_info = get_pool_info(byid_disk_name, d.root) - # The above call also enacts a pool auto labeling mechanism. - pool_name = p_info['label'] - else: - # We fail over to the less robust disk label as no byid name. - pool_name = d.label - if Pool.objects.filter(name=pool_name).exists(): + # ### END OF ROLE FIELD UPDATE ### + # Does our existing Pool db know of this disk's pool? + # Find pool association, if any, of the current disk: + pool_name = None # Until we find otherwise. + if d.fstype == 'btrfs': + # Use canonical 'btrfs fi show' source via get_dev_pool_info() + dev_name = d.name + if d.partitions != {}: # could have btrfs fs from a partition? + # d.partitions={'/dev/vdc1': 'vfat', '/dev/vdc2': 'btrfs'} + for partition, fs in d.partitions.iteritems(): + if fs == 'btrfs': # We only allow one btrfs part / dev + dev_name = partition + break + p_info = dev_pool_info[dev_name] + pool_name = p_info.label + # TODO: First call we reset none pool label member count times! + # Corner case but room for efficiency improvement. + # Consider building a list of pools relabeled to address issue. + if pool_name == 'none': + pool_name = set_pool_label(p_info.uuid, dev_name, d.root) + # Update our disk database entry with btrfs specific data. + dob.devid = p_info.devid + # For btrfs we override disk size with more relevant btrfs size + # which should also fix btrfs in partition size as whole disk. + dob.size = p_info.size + dob.allocated = p_info.allocated + # Quick 'not None' test first to avoid redundant lengthy db filter. + if pool_name is not None \ + and Pool.objects.filter(name=pool_name).exists(): # update the disk db object's pool field accordingly. dob.pool = Pool.objects.get(name=pool_name) # this is for backwards compatibility. root pools created @@ -322,7 +344,7 @@ def _update_disk_state(): if (d.root is True): dob.pool.role = 'root' dob.pool.save() - else: # disk not member of db pool via get_pool_info() / d.label + else: # disk not member of db pool via get_dev_pool_info() dob.pool = None # If no db pool has yet been found for this disk and # the attached disk is our root disk (flagged by scan_disks): @@ -340,8 +362,10 @@ def _update_disk_state(): logger.debug('++++ Creating special system pool db entry.') root_compression = 'no' root_raid = pool_raid('/')['data'] + # scan_disks() has already acquired our fs uuid so inherit. + # We have already established btrfs as the fs type. p = Pool(name=pool_name, raid=root_raid, role='root', - compression=root_compression) + compression=root_compression, uuid=d.uuid) p.save() p.disk_set.add(dob) # update disk db object to reflect special root pool status @@ -349,15 +373,9 @@ def _update_disk_state(): dob.save() p.size = p.usage_bound() enable_quota(p) - # scan_disks() has already acquired our fs uuid so inherit. - # We have already established btrfs as the fs type. - p.uuid = d.uuid p.save() else: - # Likely unlabeled pool and no by-id name for system disk - # and given we rely on get_pool_info(), which takes by-id - # names, to label unlabelled pools we bail out for now with - # an error log message. + # Likely unlabeled pool & auto label failed - system disk. logger.error('Skipping system pool creation. Ensure the ' 'system disk has a unique serial.') # save our updated db disk object @@ -398,6 +416,30 @@ def _update_disk_state(): except Exception as e: logger.exception(e) do.smart_available = do.smart_enabled = False + else: # We have offline / detached Disk db entries. + # Update detached disks previously know to a pool i.e. missing. + # After a reboot device name is lost and replaced by 'missing' + # so we compare via btrfs devid stored prior to detached state. + # N.B. potential flag mechanism to denote required reboot if + # missing device has non existent dev entry rather than missing + # otherwise remove missing / detached fails with: + # "no missing devices found to remove". + # Suspect this will be fixed in future btrfs variants. + if do.pool is not None and do.pool.is_mounted: + mnt_pt = '{}{}'.format(settings.MNT_PT, do.pool.name) + devid_usage = get_devid_usage(mnt_pt) + if do.devid in devid_usage: + dev_info = devid_usage[do.devid] + do.size = dev_info.size + do.allocated = dev_info.allocated + else: + # Our device has likely been removed from this pool as + # it's devid no longer show up in it's associated pool. + # Reset all btrfs related elements for disk db object: + do.pool = None + do.btrfs_uuid = None + do.devid = 0 # db default and int flag for None. + do.allocated = 0 # No devid_usage = no allocation. do.save() ds = DiskInfoSerializer(Disk.objects.all().order_by('name'), many=True) return Response(ds.data) @@ -640,6 +682,8 @@ def _wipe(self, did, request): # either way (partitioned or not) we have just wiped any btrfs so we # universally remove the btrfs_uuid. disk.btrfs_uuid = None + disk.devid = 0 + disk.allocated = 0 disk.save() return Response(DiskInfoSerializer(disk).data) @@ -672,9 +716,11 @@ def _luks_format(self, did, request, passphrase): raise Exception(e_msg) luks_format_disk(disk_name, passphrase) disk.parted = isPartition # should be False by now. - # The following value may well be updated with a more informed truth + # The following values may well be updated with a more informed truth # from the next scan_disks() run via _update_disk_state() disk.btrfs_uuid = None + disk.devid = 0 + disk.allocated = 0 # Rather than await the next _update_disk_state() we populate our # LUKS container role. roles = {} @@ -715,17 +761,26 @@ def _btrfs_disk_import(self, did, request): p_info = get_pool_info(disk_name) # Create our initial pool object, default to no compression. po = Pool(name=p_info['label'], raid="unknown", - compression="no") + compression="no", uuid=p_info['uuid']) # need to save it so disk objects get updated properly in the for # loop below. po.save() + # p_info['disks'] = by_id name indexed dict with named tuple values for device in p_info['disks']: + # Database uses base dev names in by-id format: acquire via; disk_name, isPartition = \ self._reverse_role_filter_name(device, request) + # All bar system disk are stored in db as base byid name, + # a partition, if used, is then held in a redirect role. + # System's partition name is considered it's base name; but + # we don't have to import our system pool. do = Disk.objects.get(name=disk_name) do.pool = po - # update this disk's parted property + # Update this disk's parted, devid, and used properties. do.parted = isPartition + do.devid = p_info['disks'][device].devid + do.size = p_info['disks'][device].size + do.allocated = p_info['disks'][device].allocated if isPartition: # ensure a redirect role to reach this partition; ie: # "redirect": "virtio-serial-3-part2" @@ -750,7 +805,7 @@ def _btrfs_disk_import(self, did, request): import_snapshots(share) return Response(DiskInfoSerializer(disk).data) except Exception as e: - e_msg = ('Failed to import any pool on device id ({}). ' + e_msg = ('Failed to import any pool on device db id ({}). ' 'Error: ({}).').format(did, e.__str__()) handle_exception(Exception(e_msg), request) diff --git a/src/rockstor/storageadmin/views/pool.py b/src/rockstor/storageadmin/views/pool.py index 33844c549..3948a1e55 100644 --- a/src/rockstor/storageadmin/views/pool.py +++ b/src/rockstor/storageadmin/views/pool.py @@ -26,9 +26,10 @@ from django.db import transaction from storageadmin.serializers import PoolInfoSerializer from storageadmin.models import (Disk, Pool, Share, PoolBalance) -from fs.btrfs import (add_pool, pool_usage, resize_pool, umount_root, +from fs.btrfs import (add_pool, pool_usage, resize_pool_cmd, umount_root, btrfs_uuid, mount_root, start_balance, usage_bound, - remove_share, enable_quota, disable_quota, rescan_quotas) + remove_share, enable_quota, disable_quota, rescan_quotas, + start_resize_pool) from system.osi import remount, trigger_udev_update from storageadmin.util import handle_exception from django.conf import settings @@ -283,11 +284,44 @@ def _balance_start(self, pool, force=False, convert=None): for t in Task.objects.all(): if (pickle.loads(t.args)[0] == mnt_pt): tid = t.uuid - time.sleep(0.2) + time.sleep(0.2) # 200 milliseconds count += 1 logger.debug('balance tid = ({}).'.format(tid)) return tid + def _resize_pool_start(self, pool, dnames, add=True): + """ + Async initiator for resize_pool(pool, dnames, add=False) as when a + device is deleted it initiates a btrfs internal balance which is not + accessible to 'btrfs balance status' but is a balance nevertheless. + Based on _balance_start() + :param pool: Pool object. + :param dnames: list of by-id device names without paths. + :param add: True if adding dnames, False if deleting (removing) dnames. + :return: 0 if + """ + tid = 0 + cmd = resize_pool_cmd(pool, dnames, add) + if cmd is None: + return tid + logger.info('Beginning device resize on pool ({}). ' + 'Changed member devices:({}).'.format(pool.name, dnames)) + if add: + # Mostly instantaneous so avoid complexity/overhead of django ztask + start_resize_pool(cmd) + return tid + # Device delete initiates long running internal balance: start async. + start_resize_pool.async(cmd) + # Try to find django-ztask id for (25*0.2) 5 seconds via cmd args match + count = 0 + while tid == 0 and count < 25: + for t in Task.objects.all(): + if pickle.loads(t.args)[0] == cmd: + tid = t.uuid + time.sleep(0.2) # 200 milliseconds + count += 1 + logger.debug('Pool resize tid = ({}).'.format(tid)) + return tid class PoolListView(PoolMixin, rfc.GenericView): def get_queryset(self, *args, **kwargs): @@ -490,13 +524,14 @@ def put(self, request, pid, command): 'during a balance process.').format(pool.name) handle_exception(Exception(e_msg), request) - # TODO: run resize_pool() as async task like start_balance() - resize_pool(pool, dnames) # None if no action + # _resize_pool_start() add dev mode is quick so no async or tid + self._resize_pool_start(pool, dnames) force = False # During dev add we also offer raid level change, if selected # blanket apply '-f' to allow for reducing metadata integrity. if new_raid != pool.raid: force = True + # Django-ztask initialization as balance is long running. tid = self._balance_start(pool, force=force, convert=new_raid) ps = PoolBalance(pool=pool, tid=tid) ps.save() @@ -563,7 +598,7 @@ def put(self, request, pid, command): usage = pool_usage('/%s/%s' % (settings.MNT_PT, pool.name)) size_cut = 0 for d in disks: - size_cut += d.size + size_cut += d.allocated if size_cut >= (pool.size - usage): e_msg = ('Removing disks ({}) may shrink the pool by ' '{} KB, which is greater than available free ' @@ -571,21 +606,21 @@ def put(self, request, pid, command): 'not supported.').format(dnames, size_cut, usage) handle_exception(Exception(e_msg), request) - # TODO: run resize_pool() as async task like start_balance(), - # particularly important on device delete as it initiates an - # internal volume balance which cannot be monitored by: - # btrfs balance status. - # See https://github.com/rockstor/rockstor-core/issues/1722 - # Hence we need also to add a 'DIY' status / percentage - # reporting method. - resize_pool(pool, dnames, add=False) # None if no action - # Unlike resize_pool() with add=True a delete has an implicit - # balance where the deleted disks contents are re-distributed - # across the remaining disks. + # Unlike resize_pool_start() with add=True a remove has an + # implicit balance where the removed disks contents are + # re-distributed across the remaining pool members. + # This internal balance cannot currently be monitored by the + # usual 'btrfs balance status /mnt_pt' command. So we have to + # use our own mechanism to assess it's status. + # Django-ztask initialization: + tid = self._resize_pool_start(pool, dnames, add=False) + ps = PoolBalance(pool=pool, tid=tid, internal=True) + ps.save() - for d in disks: - d.pool = None - d.save() + # Setting disk.pool = None for all removed members is redundant + # as our next disk scan will re-find them until such time as + # our async task, and it's associated dev remove, has completed + # it's internal balance. This can take hours. else: e_msg = 'Command ({}) is not supported.'.format(command) diff --git a/src/rockstor/storageadmin/views/pool_balance.py b/src/rockstor/storageadmin/views/pool_balance.py index 49639d2ac..0599aeba1 100644 --- a/src/rockstor/storageadmin/views/pool_balance.py +++ b/src/rockstor/storageadmin/views/pool_balance.py @@ -23,7 +23,7 @@ from storageadmin.serializers import PoolBalanceSerializer from storageadmin.models import (Pool, PoolBalance) import rest_framework_custom as rfc -from fs.btrfs import balance_status +from fs.btrfs import balance_status, balance_status_internal from pool import PoolMixin import logging @@ -69,7 +69,10 @@ def _balance_status(pool): return ps # Get the current status of balance on this pool, irrespective of # a running balance task, ie command line intervention. - cur_status = balance_status(pool) + if ps.internal: + cur_status = balance_status_internal(pool) + else: + cur_status = balance_status(pool) previous_status = ps.status # TODO: future "Balance Cancel" button should call us to have these # TODO: values updated in the db table ready for display later. @@ -81,6 +84,13 @@ def _balance_status(pool): 'cancelled at %s%% complete' % ps.percent_done # and retain prior percent finished value cur_status['percent_done'] = ps.percent_done + if previous_status == 'failed' \ + and cur_status['status'] == 'finished': + # override current status as 'failed' + cur_status['status'] = 'failed' + # and retain prior percent finished value + cur_status['percent_done'] = ps.percent_done + if previous_status != 'finished' and previous_status != 'cancelled': # update the last pool balance status with current status info. PoolBalance.objects.filter(id=ps.id).update(**cur_status) diff --git a/src/rockstor/system/luks.py b/src/rockstor/system/luks.py index f25f18e4e..b9dd77be5 100644 --- a/src/rockstor/system/luks.py +++ b/src/rockstor/system/luks.py @@ -53,7 +53,7 @@ def get_open_luks_volume_status(mapped_device_name, byid_name_map): /dev/disk/by-id/dm-name- luks-3efb3830-fee1-4a9e-a5c6-ea456bfc269e is active and is in use. :param mapped_device_name: any mapped device name accepted by cryptsetup, - ie starting with "/dev/mapper/" + ie starting with "/dev/mapper/", path included or not, output unaffected. :return: dictionary of the stated commands output or {} upon a non zero return code from command execution. """ diff --git a/src/rockstor/system/osi.py b/src/rockstor/system/osi.py index 89c753ca8..bcf9e01c2 100644 --- a/src/rockstor/system/osi.py +++ b/src/rockstor/system/osi.py @@ -135,8 +135,8 @@ def scan_disks(min_size, test_mode=False): :param test_mode: Used by unit tests for deterministic 'fake-serial-' mode. :return: List containing drives of interest """ - base_root_disk = root_disk() - cmd = [LSBLK, '-P', '-o', + base_root_disk = root_disk() # /dev/sda if /dev/sda3, or md126 if md126p2 + cmd = [LSBLK, '-P', '-p', '-o', 'NAME,MODEL,SERIAL,SIZE,TRAN,VENDOR,HCTL,TYPE,FSTYPE,LABEL,UUID'] o, e, rc = run_command(cmd) dnames = {} # Working dictionary of devices. @@ -224,7 +224,7 @@ def scan_disks(min_size, test_mode=False): continue # ----- Now we are done with easy exclusions we begin classification. # If md device populate unused MODEL with basic member/raid summary. - if (re.match('md', dmap['NAME']) is not None): + if (re.match('/dev/md', dmap['NAME']) is not None): # cheap way to display our member drives dmap['MODEL'] = get_md_members(dmap['NAME']) # ------------ Start more complex classification ------------- @@ -375,7 +375,7 @@ def scan_disks(min_size, test_mode=False): # a btrfs file system # Regex to identify a partition on the base_root_disk. # Root on 'sda3' gives base_root_disk 'sda'. - if re.match('sd|vd', dmap['NAME']) is not None: + if re.match('/dev/sd|/dev/vd', dmap['NAME']) is not None: # eg 'sda' or 'vda' with >= one additional digit, part_regex = base_root_disk + '\d+' else: @@ -823,6 +823,31 @@ def mount_status(mnt_pt, return_boolean=False): return 'unmounted' +def dev_mount_point(dev_temp_name): + """ + Parses /proc/mounts to return the first associated mount point for a given + device temp name (ie /dev/sda). + Note this is trivially different from mount_status() but intended initially + for use by set_pool_label. + :param dev_temp_name: /dev/sda3 or /dev/bcache0, or /dev/mapper/luks-... + :return: None if note device match found or first associated mount point. + """ + with open('/proc/mounts') as pfo: + for each_line in pfo.readlines(): + line_fields = each_line.split() + if len(line_fields) < 4: + # Avoid index issues as we expect >= 4 columns. + continue + if line_fields[0] in EXCLUDED_MOUNT_DEVS: + # Skip excluded/special mount devices ie sysfs, proc, etc. + continue + if line_fields[0] == dev_temp_name: + logger.debug('dev_mount_point returning {}'.format(line_fields[1])) + return line_fields[1] + logger.debug('dev_mount_point() returning None') + return None + + def remount(mnt_pt, mnt_options): if (is_mounted(mnt_pt)): run_command([MOUNT, '-o', 'remount,%s' % mnt_options, mnt_pt]) @@ -902,9 +927,10 @@ def root_disk(): the returned value is sdc The assumption with non md devices is that the partition number will be a single character. - :return: sdX type device name (without path) where root is mounted. + :return: /dev/sdX type device name (with path) where root is mounted. """ # TODO: Consider 'lsblk -no pkname devname' rather than parse and strip. + # -no pkname returns blank line with /dev/mapper/luks but no partitions. # -n = no headings, -o specify output (pkname = Parent Kernel Name) with open('/proc/mounts') as fo: for line in fo.readlines(): @@ -915,11 +941,11 @@ def root_disk(): # Our root is on a mapped open LUKS container so we need # not resolve the symlink, ie /dev/dm-0, as we loose info # and lsblk's name output also uses the luks- name. - # So we return the name minus it's /dev/mapper/ component + # So we return the name component # as there are no partitions within these devices so it is # it's own base device. N.B. we do not resolve to the # parent device hosting the LUKS container itself. - return fields[0][12:] + return fields[0] # resolve symbolic links to their targets. disk = os.path.realpath(fields[0]) if (re.match('/dev/md', disk) is not None): @@ -934,7 +960,7 @@ def root_disk(): # numbers after "md" end. N.B. the following will also # work if root is not in a partition ie on md126 directly. end = re.search('\d+', disk).end() - return disk[5:end] + return disk[:end] if (re.match('/dev/nvme', disk) is not None): # We have an nvme device. These have the following naming # conventions. @@ -946,13 +972,13 @@ def root_disk(): # device itself as with the /dev/md parsing just in case, # so look for the end of the base device name via 'n1'. end = re.search('n1', disk).end() - return disk[5:end] - # catch all that assumes we have eg /dev/sda3 and want "sda" - # so start from 6th char and remove the last char - # /dev/sda3 = sda + return disk[:end] + # catch all that assumes we have eg /dev/sda3 and want /dev/sda + # remove the last char + # /dev/sda3 = /dev/sda # TODO: consider changing to same method as in md devs above # TODO: to cope with more than one numeric in name. - return disk[5:-1] + return disk[:-1] msg = ('root filesystem is not BTRFS. During Rockstor installation, ' 'you must select BTRFS instead of LVM and other options for ' 'root filesystem. Please re-install Rockstor properly.') @@ -962,7 +988,7 @@ def root_disk(): def get_md_members(device_name, test=None): """ Returns the md members from a given device, if the given device is not an - md device or the udevadm info command returns a non 0 (error) then the an + md device or the udevadm info command returns a non 0 (error) then an empty string is returned. Example lines to parse from udevadmin:- E: MD_DEVICE_sda_DEV=/dev/sda @@ -972,7 +998,7 @@ def get_md_members(device_name, test=None): Based on the get_disk_serial function. N.B. may be deprecated on scan_disks move to udevadmin, or integrated. Could consider parsing "mdadm --detail /dev/md1" instead - :param device_name: eg md126 or md0p2 + :param device_name: eg /dev/md126 or /dev/md0p2 :param test: if test is not None then it's contents is used in lieu of udevadm output. :return: String of all members listed in udevadm info --name=device_name @@ -980,7 +1006,7 @@ def get_md_members(device_name, test=None): """ line_fields = [] # if non md device then return empty string - if re.match('md', device_name) is None: + if re.match('/dev/md', device_name) is None: return '' members_string = '' if test is None: @@ -1039,7 +1065,7 @@ def get_disk_serial(device_name, device_type=None, test=None): --------- Additional personality added for md devices ie md0p1 or md126, these devices have no serial so we search for their MD_UUID and use that instead. - :param device_name: eg sda as per lsblk output used in scan_disks() + :param device_name: eg /dev/sda as per lsblk output used in scan_disks() :param device_type: the lsblk TYPE for the given device eg: disk, crypt. The equivalent to the output of lsblk -n -o TYPE device_name. Defaults to None as an indication that the caller cannot provide this info. @@ -1054,7 +1080,6 @@ def get_disk_serial(device_name, device_type=None, test=None): # type indicates this then add the '/dev/mapper' path to device_name # Set search string / flag for dm personality if need be. if device_type == 'crypt': - device_name = '/dev/mapper/%s' % device_name # Assuming device mapped (DM) so without it's own serial. uuid_search_string = 'DM_UUID' # Note that we can't use "cryptsetup luksUUID " as this is for @@ -1064,7 +1089,7 @@ def get_disk_serial(device_name, device_type=None, test=None): # change that devices serial which in turn makes it appear as a # different device to Rockstor. # Set search string / flag for md personality if need be. - if re.match('md', device_name) is not None: + if re.match('/dev/md', device_name) is not None: uuid_search_string = 'MD_UUID' if test is None: out, err, rc = run_command([UDEVADM, 'info', '--name=' + device_name], @@ -1277,10 +1302,11 @@ def get_bcache_device_type(device): Cache devices have a "cache_replacement_policy" The passed device will have already been identified as having: lsblk FSTYPE=bcache - :param device: as presented by lsblk output ie sdX type with no path + :param device: as presented by lsblk output ie /dev/sdX type with path :return: "bdev" for "backing device" or "cdev" for "cache device" or None ie neither indicator is found. """ + device = device.split('/')[-1] # strip off the path sys_path = ('/sys/block/%s/bcache/' % device) if os.path.isfile(sys_path + 'label'): return "bdev" @@ -1557,7 +1583,7 @@ def get_dev_byid_name(device_name, remove_path=False): N.B. As the subsystem of the device is embedded in the by-id name a drive's by-id path will change if for example it is plugged in via usb rather than ata subsystem. - :param device_name: eg sda but can also be /dev/sda or even the by-id name + :param device_name: eg /dev/sda or even the by-id name (with path) but only if the full path is specified with the by-id type name. :param remove_path: flag request to strip the path from the returned device name, if an error occurred or no by-id type name was found then the path @@ -1576,12 +1602,7 @@ def get_dev_byid_name(device_name, remove_path=False): byid_name = '' # Should never be returned prior to reassignment. longest_byid_name_length = 0 devlinks = [] # Doubles as a flag for DEVLINKS line found. - # Caveats for mapped devices that require paths for udevadm to work - # ie openLUKS containers are named eg luks- but are not found by - # udevadmin via --name unless a /dev/mapper path is provided. - if re.match('luks-', str(device_name)) is not None: - device_name = '/dev/mapper/%s' % device_name - # Other special device name considerations can go here. + # Special device name considerations / pre-processing can go here. cmd = [UDEVADM, 'info', '--query=property', '--name', str(device_name)] out, err, rc = run_command(cmd, throw=False) if len(out) > 0 and rc == 0: @@ -1684,6 +1705,33 @@ def get_byid_name_map(): return byid_name_map +def get_device_mapper_map(): + """ + Simple wrapper around 'ls -lr /dev/mapper' akin to get_byid_name_map() but + without the assumption of multiple entries and with differing field count + expectations. + :return: dictionary indexed (keyed) by 'dm-0' type names with associated + /dev/mapper names as the values (path included), or an empty dictionary if + a non zero return code was encountered by run_command or no /dev/mapper + names found. + """ + device_mapper_map = {} + out, err, rc = run_command([LS, '-lr', '/dev/mapper'], throw=True) + if rc == 0 and len(out) > 3: # len 3 is only control char dev listed. + for each_line in out: + if each_line == '': + continue + # Split the line by spaces and '/' chars + line_fields = each_line.replace('/', ' ').split() + # Grab every dm-0 type name from the last field in the line and add + # it as a dictionary key with it's value as the mapped dir entry. + # Our full path is added as a convenience to our caller. + # {'dm-0': '/dev/mapper/luks-dd6589a6-14aa-4a5a-bcea-fe72e2dec333'} + if len(line_fields) == 12: + device_mapper_map[line_fields[-1]] = line_fields[-4] + return device_mapper_map + + def get_device_path(by_id): """ Return full path for given device id. @@ -1820,7 +1868,7 @@ def get_devname_old(device_name): def get_devname(device_name, addPath=False): """Intended as a light and quicker way to retrieve a device name with or - without path (default) from any legal udevadm --name parameter + without (default) path from any legal udevadm --name parameter Simple wrapper around a call to: udevadm info --query=name device_name Works with device_name of eg sda /dev/sda /dev/disk/by-id/ and /dev/disk/ @@ -1842,7 +1890,7 @@ def get_devname(device_name, addPath=False): if len(fields) == 1: # we have a single word output so return it with or without path if addPath: - return '/dev/%s' % fields[0] + return '/dev/{}'.format(fields[0]) # return the word (device name ie sda) without added /dev/ return fields[0] # a non one word reply was received on the first line from udevadm or diff --git a/src/rockstor/system/tests/test_osi.py b/src/rockstor/system/tests/test_osi.py index 8e135fedb..6cff4a351 100644 --- a/src/rockstor/system/tests/test_osi.py +++ b/src/rockstor/system/tests/test_osi.py @@ -43,10 +43,10 @@ def setUp(self): self.patch_os_path_isfile = patch('os.path.isfile') self.mock_os_path_isfile = self.patch_os_path_isfile.start() - # root_disk() default mock - return sda for sda3 '/' from /proc/mounts + # root_disk() default mock - return /dev/sda for /dev/sda3 '/' self.patch_root_disk = patch('system.osi.root_disk') self.mock_root_disk = self.patch_root_disk.start() - self.mock_root_disk.return_value = 'sda' + self.mock_root_disk.return_value = '/dev/sda' def tearDown(self): patch.stopall() @@ -201,7 +201,10 @@ def test_get_dev_byid_name(self): expected_result.append( ('/dev/disk/by-id/scsi-SATA_QEMU_HARDDISK_QM00009', True)) # Query on an openLUKS container (backed by bcache): - dev_name.append('luks-a47f4950-3296-4504-b9a4-2dc75681a6ad') + # N.B. legacy versions of get_dev_byid_name() would auto add + # /dev/mapper if dev name matched 'luks-' this was later removed in + # favour of generating the full path in scan_disks(). + dev_name.append('/dev/mapper/luks-a47f4950-3296-4504-b9a4-2dc75681a6ad') remove_path.append(True) out.append([ 'DEVLINKS=/dev/disk/by-id/dm-name-luks-a47f4950-3296-4504-b9a4-2dc75681a6ad /dev/disk/by-id/dm-uuid-CRYPT-LUKS1-a47f495032964504b9a42dc75681a6ad-luks-a47f4950-3296-4504-b9a4-2dc75681a6ad /dev/disk/by-label/luks-pool-on-bcache /dev/disk/by-uuid/8ad02be6-fc5f-4342-bdd2-f992e7792a5b /dev/mapper/luks-a47f4950-3296-4504-b9a4-2dc75681a6ad', # noqa E501 @@ -379,35 +382,35 @@ def test_scan_disks_luks_on_bcache(self): # Moc output for run_command with: # lsblk -P -o NAME,MODEL,SERIAL,SIZE,TRAN,VENDOR,HCTL,TYPE,FSTYPE,LABEL,UUID # noqa E501 out = [[ - 'NAME="sdd" MODEL="QEMU HARDDISK " SERIAL="bcache-cdev" SIZE="2G" TRAN="sata" VENDOR="ATA " HCTL="3:0:0:0" TYPE="disk" FSTYPE="bcache" LABEL="" UUID="6efd5476-77a9-4f57-97a5-fa1a37d4338b"', # noqa E501 - 'NAME="bcache0" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="disk" FSTYPE="crypto_LUKS" LABEL="" UUID="3efb3830-fee1-4a9e-a5c6-ea456bfc269e"', # noqa E501 - 'NAME="luks-3efb3830-fee1-4a9e-a5c6-ea456bfc269e" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="crypt" FSTYPE="btrfs" LABEL="pool-on-mixed-luks" UUID="1fdd4b41-fdd0-40c4-8ae6-7d6309b09ded"', # noqa E501 - 'NAME="bcache16" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="disk" FSTYPE="crypto_LUKS" LABEL="" UUID="a47f4950-3296-4504-b9a4-2dc75681a6ad"', # noqa E501 - 'NAME="luks-a47f4950-3296-4504-b9a4-2dc75681a6ad" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="crypt" FSTYPE="btrfs" LABEL="pool-on-mixed-luks" UUID="1fdd4b41-fdd0-40c4-8ae6-7d6309b09ded"', # noqa E501 - 'NAME="sdb" MODEL="QEMU HARDDISK " SERIAL="bcache-bdev-1" SIZE="2G" TRAN="sata" VENDOR="ATA " HCTL="1:0:0:0" TYPE="disk" FSTYPE="bcache" LABEL="" UUID="c9ed805f-b141-4ce9-80c7-9f9e1f71195d"', # noqa E501 - 'NAME="bcache0" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="disk" FSTYPE="crypto_LUKS" LABEL="" UUID="3efb3830-fee1-4a9e-a5c6-ea456bfc269e"', # noqa E501 - 'NAME="luks-3efb3830-fee1-4a9e-a5c6-ea456bfc269e" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="crypt" FSTYPE="btrfs" LABEL="pool-on-mixed-luks" UUID="1fdd4b41-fdd0-40c4-8ae6-7d6309b09ded"', # noqa E501 - 'NAME="vdb" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="0x1af4" HCTL="" TYPE="disk" FSTYPE="crypto_LUKS" LABEL="" UUID="41cd2e3c-3bd6-49fc-9f42-20e368a66efc"', # noqa E501 - 'NAME="luks-41cd2e3c-3bd6-49fc-9f42-20e368a66efc" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="crypt" FSTYPE="btrfs" LABEL="pool-on-mixed-luks" UUID="1fdd4b41-fdd0-40c4-8ae6-7d6309b09ded"', # noqa E501 - 'NAME="sr0" MODEL="QEMU DVD-ROM " SERIAL="QM00001" SIZE="1024M" TRAN="ata" VENDOR="QEMU " HCTL="6:0:0:0" TYPE="rom" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="sdc" MODEL="QEMU HARDDISK " SERIAL="bcache-bdev-2" SIZE="2G" TRAN="sata" VENDOR="ATA " HCTL="2:0:0:0" TYPE="disk" FSTYPE="bcache" LABEL="" UUID="06754c95-4f78-4ffb-a243-5c85144d1833"', # noqa E501 - 'NAME="bcache16" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="disk" FSTYPE="crypto_LUKS" LABEL="" UUID="a47f4950-3296-4504-b9a4-2dc75681a6ad"', # noqa E501 - 'NAME="luks-a47f4950-3296-4504-b9a4-2dc75681a6ad" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="crypt" FSTYPE="btrfs" LABEL="pool-on-mixed-luks" UUID="1fdd4b41-fdd0-40c4-8ae6-7d6309b09ded"', # noqa E501 - 'NAME="sda" MODEL="QEMU HARDDISK " SERIAL="sys-drive-serial-num" SIZE="8G" TRAN="sata" VENDOR="ATA " HCTL="0:0:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="sda2" MODEL="" SERIAL="" SIZE="820M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="swap" LABEL="" UUID="c25eec5f-d4bd-4670-b756-e8b687562f6e"', # noqa E501 - 'NAME="sda3" MODEL="" SERIAL="" SIZE="6.7G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="btrfs" LABEL="rockstor_rockstor" UUID="a98f88c2-2031-4bd3-9124-2f9d8a77987c"', # noqa E501 - 'NAME="sda1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="ext4" LABEL="" UUID="6b8e342c-6cd6-40e8-a134-db302fad3f20"', # noqa E501 - 'NAME="vda" MODEL="" SERIAL="" SIZE="3G" TRAN="" VENDOR="0x1af4" HCTL="" TYPE="disk" FSTYPE="btrfs" LABEL="rock-pool" UUID="d7e5987d-9428-4b4a-9abb-f3d564e4c467"', # noqa E501 + 'NAME="/dev/sdd" MODEL="QEMU HARDDISK " SERIAL="bcache-cdev" SIZE="2G" TRAN="sata" VENDOR="ATA " HCTL="3:0:0:0" TYPE="disk" FSTYPE="bcache" LABEL="" UUID="6efd5476-77a9-4f57-97a5-fa1a37d4338b"', # noqa E501 + 'NAME="/dev/bcache0" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="disk" FSTYPE="crypto_LUKS" LABEL="" UUID="3efb3830-fee1-4a9e-a5c6-ea456bfc269e"', # noqa E501 + 'NAME="/dev/mapper/luks-3efb3830-fee1-4a9e-a5c6-ea456bfc269e" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="crypt" FSTYPE="btrfs" LABEL="pool-on-mixed-luks" UUID="1fdd4b41-fdd0-40c4-8ae6-7d6309b09ded"', # noqa E501 + 'NAME="/dev/bcache16" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="disk" FSTYPE="crypto_LUKS" LABEL="" UUID="a47f4950-3296-4504-b9a4-2dc75681a6ad"', # noqa E501 + 'NAME="/dev/mapper/luks-a47f4950-3296-4504-b9a4-2dc75681a6ad" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="crypt" FSTYPE="btrfs" LABEL="pool-on-mixed-luks" UUID="1fdd4b41-fdd0-40c4-8ae6-7d6309b09ded"', # noqa E501 + 'NAME="/dev/sdb" MODEL="QEMU HARDDISK " SERIAL="bcache-bdev-1" SIZE="2G" TRAN="sata" VENDOR="ATA " HCTL="1:0:0:0" TYPE="disk" FSTYPE="bcache" LABEL="" UUID="c9ed805f-b141-4ce9-80c7-9f9e1f71195d"', # noqa E501 + 'NAME="/dev/bcache0" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="disk" FSTYPE="crypto_LUKS" LABEL="" UUID="3efb3830-fee1-4a9e-a5c6-ea456bfc269e"', # noqa E501 + 'NAME="/dev/mapper/luks-3efb3830-fee1-4a9e-a5c6-ea456bfc269e" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="crypt" FSTYPE="btrfs" LABEL="pool-on-mixed-luks" UUID="1fdd4b41-fdd0-40c4-8ae6-7d6309b09ded"', # noqa E501 + 'NAME="/dev/vdb" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="0x1af4" HCTL="" TYPE="disk" FSTYPE="crypto_LUKS" LABEL="" UUID="41cd2e3c-3bd6-49fc-9f42-20e368a66efc"', # noqa E501 + 'NAME="/dev/mapper/luks-41cd2e3c-3bd6-49fc-9f42-20e368a66efc" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="crypt" FSTYPE="btrfs" LABEL="pool-on-mixed-luks" UUID="1fdd4b41-fdd0-40c4-8ae6-7d6309b09ded"', # noqa E501 + 'NAME="/dev/sr0" MODEL="QEMU DVD-ROM " SERIAL="QM00001" SIZE="1024M" TRAN="ata" VENDOR="QEMU " HCTL="6:0:0:0" TYPE="rom" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/sdc" MODEL="QEMU HARDDISK " SERIAL="bcache-bdev-2" SIZE="2G" TRAN="sata" VENDOR="ATA " HCTL="2:0:0:0" TYPE="disk" FSTYPE="bcache" LABEL="" UUID="06754c95-4f78-4ffb-a243-5c85144d1833"', # noqa E501 + 'NAME="/dev/bcache16" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="disk" FSTYPE="crypto_LUKS" LABEL="" UUID="a47f4950-3296-4504-b9a4-2dc75681a6ad"', # noqa E501 + 'NAME="/dev/mapper/luks-a47f4950-3296-4504-b9a4-2dc75681a6ad" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="crypt" FSTYPE="btrfs" LABEL="pool-on-mixed-luks" UUID="1fdd4b41-fdd0-40c4-8ae6-7d6309b09ded"', # noqa E501 + 'NAME="/dev/sda" MODEL="QEMU HARDDISK " SERIAL="sys-drive-serial-num" SIZE="8G" TRAN="sata" VENDOR="ATA " HCTL="0:0:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/sda2" MODEL="" SERIAL="" SIZE="820M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="swap" LABEL="" UUID="c25eec5f-d4bd-4670-b756-e8b687562f6e"', # noqa E501 + 'NAME="/dev/sda3" MODEL="" SERIAL="" SIZE="6.7G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="btrfs" LABEL="rockstor_rockstor" UUID="a98f88c2-2031-4bd3-9124-2f9d8a77987c"', # noqa E501 + 'NAME="/dev/sda1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="ext4" LABEL="" UUID="6b8e342c-6cd6-40e8-a134-db302fad3f20"', # noqa E501 + 'NAME="/dev/vda" MODEL="" SERIAL="" SIZE="3G" TRAN="" VENDOR="0x1af4" HCTL="" TYPE="disk" FSTYPE="btrfs" LABEL="rock-pool" UUID="d7e5987d-9428-4b4a-9abb-f3d564e4c467"', # noqa E501 '']] err = [['']] rc = [0] expected_result = [[ - Disk(name='vda', model=None, serial='serial-6', size=3145728, + Disk(name='/dev/vda', model=None, serial='serial-6', size=3145728, transport=None, vendor='0x1af4', hctl=None, type='disk', fstype='btrfs', label='rock-pool', uuid='d7e5987d-9428-4b4a-9abb-f3d564e4c467', parted=False, root=False, partitions={}), - Disk(name='bcache0', model=None, + Disk(name='/dev/bcache0', model=None, serial='bcache-c9ed805f-b141-4ce9-80c7-9f9e1f71195d', size=2097152, transport=None, vendor=None, hctl=None, @@ -416,18 +419,18 @@ def test_scan_disks_luks_on_bcache(self): uuid='3efb3830-fee1-4a9e-a5c6-ea456bfc269e', parted=False, root=False, partitions={}), - Disk(name='luks-a47f4950-3296-4504-b9a4-2dc75681a6ad', model=None, + Disk(name='/dev/mapper/luks-a47f4950-3296-4504-b9a4-2dc75681a6ad', model=None, # noqa E501 serial='CRYPT-LUKS1-a47f495032964504b9a42dc75681a6ad-luks-a47f4950-3296-4504-b9a4-2dc75681a6ad', # noqa E501 size=2097152, transport=None, vendor=None, hctl=None, type='crypt', fstype='btrfs', label='pool-on-mixed-luks', uuid='1fdd4b41-fdd0-40c4-8ae6-7d6309b09ded', parted=False, root=False, partitions={}), - Disk(name='sdd', model='QEMU HARDDISK', serial='bcache-cdev', + Disk(name='/dev/sdd', model='QEMU HARDDISK', serial='bcache-cdev', size=2097152, transport='sata', vendor='ATA', hctl='3:0:0:0', type='disk', fstype='bcachecdev', label=None, uuid='6efd5476-77a9-4f57-97a5-fa1a37d4338b', parted=False, root=False, partitions={}), - Disk(name='bcache16', model=None, + Disk(name='/dev/bcache16', model=None, serial='bcache-06754c95-4f78-4ffb-a243-5c85144d1833', size=2097152, transport=None, vendor=None, hctl=None, @@ -436,34 +439,34 @@ def test_scan_disks_luks_on_bcache(self): uuid='a47f4950-3296-4504-b9a4-2dc75681a6ad', parted=False, root=False, partitions={}), - Disk(name='luks-3efb3830-fee1-4a9e-a5c6-ea456bfc269e', model=None, + Disk(name='/dev/mapper/luks-3efb3830-fee1-4a9e-a5c6-ea456bfc269e', model=None, # noqa E501 serial='CRYPT-LUKS1-3efb3830fee14a9ea5c6ea456bfc269e-luks-3efb3830-fee1-4a9e-a5c6-ea456bfc269e', # noqa E501 size=2097152, transport=None, vendor=None, hctl=None, type='crypt', fstype='btrfs', label='pool-on-mixed-luks', uuid='1fdd4b41-fdd0-40c4-8ae6-7d6309b09ded', parted=False, root=False, partitions={}), - Disk(name='vdb', model=None, serial='serial-5', size=2097152, + Disk(name='/dev/vdb', model=None, serial='serial-5', size=2097152, transport=None, vendor='0x1af4', hctl=None, type='disk', fstype='crypto_LUKS', label=None, uuid='41cd2e3c-3bd6-49fc-9f42-20e368a66efc', parted=False, root=False, partitions={}), - Disk(name='sda3', model='QEMU HARDDISK', + Disk(name='/dev/sda3', model='QEMU HARDDISK', serial='sys-drive-serial-num', size=7025459, transport='sata', vendor='ATA', hctl='0:0:0:0', type='part', fstype='btrfs', label='rockstor_rockstor', uuid='a98f88c2-2031-4bd3-9124-2f9d8a77987c', parted=True, root=True, partitions={}), - Disk(name='sdb', model='QEMU HARDDISK', serial='bcache-bdev-1', + Disk(name='/dev/sdb', model='QEMU HARDDISK', serial='bcache-bdev-1', # noqa E501 size=2097152, transport='sata', vendor='ATA', hctl='1:0:0:0', type='disk', fstype='bcache', label=None, uuid='c9ed805f-b141-4ce9-80c7-9f9e1f71195d', parted=False, root=False, partitions={}), - Disk(name='sdc', model='QEMU HARDDISK', serial='bcache-bdev-2', + Disk(name='/dev/sdc', model='QEMU HARDDISK', serial='bcache-bdev-2', # noqa E501 size=2097152, transport='sata', vendor='ATA', hctl='2:0:0:0', type='disk', fstype='bcache', label=None, uuid='06754c95-4f78-4ffb-a243-5c85144d1833', parted=False, root=False, partitions={}), - Disk(name='luks-41cd2e3c-3bd6-49fc-9f42-20e368a66efc', model=None, + Disk(name='/dev/mapper/luks-41cd2e3c-3bd6-49fc-9f42-20e368a66efc', model=None, # noqa E501 serial='CRYPT-LUKS1-41cd2e3c3bd649fc9f4220e368a66efc-luks-41cd2e3c-3bd6-49fc-9f42-20e368a66efc', # noqa E501 size=2097152, transport=None, vendor=None, hctl=None, type='crypt', fstype='btrfs', label='pool-on-mixed-luks', @@ -479,13 +482,13 @@ def dyn_disk_serial_return(*args, **kwargs): # Entries only requred here if lsblk test data has no serial info: # eg for bcache, LUKS, mdraid, and virtio type devices. s_map = { - 'bcache0': 'bcache-c9ed805f-b141-4ce9-80c7-9f9e1f71195d', - 'bcache16': 'bcache-06754c95-4f78-4ffb-a243-5c85144d1833', - 'luks-3efb3830-fee1-4a9e-a5c6-ea456bfc269e': 'CRYPT-LUKS1-3efb3830fee14a9ea5c6ea456bfc269e-luks-3efb3830-fee1-4a9e-a5c6-ea456bfc269e', # noqa E501 - 'luks-a47f4950-3296-4504-b9a4-2dc75681a6ad': 'CRYPT-LUKS1-a47f495032964504b9a42dc75681a6ad-luks-a47f4950-3296-4504-b9a4-2dc75681a6ad', # noqa E501 - 'luks-41cd2e3c-3bd6-49fc-9f42-20e368a66efc': 'CRYPT-LUKS1-41cd2e3c3bd649fc9f4220e368a66efc-luks-41cd2e3c-3bd6-49fc-9f42-20e368a66efc', # noqa E501 - 'vdb': 'serial-5', - 'vda': 'serial-6' + '/dev/bcache0': 'bcache-c9ed805f-b141-4ce9-80c7-9f9e1f71195d', + '/dev/bcache16': 'bcache-06754c95-4f78-4ffb-a243-5c85144d1833', + '/dev/mapper/luks-3efb3830-fee1-4a9e-a5c6-ea456bfc269e': 'CRYPT-LUKS1-3efb3830fee14a9ea5c6ea456bfc269e-luks-3efb3830-fee1-4a9e-a5c6-ea456bfc269e', # noqa E501 + '/dev/mapper/luks-a47f4950-3296-4504-b9a4-2dc75681a6ad': 'CRYPT-LUKS1-a47f495032964504b9a42dc75681a6ad-luks-a47f4950-3296-4504-b9a4-2dc75681a6ad', # noqa E501 + '/dev/mapper/luks-41cd2e3c-3bd6-49fc-9f42-20e368a66efc': 'CRYPT-LUKS1-41cd2e3c3bd649fc9f4220e368a66efc-luks-41cd2e3c-3bd6-49fc-9f42-20e368a66efc', # noqa E501 + '/dev/vdb': 'serial-5', + '/dev/vda': 'serial-6' } # First argument in get_disk_serial() is device_name, key off this # for our dynamic mock return from s_map (serial map). @@ -504,9 +507,9 @@ def dyn_disk_serial_return(*args, **kwargs): def dyn_bcache_device_type(*args, **kwargs): bc_dev_map = { - 'sdd': 'cdev', - 'sdb': 'bdev', - 'sdc': 'bdev' + '/dev/sdd': 'cdev', + '/dev/sdb': 'bdev', + '/dev/sdc': 'bdev' } if args[0] in bc_dev_map: return bc_dev_map[args[0]] @@ -517,7 +520,9 @@ def dyn_bcache_device_type(*args, **kwargs): # Iterate the test data sets for run_command running lsblk. for o, e, r, expected in zip(out, err, rc, expected_result): self.mock_run_command.return_value = (o, e, r) + expected.sort(key=operator.itemgetter(0)) returned = scan_disks(1048576) + returned.sort(key=operator.itemgetter(0)) self.assertEqual(returned, expected, msg='Un-expected scan_disks() result:\n ' 'returned = ({}).\n ' @@ -539,236 +544,236 @@ def test_scan_disks_dell_perk_h710_md1220_36_disks(self): # N.B. listed in the order returned by lsblk. # All base device (ie sda of sda3) have lsblk accessible serials. out = [[ - 'NAME="sdy" MODEL="HUC101212CSS600 " SERIAL="5000cca01d2766c0" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:11:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 - 'NAME="sdf" MODEL="PERC H710 " SERIAL="6848f690e936450021a4585b05e46fcc" SIZE="7.3T" TRAN="" VENDOR="DELL " HCTL="0:2:5:0" TYPE="disk" FSTYPE="btrfs" LABEL="BIGDATA" UUID="cb15142f-9d1e-4cb2-9b1f-adda3af6555f"', # noqa E501 - 'NAME="sdab" MODEL="ST91000640SS " SERIAL="5000c50063041947" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:14:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 - 'NAME="sdo" MODEL="HUC101212CSS600 " SERIAL="5000cca01d21bc10" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:1:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 - 'NAME="sdw" MODEL="ST91000640SS " SERIAL="5000c500630450a3" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:9:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 - 'NAME="sdd" MODEL="PERC H710 " SERIAL="6848f690e9364500219f33b21773ea22" SIZE="558.4G" TRAN="" VENDOR="DELL " HCTL="0:2:3:0" TYPE="disk" FSTYPE="btrfs" LABEL="Test" UUID="612f1fc2-dfa8-4940-a1ad-e11c893b32ca"', # noqa E501 - 'NAME="sdm" MODEL="PERC H710 " SERIAL="6848f690e936450021acd1f30663b877" SIZE="7.3T" TRAN="" VENDOR="DELL " HCTL="0:2:12:0" TYPE="disk" FSTYPE="btrfs" LABEL="BIGDATA" UUID="cb15142f-9d1e-4cb2-9b1f-adda3af6555f"', # noqa E501 - 'NAME="sdu" MODEL="HUC101212CSS600 " SERIAL="5000cca01d273a24" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:7:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 - 'NAME="sdai" MODEL="ST91000640SS " SERIAL="5000c5006303ea0f" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:21:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 - 'NAME="sdb" MODEL="PERC H710 " SERIAL="6848f690e9364500219f339b1610b547" SIZE="558.4G" TRAN="" VENDOR="DELL " HCTL="0:2:1:0" TYPE="disk" FSTYPE="btrfs" LABEL="Test" UUID="612f1fc2-dfa8-4940-a1ad-e11c893b32ca"', # noqa E501 - 'NAME="sdk" MODEL="PERC H710 " SERIAL="6848f690e936450021acd1e705b389c6" SIZE="7.3T" TRAN="" VENDOR="DELL " HCTL="0:2:10:0" TYPE="disk" FSTYPE="btrfs" LABEL="BIGDATA" UUID="cb15142f-9d1e-4cb2-9b1f-adda3af6555f"', # noqa E501 - 'NAME="sds" MODEL="HUC101212CSS600 " SERIAL="5000cca01d217968" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:5:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 - 'NAME="sdag" MODEL="ST91000640SS " SERIAL="5000c50062cbc1f3" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:19:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 - 'NAME="sdi" MODEL="PERC H710 " SERIAL="6848f690e936450021a4586906bd9742" SIZE="7.3T" TRAN="" VENDOR="DELL " HCTL="0:2:8:0" TYPE="disk" FSTYPE="btrfs" LABEL="BIGDATA" UUID="cb15142f-9d1e-4cb2-9b1f-adda3af6555f"', # noqa E501 - 'NAME="sdq" MODEL="HUC101212CSS600 " SERIAL="5000cca01d29f384" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:3:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 - 'NAME="sdae" MODEL="INTEL SSDSC2KW24" SERIAL="CVLT6153072G240CGN" SIZE="223.6G" TRAN="sas" VENDOR="ATA " HCTL="1:0:17:0" TYPE="disk" FSTYPE="btrfs" LABEL="INTEL_SSD" UUID="a504bf03-0299-4648-8a95-c91aba291de8"', # noqa E501 - 'NAME="sdz" MODEL="ST91000640SS " SERIAL="5000c5006304544b" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:12:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 - 'NAME="sdg" MODEL="PERC H710 " SERIAL="6848f690e936450021ed61830ae57fbf" SIZE="7.3T" TRAN="" VENDOR="DELL " HCTL="0:2:6:0" TYPE="disk" FSTYPE="btrfs" LABEL="BIGDATA" UUID="cb15142f-9d1e-4cb2-9b1f-adda3af6555f"', # noqa E501 - 'NAME="sdac" MODEL="ST91000640SS " SERIAL="5000c500630249cb" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:15:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 - 'NAME="sdx" MODEL="ST91000640SS " SERIAL="5000c50063044387" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:10:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 - 'NAME="sde" MODEL="PERC H710 " SERIAL="6848f690e9364500219f33bb17fe7d7b" SIZE="558.4G" TRAN="" VENDOR="DELL " HCTL="0:2:4:0" TYPE="disk" FSTYPE="btrfs" LABEL="Test" UUID="612f1fc2-dfa8-4940-a1ad-e11c893b32ca"', # noqa E501 - 'NAME="sdaa" MODEL="ST91000640SS " SERIAL="5000c50063044363" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:13:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 - 'NAME="sdn" MODEL="HUC101212CSS600 " SERIAL="5000cca01d2144ac" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:0:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 - 'NAME="sdv" MODEL="HUC101212CSS600 " SERIAL="5000cca01d21893c" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:8:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 - 'NAME="sdaj" MODEL="INTEL SSDSC2KW24" SERIAL="CVLT6181019S240CGN" SIZE="223.6G" TRAN="sas" VENDOR="ATA " HCTL="1:0:22:0" TYPE="disk" FSTYPE="btrfs" LABEL="INTEL_SSD" UUID="a504bf03-0299-4648-8a95-c91aba291de8"', # noqa E501 - 'NAME="sdc" MODEL="PERC H710 " SERIAL="6848f690e936450021ed614a077c1b44" SIZE="7.3T" TRAN="" VENDOR="DELL " HCTL="0:2:2:0" TYPE="disk" FSTYPE="btrfs" LABEL="BIGDATA" UUID="cb15142f-9d1e-4cb2-9b1f-adda3af6555f"', # noqa E501 - 'NAME="sdl" MODEL="PERC H710 " SERIAL="6848f690e936450021a4525005828671" SIZE="4.6T" TRAN="" VENDOR="DELL " HCTL="0:2:11:0" TYPE="disk" FSTYPE="btrfs" LABEL="5TBWDGREEN" UUID="a37956a8-a175-4906-82c1-bf843132da1a"', # noqa E501 - 'NAME="sdt" MODEL="HUC101212CSS600 " SERIAL="5000cca01d2af91c" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:6:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 - 'NAME="sdah" MODEL="ST91000640SS " SERIAL="5000c50062cb366f" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:20:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 - 'NAME="sda" MODEL="PERC H710 " SERIAL="6848f690e936450018b7c3a11330997b" SIZE="278.9G" TRAN="" VENDOR="DELL " HCTL="0:2:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="sda2" MODEL="" SERIAL="" SIZE="13.8G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="swap" LABEL="" UUID="a34b82d0-c342-41e0-a58d-4f0a0027829d"', # noqa E501 - 'NAME="sda3" MODEL="" SERIAL="" SIZE="264.7G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="btrfs" LABEL="rockstor_rockstor" UUID="7f7acdd7-493e-4bb5-b801-b7b7dc289535"', # noqa E501 - 'NAME="sda1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="ext4" LABEL="" UUID="5d2848ff-ae8f-4c2f-b825-90621076acc1"', # noqa E501 - 'NAME="sdj" MODEL="PERC H710 " SERIAL="6848f690e936450021a45f9904046a2f" SIZE="2.7T" TRAN="" VENDOR="DELL " HCTL="0:2:9:0" TYPE="disk" FSTYPE="btrfs" LABEL="VMWARE_MECH_ARRAY" UUID="e6d13c0b-825f-4b43-81b6-7eb2b791b1c3"', # noqa E501 - 'NAME="sdr" MODEL="HUC101212CSS600 " SERIAL="5000cca01d2188e0" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:4:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 - 'NAME="sdaf" MODEL="ST91000640SS " SERIAL="5000c500630425df" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:18:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 - 'NAME="sdh" MODEL="PERC H710 " SERIAL="6848f690e9364500219f33d919c7488a" SIZE="558.4G" TRAN="" VENDOR="DELL " HCTL="0:2:7:0" TYPE="disk" FSTYPE="btrfs" LABEL="Test" UUID="612f1fc2-dfa8-4940-a1ad-e11c893b32ca"', # noqa E501 - 'NAME="sdp" MODEL="HUC101212CSS600 " SERIAL="5000cca01d21885c" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:2:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 - 'NAME="sdad" MODEL="INTEL SSDSC2KW24" SERIAL="CVLT618101SE240CGN" SIZE="223.6G" TRAN="sas" VENDOR="ATA " HCTL="1:0:16:0" TYPE="disk" FSTYPE="btrfs" LABEL="INTEL_SSD" UUID="a504bf03-0299-4648-8a95-c91aba291de8"', # noqa E501 + 'NAME="/dev/sdy" MODEL="HUC101212CSS600 " SERIAL="5000cca01d2766c0" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:11:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 + 'NAME="/dev/sdf" MODEL="PERC H710 " SERIAL="6848f690e936450021a4585b05e46fcc" SIZE="7.3T" TRAN="" VENDOR="DELL " HCTL="0:2:5:0" TYPE="disk" FSTYPE="btrfs" LABEL="BIGDATA" UUID="cb15142f-9d1e-4cb2-9b1f-adda3af6555f"', # noqa E501 + 'NAME="/dev/sdab" MODEL="ST91000640SS " SERIAL="5000c50063041947" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:14:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 + 'NAME="/dev/sdo" MODEL="HUC101212CSS600 " SERIAL="5000cca01d21bc10" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:1:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 + 'NAME="/dev/sdw" MODEL="ST91000640SS " SERIAL="5000c500630450a3" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:9:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 + 'NAME="/dev/sdd" MODEL="PERC H710 " SERIAL="6848f690e9364500219f33b21773ea22" SIZE="558.4G" TRAN="" VENDOR="DELL " HCTL="0:2:3:0" TYPE="disk" FSTYPE="btrfs" LABEL="Test" UUID="612f1fc2-dfa8-4940-a1ad-e11c893b32ca"', # noqa E501 + 'NAME="/dev/sdm" MODEL="PERC H710 " SERIAL="6848f690e936450021acd1f30663b877" SIZE="7.3T" TRAN="" VENDOR="DELL " HCTL="0:2:12:0" TYPE="disk" FSTYPE="btrfs" LABEL="BIGDATA" UUID="cb15142f-9d1e-4cb2-9b1f-adda3af6555f"', # noqa E501 + 'NAME="/dev/sdu" MODEL="HUC101212CSS600 " SERIAL="5000cca01d273a24" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:7:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 + 'NAME="/dev/sdai" MODEL="ST91000640SS " SERIAL="5000c5006303ea0f" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:21:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 + 'NAME="/dev/sdb" MODEL="PERC H710 " SERIAL="6848f690e9364500219f339b1610b547" SIZE="558.4G" TRAN="" VENDOR="DELL " HCTL="0:2:1:0" TYPE="disk" FSTYPE="btrfs" LABEL="Test" UUID="612f1fc2-dfa8-4940-a1ad-e11c893b32ca"', # noqa E501 + 'NAME="/dev/sdk" MODEL="PERC H710 " SERIAL="6848f690e936450021acd1e705b389c6" SIZE="7.3T" TRAN="" VENDOR="DELL " HCTL="0:2:10:0" TYPE="disk" FSTYPE="btrfs" LABEL="BIGDATA" UUID="cb15142f-9d1e-4cb2-9b1f-adda3af6555f"', # noqa E501 + 'NAME="/dev/sds" MODEL="HUC101212CSS600 " SERIAL="5000cca01d217968" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:5:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 + 'NAME="/dev/sdag" MODEL="ST91000640SS " SERIAL="5000c50062cbc1f3" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:19:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 + 'NAME="/dev/sdi" MODEL="PERC H710 " SERIAL="6848f690e936450021a4586906bd9742" SIZE="7.3T" TRAN="" VENDOR="DELL " HCTL="0:2:8:0" TYPE="disk" FSTYPE="btrfs" LABEL="BIGDATA" UUID="cb15142f-9d1e-4cb2-9b1f-adda3af6555f"', # noqa E501 + 'NAME="/dev/sdq" MODEL="HUC101212CSS600 " SERIAL="5000cca01d29f384" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:3:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 + 'NAME="/dev/sdae" MODEL="INTEL SSDSC2KW24" SERIAL="CVLT6153072G240CGN" SIZE="223.6G" TRAN="sas" VENDOR="ATA " HCTL="1:0:17:0" TYPE="disk" FSTYPE="btrfs" LABEL="INTEL_SSD" UUID="a504bf03-0299-4648-8a95-c91aba291de8"', # noqa E501 + 'NAME="/dev/sdz" MODEL="ST91000640SS " SERIAL="5000c5006304544b" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:12:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 + 'NAME="/dev/sdg" MODEL="PERC H710 " SERIAL="6848f690e936450021ed61830ae57fbf" SIZE="7.3T" TRAN="" VENDOR="DELL " HCTL="0:2:6:0" TYPE="disk" FSTYPE="btrfs" LABEL="BIGDATA" UUID="cb15142f-9d1e-4cb2-9b1f-adda3af6555f"', # noqa E501 + 'NAME="/dev/sdac" MODEL="ST91000640SS " SERIAL="5000c500630249cb" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:15:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 + 'NAME="/dev/sdx" MODEL="ST91000640SS " SERIAL="5000c50063044387" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:10:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 + 'NAME="/dev/sde" MODEL="PERC H710 " SERIAL="6848f690e9364500219f33bb17fe7d7b" SIZE="558.4G" TRAN="" VENDOR="DELL " HCTL="0:2:4:0" TYPE="disk" FSTYPE="btrfs" LABEL="Test" UUID="612f1fc2-dfa8-4940-a1ad-e11c893b32ca"', # noqa E501 + 'NAME="/dev/sdaa" MODEL="ST91000640SS " SERIAL="5000c50063044363" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:13:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 + 'NAME="/dev/sdn" MODEL="HUC101212CSS600 " SERIAL="5000cca01d2144ac" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:0:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 + 'NAME="/dev/sdv" MODEL="HUC101212CSS600 " SERIAL="5000cca01d21893c" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:8:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 + 'NAME="/dev/sdaj" MODEL="INTEL SSDSC2KW24" SERIAL="CVLT6181019S240CGN" SIZE="223.6G" TRAN="sas" VENDOR="ATA " HCTL="1:0:22:0" TYPE="disk" FSTYPE="btrfs" LABEL="INTEL_SSD" UUID="a504bf03-0299-4648-8a95-c91aba291de8"', # noqa E501 + 'NAME="/dev/sdc" MODEL="PERC H710 " SERIAL="6848f690e936450021ed614a077c1b44" SIZE="7.3T" TRAN="" VENDOR="DELL " HCTL="0:2:2:0" TYPE="disk" FSTYPE="btrfs" LABEL="BIGDATA" UUID="cb15142f-9d1e-4cb2-9b1f-adda3af6555f"', # noqa E501 + 'NAME="/dev/sdl" MODEL="PERC H710 " SERIAL="6848f690e936450021a4525005828671" SIZE="4.6T" TRAN="" VENDOR="DELL " HCTL="0:2:11:0" TYPE="disk" FSTYPE="btrfs" LABEL="5TBWDGREEN" UUID="a37956a8-a175-4906-82c1-bf843132da1a"', # noqa E501 + 'NAME="/dev/sdt" MODEL="HUC101212CSS600 " SERIAL="5000cca01d2af91c" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:6:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 + 'NAME="/dev/sdah" MODEL="ST91000640SS " SERIAL="5000c50062cb366f" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:20:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 + 'NAME="/dev/sda" MODEL="PERC H710 " SERIAL="6848f690e936450018b7c3a11330997b" SIZE="278.9G" TRAN="" VENDOR="DELL " HCTL="0:2:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/sda2" MODEL="" SERIAL="" SIZE="13.8G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="swap" LABEL="" UUID="a34b82d0-c342-41e0-a58d-4f0a0027829d"', # noqa E501 + 'NAME="/dev/sda3" MODEL="" SERIAL="" SIZE="264.7G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="btrfs" LABEL="rockstor_rockstor" UUID="7f7acdd7-493e-4bb5-b801-b7b7dc289535"', # noqa E501 + 'NAME="/dev/sda1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="ext4" LABEL="" UUID="5d2848ff-ae8f-4c2f-b825-90621076acc1"', # noqa E501 + 'NAME="/dev/sdj" MODEL="PERC H710 " SERIAL="6848f690e936450021a45f9904046a2f" SIZE="2.7T" TRAN="" VENDOR="DELL " HCTL="0:2:9:0" TYPE="disk" FSTYPE="btrfs" LABEL="VMWARE_MECH_ARRAY" UUID="e6d13c0b-825f-4b43-81b6-7eb2b791b1c3"', # noqa E501 + 'NAME="/dev/sdr" MODEL="HUC101212CSS600 " SERIAL="5000cca01d2188e0" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:4:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 + 'NAME="/dev/sdaf" MODEL="ST91000640SS " SERIAL="5000c500630425df" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:18:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 + 'NAME="/dev/sdh" MODEL="PERC H710 " SERIAL="6848f690e9364500219f33d919c7488a" SIZE="558.4G" TRAN="" VENDOR="DELL " HCTL="0:2:7:0" TYPE="disk" FSTYPE="btrfs" LABEL="Test" UUID="612f1fc2-dfa8-4940-a1ad-e11c893b32ca"', # noqa E501 + 'NAME="/dev/sdp" MODEL="HUC101212CSS600 " SERIAL="5000cca01d21885c" SIZE="1.1T" TRAN="sas" VENDOR="HGST " HCTL="1:0:2:0" TYPE="disk" FSTYPE="btrfs" LABEL="MD1220-DAS" UUID="12d76eb6-7aad-46ba-863e-d9c51e8e6f2d"', # noqa E501 + 'NAME="/dev/sdad" MODEL="INTEL SSDSC2KW24" SERIAL="CVLT618101SE240CGN" SIZE="223.6G" TRAN="sas" VENDOR="ATA " HCTL="1:0:16:0" TYPE="disk" FSTYPE="btrfs" LABEL="INTEL_SSD" UUID="a504bf03-0299-4648-8a95-c91aba291de8"', # noqa E501 '' ]] err = [['']] rc = [0] expected_result = [[ - Disk(name='sda3', model='PERC H710', + Disk(name='/dev/sda3', model='PERC H710', serial='6848f690e936450018b7c3a11330997b', size=277558067, transport=None, vendor='DELL', hctl='0:2:0:0', type='part', fstype='btrfs', label='rockstor_rockstor', uuid='7f7acdd7-493e-4bb5-b801-b7b7dc289535', parted=True, root=True, partitions={}), - Disk(name='sdt', model='HUC101212CSS600', + Disk(name='/dev/sdt', model='HUC101212CSS600', serial='5000cca01d2af91c', size=1181116006, transport='sas', vendor='HGST', hctl='1:0:6:0', type='disk', fstype='btrfs', label='MD1220-DAS', uuid='12d76eb6-7aad-46ba-863e-d9c51e8e6f2d', parted=False, root=False, partitions={}), - Disk(name='sdu', model='HUC101212CSS600', + Disk(name='/dev/sdu', model='HUC101212CSS600', serial='5000cca01d273a24', size=1181116006, transport='sas', vendor='HGST', hctl='1:0:7:0', type='disk', fstype='btrfs', label='MD1220-DAS', uuid='12d76eb6-7aad-46ba-863e-d9c51e8e6f2d', parted=False, root=False, partitions={}), - Disk(name='sdv', model='HUC101212CSS600', + Disk(name='/dev/sdv', model='HUC101212CSS600', serial='5000cca01d21893c', size=1181116006, transport='sas', vendor='HGST', hctl='1:0:8:0', type='disk', fstype='btrfs', label='MD1220-DAS', uuid='12d76eb6-7aad-46ba-863e-d9c51e8e6f2d', parted=False, root=False, partitions={}), - Disk(name='sdw', model='ST91000640SS', serial='5000c500630450a3', + Disk(name='/dev/sdw', model='ST91000640SS', serial='5000c500630450a3', # noqa E501 size=976748544, transport='sas', vendor='SEAGATE', hctl='1:0:9:0', type='disk', fstype='btrfs', label='SCRATCH', uuid='a90e6787-1c45-46d6-a2ba-41017a17c1d5', parted=False, root=False, partitions={}), - Disk(name='sdp', model='HUC101212CSS600', + Disk(name='/dev/sdp', model='HUC101212CSS600', serial='5000cca01d21885c', size=1181116006, transport='sas', vendor='HGST', hctl='1:0:2:0', type='disk', fstype='btrfs', label='MD1220-DAS', uuid='12d76eb6-7aad-46ba-863e-d9c51e8e6f2d', parted=False, root=False, partitions={}), - Disk(name='sdq', model='HUC101212CSS600', + Disk(name='/dev/sdq', model='HUC101212CSS600', serial='5000cca01d29f384', size=1181116006, transport='sas', vendor='HGST', hctl='1:0:3:0', type='disk', fstype='btrfs', label='MD1220-DAS', uuid='12d76eb6-7aad-46ba-863e-d9c51e8e6f2d', parted=False, root=False, partitions={}), - Disk(name='sdr', model='HUC101212CSS600', + Disk(name='/dev/sdr', model='HUC101212CSS600', serial='5000cca01d2188e0', size=1181116006, transport='sas', vendor='HGST', hctl='1:0:4:0', type='disk', fstype='btrfs', label='MD1220-DAS', uuid='12d76eb6-7aad-46ba-863e-d9c51e8e6f2d', parted=False, root=False, partitions={}), - Disk(name='sds', model='HUC101212CSS600', + Disk(name='/dev/sds', model='HUC101212CSS600', serial='5000cca01d217968', size=1181116006, transport='sas', vendor='HGST', hctl='1:0:5:0', type='disk', fstype='btrfs', label='MD1220-DAS', uuid='12d76eb6-7aad-46ba-863e-d9c51e8e6f2d', parted=False, root=False, partitions={}), - Disk(name='sdx', model='ST91000640SS', serial='5000c50063044387', + Disk(name='/dev/sdx', model='ST91000640SS', serial='5000c50063044387', # noqa E501 size=976748544, transport='sas', vendor='SEAGATE', hctl='1:0:10:0', type='disk', fstype='btrfs', label='SCRATCH', uuid='a90e6787-1c45-46d6-a2ba-41017a17c1d5', parted=False, root=False, partitions={}), - Disk(name='sdy', model='HUC101212CSS600', + Disk(name='/dev/sdy', model='HUC101212CSS600', serial='5000cca01d2766c0', size=1181116006, transport='sas', vendor='HGST', hctl='1:0:11:0', type='disk', fstype='btrfs', label='MD1220-DAS', uuid='12d76eb6-7aad-46ba-863e-d9c51e8e6f2d', parted=False, root=False, partitions={}), - Disk(name='sdz', model='ST91000640SS', serial='5000c5006304544b', + Disk(name='/dev/sdz', model='ST91000640SS', serial='5000c5006304544b', # noqa E501 size=976748544, transport='sas', vendor='SEAGATE', hctl='1:0:12:0', type='disk', fstype='btrfs', label='SCRATCH', uuid='a90e6787-1c45-46d6-a2ba-41017a17c1d5', parted=False, root=False, partitions={}), - Disk(name='sdd', model='PERC H710', + Disk(name='/dev/sdd', model='PERC H710', serial='6848f690e9364500219f33b21773ea22', size=585524838, transport=None, vendor='DELL', hctl='0:2:3:0', type='disk', fstype='btrfs', label='Test', uuid='612f1fc2-dfa8-4940-a1ad-e11c893b32ca', parted=False, root=False, partitions={}), - Disk(name='sde', model='PERC H710', + Disk(name='/dev/sde', model='PERC H710', serial='6848f690e9364500219f33bb17fe7d7b', size=585524838, transport=None, vendor='DELL', hctl='0:2:4:0', type='disk', fstype='btrfs', label='Test', uuid='612f1fc2-dfa8-4940-a1ad-e11c893b32ca', parted=False, root=False, partitions={}), - Disk(name='sdf', model='PERC H710', + Disk(name='/dev/sdf', model='PERC H710', serial='6848f690e936450021a4585b05e46fcc', size=7838315315, transport=None, vendor='DELL', hctl='0:2:5:0', type='disk', fstype='btrfs', label='BIGDATA', uuid='cb15142f-9d1e-4cb2-9b1f-adda3af6555f', parted=False, root=False, partitions={}), - Disk(name='sdg', model='PERC H710', + Disk(name='/dev/sdg', model='PERC H710', serial='6848f690e936450021ed61830ae57fbf', size=7838315315, transport=None, vendor='DELL', hctl='0:2:6:0', type='disk', fstype='btrfs', label='BIGDATA', uuid='cb15142f-9d1e-4cb2-9b1f-adda3af6555f', parted=False, root=False, partitions={}), - Disk(name='sdb', model='PERC H710', + Disk(name='/dev/sdb', model='PERC H710', serial='6848f690e9364500219f339b1610b547', size=585524838, transport=None, vendor='DELL', hctl='0:2:1:0', type='disk', fstype='btrfs', label='Test', uuid='612f1fc2-dfa8-4940-a1ad-e11c893b32ca', parted=False, root=False, partitions={}), - Disk(name='sdc', model='PERC H710', + Disk(name='/dev/sdc', model='PERC H710', serial='6848f690e936450021ed614a077c1b44', size=7838315315, transport=None, vendor='DELL', hctl='0:2:2:0', type='disk', fstype='btrfs', label='BIGDATA', uuid='cb15142f-9d1e-4cb2-9b1f-adda3af6555f', parted=False, root=False, partitions={}), - Disk(name='sdl', model='PERC H710', + Disk(name='/dev/sdl', model='PERC H710', serial='6848f690e936450021a4525005828671', size=4939212390, transport=None, vendor='DELL', hctl='0:2:11:0', type='disk', fstype='btrfs', label='5TBWDGREEN', uuid='a37956a8-a175-4906-82c1-bf843132da1a', parted=False, root=False, partitions={}), - Disk(name='sdm', model='PERC H710', + Disk(name='/dev/sdm', model='PERC H710', serial='6848f690e936450021acd1f30663b877', size=7838315315, transport=None, vendor='DELL', hctl='0:2:12:0', type='disk', fstype='btrfs', label='BIGDATA', uuid='cb15142f-9d1e-4cb2-9b1f-adda3af6555f', parted=False, root=False, partitions={}), - Disk(name='sdn', model='HUC101212CSS600', + Disk(name='/dev/sdn', model='HUC101212CSS600', serial='5000cca01d2144ac', size=1181116006, transport='sas', vendor='HGST', hctl='1:0:0:0', type='disk', fstype='btrfs', label='MD1220-DAS', uuid='12d76eb6-7aad-46ba-863e-d9c51e8e6f2d', parted=False, root=False, partitions={}), - Disk(name='sdo', model='HUC101212CSS600', + Disk(name='/dev/sdo', model='HUC101212CSS600', serial='5000cca01d21bc10', size=1181116006, transport='sas', vendor='HGST', hctl='1:0:1:0', type='disk', fstype='btrfs', label='MD1220-DAS', uuid='12d76eb6-7aad-46ba-863e-d9c51e8e6f2d', parted=False, root=False, partitions={}), - Disk(name='sdh', model='PERC H710', + Disk(name='/dev/sdh', model='PERC H710', serial='6848f690e9364500219f33d919c7488a', size=585524838, transport=None, vendor='DELL', hctl='0:2:7:0', type='disk', fstype='btrfs', label='Test', uuid='612f1fc2-dfa8-4940-a1ad-e11c893b32ca', parted=False, root=False, partitions={}), - Disk(name='sdi', model='PERC H710', + Disk(name='/dev/sdi', model='PERC H710', serial='6848f690e936450021a4586906bd9742', size=7838315315, transport=None, vendor='DELL', hctl='0:2:8:0', type='disk', fstype='btrfs', label='BIGDATA', uuid='cb15142f-9d1e-4cb2-9b1f-adda3af6555f', parted=False, root=False, partitions={}), - Disk(name='sdj', model='PERC H710', + Disk(name='/dev/sdj', model='PERC H710', serial='6848f690e936450021a45f9904046a2f', size=2899102924, transport=None, vendor='DELL', hctl='0:2:9:0', type='disk', fstype='btrfs', label='VMWARE_MECH_ARRAY', uuid='e6d13c0b-825f-4b43-81b6-7eb2b791b1c3', parted=False, root=False, partitions={}), - Disk(name='sdk', model='PERC H710', + Disk(name='/dev/sdk', model='PERC H710', serial='6848f690e936450021acd1e705b389c6', size=7838315315, transport=None, vendor='DELL', hctl='0:2:10:0', type='disk', fstype='btrfs', label='BIGDATA', uuid='cb15142f-9d1e-4cb2-9b1f-adda3af6555f', parted=False, root=False, partitions={}), - Disk(name='sdaf', model='ST91000640SS', + Disk(name='/dev/sdaf', model='ST91000640SS', serial='5000c500630425df', size=976748544, transport='sas', vendor='SEAGATE', hctl='1:0:18:0', type='disk', fstype='btrfs', label='SCRATCH', uuid='a90e6787-1c45-46d6-a2ba-41017a17c1d5', parted=False, root=False, partitions={}), - Disk(name='sdag', model='ST91000640SS', + Disk(name='/dev/sdag', model='ST91000640SS', serial='5000c50062cbc1f3', size=976748544, transport='sas', vendor='SEAGATE', hctl='1:0:19:0', type='disk', fstype='btrfs', label='SCRATCH', uuid='a90e6787-1c45-46d6-a2ba-41017a17c1d5', parted=False, root=False, partitions={}), - Disk(name='sdad', model='INTEL SSDSC2KW24', + Disk(name='/dev/sdad', model='INTEL SSDSC2KW24', serial='CVLT618101SE240CGN', size=234461593, transport='sas', vendor='ATA', hctl='1:0:16:0', type='disk', fstype='btrfs', label='INTEL_SSD', uuid='a504bf03-0299-4648-8a95-c91aba291de8', parted=False, root=False, partitions={}), - Disk(name='sdae', model='INTEL SSDSC2KW24', + Disk(name='/dev/sdae', model='INTEL SSDSC2KW24', serial='CVLT6153072G240CGN', size=234461593, transport='sas', vendor='ATA', hctl='1:0:17:0', @@ -777,42 +782,42 @@ def test_scan_disks_dell_perk_h710_md1220_36_disks(self): root=False, partitions={}), # N.B. we have sdab with serial=None, suspected due to first listed # matching base root device name of sda (sda3). - Disk(name='sdab', model='ST91000640SS', + Disk(name='/dev/sdab', model='ST91000640SS', serial='5000c50063041947', size=976748544, transport='sas', vendor='SEAGATE', hctl='1:0:14:0', type='disk', fstype='btrfs', label='SCRATCH', uuid='a90e6787-1c45-46d6-a2ba-41017a17c1d5', parted=False, root=False, partitions={}), - Disk(name='sdac', model='ST91000640SS', + Disk(name='/dev/sdac', model='ST91000640SS', serial='5000c500630249cb', size=976748544, transport='sas', vendor='SEAGATE', hctl='1:0:15:0', type='disk', fstype='btrfs', label='SCRATCH', uuid='a90e6787-1c45-46d6-a2ba-41017a17c1d5', parted=False, root=False, partitions={}), - Disk(name='sdaa', model='ST91000640SS', + Disk(name='/dev/sdaa', model='ST91000640SS', serial='5000c50063044363', size=976748544, transport='sas', vendor='SEAGATE', hctl='1:0:13:0', type='disk', fstype='btrfs', label='SCRATCH', uuid='a90e6787-1c45-46d6-a2ba-41017a17c1d5', parted=False, root=False, partitions={}), - Disk(name='sdaj', model='INTEL SSDSC2KW24', + Disk(name='/dev/sdaj', model='INTEL SSDSC2KW24', serial='CVLT6181019S240CGN', size=234461593, transport='sas', vendor='ATA', hctl='1:0:22:0', type='disk', fstype='btrfs', label='INTEL_SSD', uuid='a504bf03-0299-4648-8a95-c91aba291de8', parted=False, root=False, partitions={}), - Disk(name='sdah', model='ST91000640SS', + Disk(name='/dev/sdah', model='ST91000640SS', serial='5000c50062cb366f', size=976748544, transport='sas', vendor='SEAGATE', hctl='1:0:20:0', type='disk', fstype='btrfs', label='SCRATCH', uuid='a90e6787-1c45-46d6-a2ba-41017a17c1d5', parted=False, root=False, partitions={}), - Disk(name='sdai', model='ST91000640SS', + Disk(name='/dev/sdai', model='ST91000640SS', serial='5000c5006303ea0f', size=976748544, transport='sas', vendor='SEAGATE', hctl='1:0:21:0', type='disk', fstype='btrfs', @@ -830,10 +835,8 @@ def test_scan_disks_dell_perk_h710_md1220_36_disks(self): returned = scan_disks(1048576, test_mode=True) # TODO: Would be nice to have differences found shown. # - # TODO: Test could also be more flexible / robust if we are - # insensitive to order, ie sort both returned and expected - # expected.sort(key=operator.itemgetter(0)) - # returned.sort(key=operator.itemgetter(0)) + expected.sort(key=operator.itemgetter(0)) + returned.sort(key=operator.itemgetter(0)) self.assertEqual(returned, expected, msg='Un-expected scan_disks() result:\n ' 'returned = ({}).\n ' @@ -856,18 +859,18 @@ def test_scan_disks_27_plus_disks_regression_issue(self): devices: without this the issue does not present. """ out = [[ - 'NAME="sdab" MODEL="ST91000640SS " SERIAL="5000c50063041947" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:14:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 - 'NAME="sdai" MODEL="ST91000640SS " SERIAL="5000c5006303ea0f" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:21:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 - 'NAME="sda" MODEL="PERC H710 " SERIAL="6848f690e936450018b7c3a11330997b" SIZE="278.9G" TRAN="" VENDOR="DELL " HCTL="0:2:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="sda2" MODEL="" SERIAL="" SIZE="13.8G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="swap" LABEL="" UUID="a34b82d0-c342-41e0-a58d-4f0a0027829d"', # noqa E501 - 'NAME="sda3" MODEL="" SERIAL="" SIZE="264.7G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="btrfs" LABEL="rockstor_rockstor" UUID="7f7acdd7-493e-4bb5-b801-b7b7dc289535"', # noqa E501 - 'NAME="sda1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="ext4" LABEL="" UUID="5d2848ff-ae8f-4c2f-b825-90621076acc1"', # noqa E501 + 'NAME="/dev/sdab" MODEL="ST91000640SS " SERIAL="5000c50063041947" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:14:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 + 'NAME="/dev/sdai" MODEL="ST91000640SS " SERIAL="5000c5006303ea0f" SIZE="931.5G" TRAN="sas" VENDOR="SEAGATE " HCTL="1:0:21:0" TYPE="disk" FSTYPE="btrfs" LABEL="SCRATCH" UUID="a90e6787-1c45-46d6-a2ba-41017a17c1d5"', # noqa E501 + 'NAME="/dev/sda" MODEL="PERC H710 " SERIAL="6848f690e936450018b7c3a11330997b" SIZE="278.9G" TRAN="" VENDOR="DELL " HCTL="0:2:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/sda2" MODEL="" SERIAL="" SIZE="13.8G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="swap" LABEL="" UUID="a34b82d0-c342-41e0-a58d-4f0a0027829d"', # noqa E501 + 'NAME="/dev/sda3" MODEL="" SERIAL="" SIZE="264.7G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="btrfs" LABEL="rockstor_rockstor" UUID="7f7acdd7-493e-4bb5-b801-b7b7dc289535"', # noqa E501 + 'NAME="/dev/sda1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="ext4" LABEL="" UUID="5d2848ff-ae8f-4c2f-b825-90621076acc1"', # noqa E501 '' ]] err = [['']] rc = [0] expected_result = [[ - Disk(name='sda3', model='PERC H710', + Disk(name='/dev/sda3', model='PERC H710', serial='6848f690e936450018b7c3a11330997b', size=277558067, transport=None, vendor='DELL', hctl='0:2:0:0', type='part', fstype='btrfs', label='rockstor_rockstor', @@ -875,13 +878,13 @@ def test_scan_disks_27_plus_disks_regression_issue(self): root=True, partitions={}), # N.B. we have sdab with serial=None, suspected due to first listed # matching base root device name of sda (sda3). - Disk(name='sdab', model=None, serial=None, size=976748544, + Disk(name='/dev/sdab', model=None, serial=None, size=976748544, transport=None, vendor=None, hctl=None, type='disk', fstype='btrfs', label='SCRATCH', uuid='a90e6787-1c45-46d6-a2ba-41017a17c1d5', parted=False, root=True, partitions={}), # Subsequent sda[a-z] device receives 'fake-serial-' - Disk(name='sdai', model=None, + Disk(name='/dev/sdai', model=None, serial='fake-serial-', size=976748544, transport=None, vendor=None, hctl=None, type='disk', fstype='btrfs', label='SCRATCH', @@ -919,40 +922,40 @@ def test_scan_disks_luks_sys_disk(self): # Rockstor sees this install as system on hole disk dev (open luks dev) # ie the system btrfs volume is on whole disk not within a partition. out = [[ - 'NAME="sdb" MODEL="QEMU HARDDISK " SERIAL="2" SIZE="5G" TRAN="sata" VENDOR="ATA " HCTL="5:0:0:0" TYPE="disk" FSTYPE="btrfs" LABEL="rock-pool" UUID="50b66542-9a19-4403-b5a0-cd22412d9ae9"', # noqa E501 - 'NAME="sr0" MODEL="QEMU DVD-ROM " SERIAL="QM00005" SIZE="1024M" TRAN="sata" VENDOR="QEMU " HCTL="2:0:0:0" TYPE="rom" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="sdc" MODEL="QEMU HARDDISK " SERIAL="QM00013" SIZE="8G" TRAN="sata" VENDOR="ATA " HCTL="6:0:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="sdc2" MODEL="" SERIAL="" SIZE="820M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="crypto_LUKS" LABEL="" UUID="3efae1ba-dbdf-4102-8bdc-e607e3448a7d"', # noqa E501 - 'NAME="luks-3efae1ba-dbdf-4102-8bdc-e607e3448a7d" MODEL="" SERIAL="" SIZE="818M" TRAN="" VENDOR="" HCTL="" TYPE="crypt" FSTYPE="swap" LABEL="" UUID="1ef3c0a9-73b6-4271-a618-8fe4e580edac"', # noqa E501 - 'NAME="sdc3" MODEL="" SERIAL="" SIZE="6.7G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="crypto_LUKS" LABEL="" UUID="315111a6-8d37-447a-8dbf-0c9026abc456"', # noqa E501 - 'NAME="luks-315111a6-8d37-447a-8dbf-0c9026abc456" MODEL="" SERIAL="" SIZE="6.7G" TRAN="" VENDOR="" HCTL="" TYPE="crypt" FSTYPE="btrfs" LABEL="rockstor_rockstor" UUID="d763b614-5eb3-45ac-8ac6-8f5aa5d0b74d"', # noqa E501 - 'NAME="sdc1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="ext4" LABEL="" UUID="bcd91aba-6f2d-441b-9f31-804ac094befe"', # noqa E501 - 'NAME="sda" MODEL="QEMU HARDDISK " SERIAL="1" SIZE="5G" TRAN="sata" VENDOR="ATA " HCTL="3:0:0:0" TYPE="disk" FSTYPE="btrfs" LABEL="rock-pool" UUID="50b66542-9a19-4403-b5a0-cd22412d9ae9"', # noqa E501 + 'NAME="/dev/sdb" MODEL="QEMU HARDDISK " SERIAL="2" SIZE="5G" TRAN="sata" VENDOR="ATA " HCTL="5:0:0:0" TYPE="disk" FSTYPE="btrfs" LABEL="rock-pool" UUID="50b66542-9a19-4403-b5a0-cd22412d9ae9"', # noqa E501 + 'NAME="/dev/sr0" MODEL="QEMU DVD-ROM " SERIAL="QM00005" SIZE="1024M" TRAN="sata" VENDOR="QEMU " HCTL="2:0:0:0" TYPE="rom" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/sdc" MODEL="QEMU HARDDISK " SERIAL="QM00013" SIZE="8G" TRAN="sata" VENDOR="ATA " HCTL="6:0:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/sdc2" MODEL="" SERIAL="" SIZE="820M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="crypto_LUKS" LABEL="" UUID="3efae1ba-dbdf-4102-8bdc-e607e3448a7d"', # noqa E501 + 'NAME="/dev/mapper/luks-3efae1ba-dbdf-4102-8bdc-e607e3448a7d" MODEL="" SERIAL="" SIZE="818M" TRAN="" VENDOR="" HCTL="" TYPE="crypt" FSTYPE="swap" LABEL="" UUID="1ef3c0a9-73b6-4271-a618-8fe4e580edac"', # noqa E501 + 'NAME="/dev/sdc3" MODEL="" SERIAL="" SIZE="6.7G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="crypto_LUKS" LABEL="" UUID="315111a6-8d37-447a-8dbf-0c9026abc456"', # noqa E501 + 'NAME="/dev/mapper/luks-315111a6-8d37-447a-8dbf-0c9026abc456" MODEL="" SERIAL="" SIZE="6.7G" TRAN="" VENDOR="" HCTL="" TYPE="crypt" FSTYPE="btrfs" LABEL="rockstor_rockstor" UUID="d763b614-5eb3-45ac-8ac6-8f5aa5d0b74d"', # noqa E501 + 'NAME="/dev/sdc1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="ext4" LABEL="" UUID="bcd91aba-6f2d-441b-9f31-804ac094befe"', # noqa E501 + 'NAME="/dev/sda" MODEL="QEMU HARDDISK " SERIAL="1" SIZE="5G" TRAN="sata" VENDOR="ATA " HCTL="3:0:0:0" TYPE="disk" FSTYPE="btrfs" LABEL="rock-pool" UUID="50b66542-9a19-4403-b5a0-cd22412d9ae9"', # noqa E501 '']] err = [['']] rc = [0] expected_result = [[ - Disk(name='luks-315111a6-8d37-447a-8dbf-0c9026abc456', model=None, + Disk(name='/dev/mapper/luks-315111a6-8d37-447a-8dbf-0c9026abc456', model=None, # noqa E501 serial='CRYPT-LUKS1-315111a68d37447a8dbf0c9026abc456-luks-315111a6-8d37-447a-8dbf-0c9026abc456', # noqa E501 size=7025459, transport=None, vendor=None, hctl=None, type='crypt', fstype='btrfs', label='rockstor_rockstor', uuid='d763b614-5eb3-45ac-8ac6-8f5aa5d0b74d', parted=False, root=True, partitions={}), - Disk(name='sda', model='QEMU HARDDISK', serial='1', size=5242880, + Disk(name='/dev/sda', model='QEMU HARDDISK', serial='1', size=5242880, # noqa E501 transport='sata', vendor='ATA', hctl='3:0:0:0', type='disk', fstype='btrfs', label='rock-pool', uuid='50b66542-9a19-4403-b5a0-cd22412d9ae9', parted=False, root=False, partitions={}), - Disk(name='sdb', model='QEMU HARDDISK', serial='2', size=5242880, + Disk(name='/dev/sdb', model='QEMU HARDDISK', serial='2', size=5242880, # noqa E501 transport='sata', vendor='ATA', hctl='5:0:0:0', type='disk', fstype='btrfs', label='rock-pool', uuid='50b66542-9a19-4403-b5a0-cd22412d9ae9', parted=False, root=False, partitions={}), - Disk(name='sdc', model='QEMU HARDDISK', serial='QM00013', + Disk(name='/dev/sdc', model='QEMU HARDDISK', serial='QM00013', size=8388608, transport='sata', vendor='ATA', hctl='6:0:0:0', type='disk', fstype='crypto_LUKS', label=None, uuid='315111a6-8d37-447a-8dbf-0c9026abc456', parted=True, - root=False, partitions={'sdc3': 'crypto_LUKS'}) + root=False, partitions={'/dev/sdc3': 'crypto_LUKS'}) ]] # Establish dynamic mock behaviour for get_disk_serial() @@ -964,7 +967,7 @@ def dyn_disk_serial_return(*args, **kwargs): # Entries only requred here if lsblk test data has no serial info: # eg for bcache, LUKS, mdraid, and virtio type devices. s_map = { - 'luks-315111a6-8d37-447a-8dbf-0c9026abc456': 'CRYPT-LUKS1-315111a68d37447a8dbf0c9026abc456-luks-315111a6-8d37-447a-8dbf-0c9026abc456' # noqa E501 + '/dev/mapper/luks-315111a6-8d37-447a-8dbf-0c9026abc456': 'CRYPT-LUKS1-315111a68d37447a8dbf0c9026abc456-luks-315111a6-8d37-447a-8dbf-0c9026abc456' # noqa E501 } # First argument in get_disk_serial() is device_name, key off this # for our dynamic mock return from s_map (serial map). @@ -980,7 +983,7 @@ def dyn_disk_serial_return(*args, **kwargs): # # Ensure we correctly mock our root_disk value away from file default # of sda as we now have a root_disk on luks: - self.mock_root_disk.return_value = 'luks-315111a6-8d37-447a-8dbf-0c9026abc456' # noqa E501 + self.mock_root_disk.return_value = '/dev/mapper/luks-315111a6-8d37-447a-8dbf-0c9026abc456' # noqa E501 for o, e, r, expected in zip(out, err, rc, expected_result): self.mock_run_command.return_value = (o, e, r) @@ -1031,23 +1034,23 @@ def test_scan_disks_btrfs_in_partition(self): root on sda, ie 'Regex to identify a partition on the base_root_disk.' """ out = [[ - 'NAME="sr0" MODEL="QEMU DVD-ROM " SERIAL="QM00001" SIZE="1024M" TRAN="ata" VENDOR="QEMU " HCTL="0:0:0:0" TYPE="rom" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="sda" MODEL="QEMU HARDDISK " SERIAL="QM00005" SIZE="8G" TRAN="sata" VENDOR="ATA " HCTL="2:0:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="sda2" MODEL="" SERIAL="" SIZE="820M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="swap" LABEL="" UUID="aaf61037-23b1-4c3b-81ca-6d07f3ed922d"', # noqa E501 - 'NAME="sda3" MODEL="" SERIAL="" SIZE="6.7G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="btrfs" LABEL="rockstor_rockstor" UUID="355f53a4-24e1-465e-95f3-7c422898f542"', # noqa E501 - 'NAME="sda1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="ext4" LABEL="" UUID="04ce9f16-a0a0-4db8-8719-1083a0d4f381"', # noqa E501 - 'NAME="vda" MODEL="" SERIAL="" SIZE="8G" TRAN="" VENDOR="0x1af4" HCTL="" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="vda2" MODEL="" SERIAL="" SIZE="4G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="btrfs" LABEL="btrfs-in-partition" UUID="55284332-af66-4ca0-9647-99d9afbe0ec5"', # noqa E501 - 'NAME="vda1" MODEL="" SERIAL="" SIZE="4G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="vfat" LABEL="" UUID="8F05-D915"', # noqa E501 + 'NAME="/dev/sr0" MODEL="QEMU DVD-ROM " SERIAL="QM00001" SIZE="1024M" TRAN="ata" VENDOR="QEMU " HCTL="0:0:0:0" TYPE="rom" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/sda" MODEL="QEMU HARDDISK " SERIAL="QM00005" SIZE="8G" TRAN="sata" VENDOR="ATA " HCTL="2:0:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/sda2" MODEL="" SERIAL="" SIZE="820M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="swap" LABEL="" UUID="aaf61037-23b1-4c3b-81ca-6d07f3ed922d"', # noqa E501 + 'NAME="/dev/sda3" MODEL="" SERIAL="" SIZE="6.7G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="btrfs" LABEL="rockstor_rockstor" UUID="355f53a4-24e1-465e-95f3-7c422898f542"', # noqa E501 + 'NAME="/dev/sda1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="ext4" LABEL="" UUID="04ce9f16-a0a0-4db8-8719-1083a0d4f381"', # noqa E501 + 'NAME="/dev/vda" MODEL="" SERIAL="" SIZE="8G" TRAN="" VENDOR="0x1af4" HCTL="" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/vda2" MODEL="" SERIAL="" SIZE="4G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="btrfs" LABEL="btrfs-in-partition" UUID="55284332-af66-4ca0-9647-99d9afbe0ec5"', # noqa E501 + 'NAME="/dev/vda1" MODEL="" SERIAL="" SIZE="4G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="vfat" LABEL="" UUID="8F05-D915"', # noqa E501 ''], [ - 'NAME="sr0" MODEL="QEMU DVD-ROM " SERIAL="QM00001" SIZE="1024M" TRAN="ata" VENDOR="QEMU " HCTL="0:0:0:0" TYPE="rom" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="sda" MODEL="QEMU HARDDISK " SERIAL="QM00005" SIZE="8G" TRAN="sata" VENDOR="ATA " HCTL="2:0:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="sda2" MODEL="" SERIAL="" SIZE="820M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="swap" LABEL="" UUID="aaf61037-23b1-4c3b-81ca-6d07f3ed922d"', # noqa E501 - 'NAME="sda3" MODEL="" SERIAL="" SIZE="6.7G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="btrfs" LABEL="rockstor_rockstor" UUID="355f53a4-24e1-465e-95f3-7c422898f542"', # noqa E501 - 'NAME="sda1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="ext4" LABEL="" UUID="04ce9f16-a0a0-4db8-8719-1083a0d4f381"', # noqa E501 - 'NAME="sdap" MODEL="QEMU HARDDISK " SERIAL="42nd-scsi" SIZE="8G" TRAN="sata" VENDOR="ATA " HCTL="3:0:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="sdap2" MODEL="" SERIAL="" SIZE="4G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="btrfs" LABEL="btrfs-in-partition" UUID="55284332-af66-4ca0-9647-99d9afbe0ec5"', # noqa E501 - 'NAME="sdap1" MODEL="" SERIAL="" SIZE="4G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="vfat" LABEL="" UUID="8F05-D915"', # noqa E501 + 'NAME="/dev/sr0" MODEL="QEMU DVD-ROM " SERIAL="QM00001" SIZE="1024M" TRAN="ata" VENDOR="QEMU " HCTL="0:0:0:0" TYPE="rom" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/sda" MODEL="QEMU HARDDISK " SERIAL="QM00005" SIZE="8G" TRAN="sata" VENDOR="ATA " HCTL="2:0:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/sda2" MODEL="" SERIAL="" SIZE="820M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="swap" LABEL="" UUID="aaf61037-23b1-4c3b-81ca-6d07f3ed922d"', # noqa E501 + 'NAME="/dev/sda3" MODEL="" SERIAL="" SIZE="6.7G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="btrfs" LABEL="rockstor_rockstor" UUID="355f53a4-24e1-465e-95f3-7c422898f542"', # noqa E501 + 'NAME="/dev/sda1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="ext4" LABEL="" UUID="04ce9f16-a0a0-4db8-8719-1083a0d4f381"', # noqa E501 + 'NAME="/dev/sdap" MODEL="QEMU HARDDISK " SERIAL="42nd-scsi" SIZE="8G" TRAN="sata" VENDOR="ATA " HCTL="3:0:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/sdap2" MODEL="" SERIAL="" SIZE="4G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="btrfs" LABEL="btrfs-in-partition" UUID="55284332-af66-4ca0-9647-99d9afbe0ec5"', # noqa E501 + 'NAME="/dev/sdap1" MODEL="" SERIAL="" SIZE="4G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="vfat" LABEL="" UUID="8F05-D915"', # noqa E501 '' ]] err = [['']] @@ -1057,24 +1060,26 @@ def test_scan_disks_btrfs_in_partition(self): rc.append(0) expected_result = [[ # Note partitions entry within vda, consistent with cli prep. - Disk(name='vda', model=None, serial='serial-1', size=4194304, + Disk(name='/dev/vda', model=None, serial='serial-1', size=4194304, transport=None, vendor='0x1af4', hctl=None, type='disk', fstype='btrfs', label='btrfs-in-partition', uuid='55284332-af66-4ca0-9647-99d9afbe0ec5', parted=True, - root=False, partitions={'vda1': 'vfat', 'vda2': 'btrfs'}), - Disk(name='sda3', model='QEMU HARDDISK', serial='QM00005', + root=False, + partitions={'/dev/vda1': 'vfat', '/dev/vda2': 'btrfs'}), + Disk(name='/dev/sda3', model='QEMU HARDDISK', serial='QM00005', size=7025459, transport='sata', vendor='ATA', hctl='2:0:0:0', type='part', fstype='btrfs', label='rockstor_rockstor', uuid='355f53a4-24e1-465e-95f3-7c422898f542', parted=True, root=True, partitions={}) ], [ # Note sdap (42nd disk) hand crafted from above vda entry - Disk(name='sdap', model='QEMU HARDDISK', serial='42nd-scsi', + Disk(name='/dev/sdap', model='QEMU HARDDISK', serial='42nd-scsi', size=4194304, transport='sata', vendor='ATA', hctl='3:0:0:0', type='disk', fstype='btrfs', label='btrfs-in-partition', uuid='55284332-af66-4ca0-9647-99d9afbe0ec5', parted=True, - root=False, partitions={'sdap1': 'vfat', 'sdap2': 'btrfs'}), - Disk(name='sda3', model='QEMU HARDDISK', serial='QM00005', + root=False, + partitions={'/dev/sdap1': 'vfat', '/dev/sdap2': 'btrfs'}), + Disk(name='/dev/sda3', model='QEMU HARDDISK', serial='QM00005', size=7025459, transport='sata', vendor='ATA', hctl='2:0:0:0', type='part', fstype='btrfs', label='rockstor_rockstor', uuid='355f53a4-24e1-465e-95f3-7c422898f542', parted=True, @@ -1090,7 +1095,7 @@ def dyn_disk_serial_return(*args, **kwargs): # Entries only requred here if lsblk test data has no serial info: # eg for bcache, LUKS, mdraid, and virtio type devices. s_map = { - 'vda': 'serial-1' + '/dev/vda': 'serial-1' } # First argument in get_disk_serial() is device_name, key off this # for our dynamic mock return from s_map (serial map). @@ -1145,43 +1150,43 @@ def test_scan_disks_mdraid_sys_disk(self): """ out = [[ - 'NAME="sdb" MODEL="QEMU HARDDISK " SERIAL="md-serial-2" SIZE="8G" TRAN="sata" VENDOR="ATA " HCTL="3:0:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="sdb2" MODEL="" SERIAL="" SIZE="954M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="linux_raid_member" LABEL="rockstor:boot" UUID="fc9fc706-e831-6b14-591e-0bc5bb008681"', # noqa E501 - 'NAME="md126" MODEL="" SERIAL="" SIZE="954M" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="ext4" LABEL="" UUID="9df7d0f5-d109-4e84-a0f0-03a0cf0c03ad"', # noqa E501 - 'NAME="sdb3" MODEL="" SERIAL="" SIZE="1.4G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="linux_raid_member" LABEL="rockstor:swap" UUID="9ed64a0b-10d2-72f9-4120-0f662c5b5d66"', # noqa E501 - 'NAME="md125" MODEL="" SERIAL="" SIZE="1.4G" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="swap" LABEL="" UUID="1234d230-0aca-4b1d-9a10-c66744464d12"', # noqa E501 - 'NAME="sdb1" MODEL="" SERIAL="" SIZE="5.7G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="linux_raid_member" LABEL="rockstor:root" UUID="183a555f-3a90-3f7d-0726-b4109a1d78ba"', # noqa E501 - 'NAME="md127" MODEL="" SERIAL="" SIZE="5.7G" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="btrfs" LABEL="rockstor_rockstor" UUID="59800daa-fdfd-493f-837d-18e9b46bbb46"', # noqa E501 - 'NAME="sr0" MODEL="QEMU DVD-ROM " SERIAL="QM00001" SIZE="791M" TRAN="ata" VENDOR="QEMU " HCTL="0:0:0:0" TYPE="rom" FSTYPE="iso9660" LABEL="Rockstor 3 x86_64" UUID="2017-07-02-03-11-01-00"', # noqa E501 - 'NAME="sda" MODEL="QEMU HARDDISK " SERIAL="md-serial-1" SIZE="8G" TRAN="sata" VENDOR="ATA " HCTL="2:0:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="sda2" MODEL="" SERIAL="" SIZE="954M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="linux_raid_member" LABEL="rockstor:boot" UUID="fc9fc706-e831-6b14-591e-0bc5bb008681"', # noqa E501 - 'NAME="md126" MODEL="" SERIAL="" SIZE="954M" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="ext4" LABEL="" UUID="9df7d0f5-d109-4e84-a0f0-03a0cf0c03ad"', # noqa E501 - 'NAME="sda3" MODEL="" SERIAL="" SIZE="1.4G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="linux_raid_member" LABEL="rockstor:swap" UUID="9ed64a0b-10d2-72f9-4120-0f662c5b5d66"', # noqa E501 - 'NAME="md125" MODEL="" SERIAL="" SIZE="1.4G" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="swap" LABEL="" UUID="1234d230-0aca-4b1d-9a10-c66744464d12"', # noqa E501 - 'NAME="sda1" MODEL="" SERIAL="" SIZE="5.7G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="linux_raid_member" LABEL="rockstor:root" UUID="183a555f-3a90-3f7d-0726-b4109a1d78ba"', # noqa E501 - 'NAME="md127" MODEL="" SERIAL="" SIZE="5.7G" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="btrfs" LABEL="rockstor_rockstor" UUID="59800daa-fdfd-493f-837d-18e9b46bbb46"', # noqa E501 + 'NAME="/dev/sdb" MODEL="QEMU HARDDISK " SERIAL="md-serial-2" SIZE="8G" TRAN="sata" VENDOR="ATA " HCTL="3:0:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/sdb2" MODEL="" SERIAL="" SIZE="954M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="linux_raid_member" LABEL="rockstor:boot" UUID="fc9fc706-e831-6b14-591e-0bc5bb008681"', # noqa E501 + 'NAME="/dev/md126" MODEL="" SERIAL="" SIZE="954M" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="ext4" LABEL="" UUID="9df7d0f5-d109-4e84-a0f0-03a0cf0c03ad"', # noqa E501 + 'NAME="/dev/sdb3" MODEL="" SERIAL="" SIZE="1.4G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="linux_raid_member" LABEL="rockstor:swap" UUID="9ed64a0b-10d2-72f9-4120-0f662c5b5d66"', # noqa E501 + 'NAME="/dev/md125" MODEL="" SERIAL="" SIZE="1.4G" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="swap" LABEL="" UUID="1234d230-0aca-4b1d-9a10-c66744464d12"', # noqa E501 + 'NAME="/dev/sdb1" MODEL="" SERIAL="" SIZE="5.7G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="linux_raid_member" LABEL="rockstor:root" UUID="183a555f-3a90-3f7d-0726-b4109a1d78ba"', # noqa E501 + 'NAME="/dev/md127" MODEL="" SERIAL="" SIZE="5.7G" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="btrfs" LABEL="rockstor_rockstor" UUID="59800daa-fdfd-493f-837d-18e9b46bbb46"', # noqa E501 + 'NAME="/dev/sr0" MODEL="QEMU DVD-ROM " SERIAL="QM00001" SIZE="791M" TRAN="ata" VENDOR="QEMU " HCTL="0:0:0:0" TYPE="rom" FSTYPE="iso9660" LABEL="Rockstor 3 x86_64" UUID="2017-07-02-03-11-01-00"', # noqa E501 + 'NAME="/dev/sda" MODEL="QEMU HARDDISK " SERIAL="md-serial-1" SIZE="8G" TRAN="sata" VENDOR="ATA " HCTL="2:0:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/sda2" MODEL="" SERIAL="" SIZE="954M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="linux_raid_member" LABEL="rockstor:boot" UUID="fc9fc706-e831-6b14-591e-0bc5bb008681"', # noqa E501 + 'NAME="/dev/md126" MODEL="" SERIAL="" SIZE="954M" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="ext4" LABEL="" UUID="9df7d0f5-d109-4e84-a0f0-03a0cf0c03ad"', # noqa E501 + 'NAME="/dev/sda3" MODEL="" SERIAL="" SIZE="1.4G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="linux_raid_member" LABEL="rockstor:swap" UUID="9ed64a0b-10d2-72f9-4120-0f662c5b5d66"', # noqa E501 + 'NAME="/dev/md125" MODEL="" SERIAL="" SIZE="1.4G" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="swap" LABEL="" UUID="1234d230-0aca-4b1d-9a10-c66744464d12"', # noqa E501 + 'NAME="/dev/sda1" MODEL="" SERIAL="" SIZE="5.7G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="linux_raid_member" LABEL="rockstor:root" UUID="183a555f-3a90-3f7d-0726-b4109a1d78ba"', # noqa E501 + 'NAME="/dev/md127" MODEL="" SERIAL="" SIZE="5.7G" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="btrfs" LABEL="rockstor_rockstor" UUID="59800daa-fdfd-493f-837d-18e9b46bbb46"', # noqa E501 '']] err = [['']] rc = [0] expected_result = [[ - Disk(name='md127', model='[2] md-serial-1[0] md-serial-2[1] raid1', + Disk(name='/dev/md127', model='[2] md-serial-1[0] md-serial-2[1] raid1', # noqa E501 serial='183a555f:3a903f7d:0726b410:9a1d78ba', size=5976883, transport=None, vendor=None, hctl=None, type='raid1', fstype='btrfs', label='rockstor_rockstor', uuid='59800daa-fdfd-493f-837d-18e9b46bbb46', parted=False, root=True, partitions={}), - Disk(name='sda', model='QEMU HARDDISK', serial='md-serial-1', + Disk(name='/dev/sda', model='QEMU HARDDISK', serial='md-serial-1', size=8388608, transport='sata', vendor='ATA', hctl='2:0:0:0', type='disk', fstype='linux_raid_member', label=None, uuid=None, parted=True, root=False, - partitions={'sda3': 'linux_raid_member', - 'sda1': 'linux_raid_member'}), - Disk(name='sdb', model='QEMU HARDDISK', serial='md-serial-2', + partitions={'/dev/sda3': 'linux_raid_member', + '/dev/sda1': 'linux_raid_member'}), + Disk(name='/dev/sdb', model='QEMU HARDDISK', serial='md-serial-2', size=8388608, transport='sata', vendor='ATA', hctl='3:0:0:0', type='disk', fstype='linux_raid_member', label=None, uuid=None, parted=True, root=False, - partitions={'sdb3': 'linux_raid_member', - 'sdb1': 'linux_raid_member'}) + partitions={'/dev/sdb3': 'linux_raid_member', + '/dev/sdb1': 'linux_raid_member'}) ]] # No LUKS or bcache mocking necessary as none in test data. # Establish dynamic mock behaviour for get_disk_serial() @@ -1193,9 +1198,9 @@ def dyn_disk_serial_return(*args, **kwargs): # Entries only requred here if lsblk test data has no serial info: # eg for bcache, LUKS, mdraid, and virtio type devices. s_map = { - 'md125': 'fc9fc706:e8316b14:591e0bc5:bb008681', - 'md126': '9ed64a0b:10d272f9:41200f66:2c5b5d66', - 'md127': '183a555f:3a903f7d:0726b410:9a1d78ba' + '/dev/md125': 'fc9fc706:e8316b14:591e0bc5:bb008681', + '/dev/md126': '9ed64a0b:10d272f9:41200f66:2c5b5d66', + '/dev/md127': '183a555f:3a903f7d:0726b410:9a1d78ba' } # First argument in get_disk_serial() is device_name, key off this # for our dynamic mock return from s_map (serial map). @@ -1209,7 +1214,7 @@ def dyn_disk_serial_return(*args, **kwargs): self.mock_dyn_get_disk_serial.side_effect = dyn_disk_serial_return # Ensure we correctly mock our root_disk value away from file default # of sda as we now have a root_disk on md device. - self.mock_root_disk.return_value = 'md127' + self.mock_root_disk.return_value = '/dev/md127' # As we have an mdraid device of interest (the system disk) it's model # info field is used to present basic info on it's members serials: # We mock this as otherwise our wide scope run_command() mock breaks @@ -1260,39 +1265,39 @@ def test_scan_disks_intel_bios_raid_sys_disk(self): """ out = [[ - 'NAME="sdb" MODEL="TOSHIBA MK1652GS" SERIAL="Z8A9CAZUT" SIZE="149.1G" TRAN="sata" VENDOR="ATA " HCTL="1:0:0:0" TYPE="disk" FSTYPE="isw_raid_member" LABEL="" UUID=""', # noqa E501 - 'NAME="md126" MODEL="" SERIAL="" SIZE="149G" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="md126p3" MODEL="" SERIAL="" SIZE="146.6G" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="btrfs" LABEL="rockstor_rockstor00" UUID="1c59b842-5d08-4472-a731-c593ab0bff93"', # noqa E501 - 'NAME="md126p1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="ext4" LABEL="" UUID="40e4a91f-6b08-4ea0-b0d1-e43d145558b3"', # noqa E501 - 'NAME="md126p2" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="swap" LABEL="" UUID="43d2f3dc-38cd-49ef-9e18-be35297c1412"', # noqa E501 - 'NAME="sdc" MODEL="SAMSUNG HM160HI " SERIAL="S1WWJ9BZ408430" SIZE="149.1G" TRAN="sata" VENDOR="ATA " HCTL="3:0:0:0" TYPE="disk" FSTYPE="isw_raid_member" LABEL="" UUID=""', # noqa E501 - 'NAME="md126" MODEL="" SERIAL="" SIZE="149G" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="md126p3" MODEL="" SERIAL="" SIZE="146.6G" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="btrfs" LABEL="rockstor_rockstor00" UUID="1c59b842-5d08-4472-a731-c593ab0bff93"', # noqa E501 - 'NAME="md126p1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="ext4" LABEL="" UUID="40e4a91f-6b08-4ea0-b0d1-e43d145558b3"', # noqa E501 - 'NAME="md126p2" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="swap" LABEL="" UUID="43d2f3dc-38cd-49ef-9e18-be35297c1412"', # noqa E501 - 'NAME="sda" MODEL="WDC WD3200AAKS-7" SERIAL="WD-WMAV20342011" SIZE="298.1G" TRAN="sata" VENDOR="ATA " HCTL="0:0:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/sdb" MODEL="TOSHIBA MK1652GS" SERIAL="Z8A9CAZUT" SIZE="149.1G" TRAN="sata" VENDOR="ATA " HCTL="1:0:0:0" TYPE="disk" FSTYPE="isw_raid_member" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/md126" MODEL="" SERIAL="" SIZE="149G" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/md126p3" MODEL="" SERIAL="" SIZE="146.6G" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="btrfs" LABEL="rockstor_rockstor00" UUID="1c59b842-5d08-4472-a731-c593ab0bff93"', # noqa E501 + 'NAME="/dev/md126p1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="ext4" LABEL="" UUID="40e4a91f-6b08-4ea0-b0d1-e43d145558b3"', # noqa E501 + 'NAME="/dev/md126p2" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="swap" LABEL="" UUID="43d2f3dc-38cd-49ef-9e18-be35297c1412"', # noqa E501 + 'NAME="/dev/sdc" MODEL="SAMSUNG HM160HI " SERIAL="S1WWJ9BZ408430" SIZE="149.1G" TRAN="sata" VENDOR="ATA " HCTL="3:0:0:0" TYPE="disk" FSTYPE="isw_raid_member" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/md126" MODEL="" SERIAL="" SIZE="149G" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/md126p3" MODEL="" SERIAL="" SIZE="146.6G" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="btrfs" LABEL="rockstor_rockstor00" UUID="1c59b842-5d08-4472-a731-c593ab0bff93"', # noqa E501 + 'NAME="/dev/md126p1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="ext4" LABEL="" UUID="40e4a91f-6b08-4ea0-b0d1-e43d145558b3"', # noqa E501 + 'NAME="/dev/md126p2" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="swap" LABEL="" UUID="43d2f3dc-38cd-49ef-9e18-be35297c1412"', # noqa E501 + 'NAME="/dev/sda" MODEL="WDC WD3200AAKS-7" SERIAL="WD-WMAV20342011" SIZE="298.1G" TRAN="sata" VENDOR="ATA " HCTL="0:0:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 '']] err = [['']] rc = [0] expected_result = [[ - Disk(name='md126p3', + Disk(name='/dev/md126p3', model='[2] Z8A9CAZUT[0] S1WWJ9BZ408430[1] raid1', serial='a300e6b0:5d69eee6:98a2354a:0ba1e1eb', size=153721241, transport=None, vendor=None, hctl=None, type='md', fstype='btrfs', label='rockstor_rockstor00', uuid='1c59b842-5d08-4472-a731-c593ab0bff93', parted=True, root=True, partitions={}), - Disk(name='sda', model='WDC WD3200AAKS-7', + Disk(name='/dev/sda', model='WDC WD3200AAKS-7', serial='WD-WMAV20342011', size=312580505, transport='sata', vendor='ATA', hctl='0:0:0:0', type='disk', fstype=None, label=None, uuid=None, parted=False, root=False, partitions={}), - Disk(name='sdb', model='TOSHIBA MK1652GS', serial='Z8A9CAZUT', + Disk(name='/dev/sdb', model='TOSHIBA MK1652GS', serial='Z8A9CAZUT', size=156342681, transport='sata', vendor='ATA', hctl='1:0:0:0', type='disk', fstype='isw_raid_member', label=None, uuid=None, parted=False, root=False, partitions={}), - Disk(name='sdc', model='SAMSUNG HM160HI', serial='S1WWJ9BZ408430', + Disk(name='/dev/sdc', model='SAMSUNG HM160HI', serial='S1WWJ9BZ408430', # noqa E501 size=156342681, transport='sata', vendor='ATA', hctl='3:0:0:0', type='disk', fstype='isw_raid_member', label=None, uuid=None, parted=False, root=False, @@ -1311,9 +1316,9 @@ def dyn_disk_serial_return(*args, **kwargs): # Note in the following our md126p3 partition has the same serial # as it's base device. s_map = { - 'md126': 'a300e6b0:5d69eee6:98a2354a:0ba1e1eb', - 'md126p3': 'a300e6b0:5d69eee6:98a2354a:0ba1e1eb', - 'md127': 'a88a8eda:1e459751:3341ad9b:fe3031a0' + '/dev/md126': 'a300e6b0:5d69eee6:98a2354a:0ba1e1eb', + '/dev/md126p3': 'a300e6b0:5d69eee6:98a2354a:0ba1e1eb', + '/dev/md127': 'a88a8eda:1e459751:3341ad9b:fe3031a0' } # First argument in get_disk_serial() is device_name, key off this # for our dynamic mock return from s_map (serial map). @@ -1327,7 +1332,7 @@ def dyn_disk_serial_return(*args, **kwargs): self.mock_dyn_get_disk_serial.side_effect = dyn_disk_serial_return # Ensure we correctly mock our root_disk value away from file default # of sda as we now have a root_disk on md device. - self.mock_root_disk.return_value = 'md126' + self.mock_root_disk.return_value = '/dev/md126' # As we have an mdraid device of interest (the system disk) it's model # info field is used to present basic info on it's members serials: # We mock this as otherwise our wide scope run_command() mock breaks @@ -1372,47 +1377,47 @@ def test_scan_disks_intel_bios_raid_data_disk(self): """ # Out and expected_results have sda stripped for simplicity. out = [[ - 'NAME="sdd" MODEL="Extreme " SERIAL="AA010312161642210668" SIZE="29.2G" TRAN="usb" VENDOR="SanDisk " HCTL="6:0:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="sdd2" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="swap" LABEL="" UUID="422cc263-788e-4a74-a127-99695c380a2c"', # noqa E501 - 'NAME="sdd3" MODEL="" SERIAL="" SIZE="26.7G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="btrfs" LABEL="rockstor_rockstor" UUID="d030d7ee-4c85-4317-96bf-6ff766fec9ef"', # noqa E501 - 'NAME="sdd1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="ext4" LABEL="" UUID="35c11bd3-bba1-4869-8a51-1e6bfaec15a2"', # noqa E501 - 'NAME="sdb" MODEL="TOSHIBA MK1652GS" SERIAL="Z8A9CAZUT" SIZE="149.1G" TRAN="sata" VENDOR="ATA " HCTL="1:0:0:0" TYPE="disk" FSTYPE="isw_raid_member" LABEL="" UUID=""', # noqa E501 - 'NAME="md126" MODEL="" SERIAL="" SIZE="149G" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="md126p3" MODEL="" SERIAL="" SIZE="146.6G" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="btrfs" LABEL="rockstor_rockstor00" UUID="1c59b842-5d08-4472-a731-c593ab0bff93"', # noqa E501 - 'NAME="md126p1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="ext4" LABEL="" UUID="40e4a91f-6b08-4ea0-b0d1-e43d145558b3"', # noqa E501 - 'NAME="md126p2" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="swap" LABEL="" UUID="43d2f3dc-38cd-49ef-9e18-be35297c1412"', # noqa E501 - 'NAME="sdc" MODEL="SAMSUNG HM160HI " SERIAL="S1WWJ9BZ408430" SIZE="149.1G" TRAN="sata" VENDOR="ATA " HCTL="3:0:0:0" TYPE="disk" FSTYPE="isw_raid_member" LABEL="" UUID=""', # noqa E501 - 'NAME="md126" MODEL="" SERIAL="" SIZE="149G" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="md126p3" MODEL="" SERIAL="" SIZE="146.6G" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="btrfs" LABEL="rockstor_rockstor00" UUID="1c59b842-5d08-4472-a731-c593ab0bff93"', # noqa E501 - 'NAME="md126p1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="ext4" LABEL="" UUID="40e4a91f-6b08-4ea0-b0d1-e43d145558b3"', # noqa E501 - 'NAME="md126p2" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="swap" LABEL="" UUID="43d2f3dc-38cd-49ef-9e18-be35297c1412"', # noqa E501 + 'NAME="/dev/sdd" MODEL="Extreme " SERIAL="AA010312161642210668" SIZE="29.2G" TRAN="usb" VENDOR="SanDisk " HCTL="6:0:0:0" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/sdd2" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="swap" LABEL="" UUID="422cc263-788e-4a74-a127-99695c380a2c"', # noqa E501 + 'NAME="/dev/sdd3" MODEL="" SERIAL="" SIZE="26.7G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="btrfs" LABEL="rockstor_rockstor" UUID="d030d7ee-4c85-4317-96bf-6ff766fec9ef"', # noqa E501 + 'NAME="/dev/sdd1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="ext4" LABEL="" UUID="35c11bd3-bba1-4869-8a51-1e6bfaec15a2"', # noqa E501 + 'NAME="/dev/sdb" MODEL="TOSHIBA MK1652GS" SERIAL="Z8A9CAZUT" SIZE="149.1G" TRAN="sata" VENDOR="ATA " HCTL="1:0:0:0" TYPE="disk" FSTYPE="isw_raid_member" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/md126" MODEL="" SERIAL="" SIZE="149G" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/md126p3" MODEL="" SERIAL="" SIZE="146.6G" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="btrfs" LABEL="rockstor_rockstor00" UUID="1c59b842-5d08-4472-a731-c593ab0bff93"', # noqa E501 + 'NAME="/dev/md126p1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="ext4" LABEL="" UUID="40e4a91f-6b08-4ea0-b0d1-e43d145558b3"', # noqa E501 + 'NAME="/dev/md126p2" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="swap" LABEL="" UUID="43d2f3dc-38cd-49ef-9e18-be35297c1412"', # noqa E501 + 'NAME="/dev/sdc" MODEL="SAMSUNG HM160HI " SERIAL="S1WWJ9BZ408430" SIZE="149.1G" TRAN="sata" VENDOR="ATA " HCTL="3:0:0:0" TYPE="disk" FSTYPE="isw_raid_member" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/md126" MODEL="" SERIAL="" SIZE="149G" TRAN="" VENDOR="" HCTL="" TYPE="raid1" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/md126p3" MODEL="" SERIAL="" SIZE="146.6G" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="btrfs" LABEL="rockstor_rockstor00" UUID="1c59b842-5d08-4472-a731-c593ab0bff93"', # noqa E501 + 'NAME="/dev/md126p1" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="ext4" LABEL="" UUID="40e4a91f-6b08-4ea0-b0d1-e43d145558b3"', # noqa E501 + 'NAME="/dev/md126p2" MODEL="" SERIAL="" SIZE="2G" TRAN="" VENDOR="" HCTL="" TYPE="md" FSTYPE="swap" LABEL="" UUID="43d2f3dc-38cd-49ef-9e18-be35297c1412"', # noqa E501 '']] err = [['']] rc = [0] expected_result = [[ - Disk(name='sdc', model='SAMSUNG HM160HI', serial='S1WWJ9BZ408430', + Disk(name='/dev/sdc', model='SAMSUNG HM160HI', serial='S1WWJ9BZ408430', # noqa E501 size=156342681, transport='sata', vendor='ATA', hctl='3:0:0:0', type='disk', fstype='isw_raid_member', label=None, uuid=None, parted=False, root=False, partitions={}), - Disk(name='sdb', model='TOSHIBA MK1652GS', serial='Z8A9CAZUT', + Disk(name='/dev/sdb', model='TOSHIBA MK1652GS', serial='Z8A9CAZUT', size=156342681, transport='sata', vendor='ATA', hctl='1:0:0:0', type='disk', fstype='isw_raid_member', label=None, uuid=None, parted=False, root=False, partitions={}), - Disk(name='sdd3', model='Extreme', serial='AA010312161642210668', + Disk(name='/dev/sdd3', model='Extreme', serial='AA010312161642210668', # noqa E501 size=27996979, transport='usb', vendor='SanDisk', hctl='6:0:0:0', type='part', fstype='btrfs', label='rockstor_rockstor', uuid='d030d7ee-4c85-4317-96bf-6ff766fec9ef', parted=True, root=True, partitions={}), - Disk(name='md126', + Disk(name='/dev/md126', model='[2] Z8A9CAZUT[0] S1WWJ9BZ408430[1] raid1', serial='a300e6b0:5d69eee6:98a2354a:0ba1e1eb', size=153721241, transport=None, vendor=None, hctl=None, type='raid1', fstype='btrfs', label='rockstor_rockstor00', uuid='1c59b842-5d08-4472-a731-c593ab0bff93', parted=True, - root=False, partitions={'md126p3': 'btrfs'}) + root=False, partitions={'/dev/md126p3': 'btrfs'}) ]] # No LUKS or bcache mocking necessary as none in test data. @@ -1427,9 +1432,9 @@ def dyn_disk_serial_return(*args, **kwargs): # Note in the following our md126p3 partition has the same serial # as it's base device. s_map = { - 'md126': 'a300e6b0:5d69eee6:98a2354a:0ba1e1eb', - 'md126p3': 'a300e6b0:5d69eee6:98a2354a:0ba1e1eb', - 'md127': 'a88a8eda:1e459751:3341ad9b:fe3031a0' + '/dev/md126': 'a300e6b0:5d69eee6:98a2354a:0ba1e1eb', + '/dev/md126p3': 'a300e6b0:5d69eee6:98a2354a:0ba1e1eb', + '/dev/md127': 'a88a8eda:1e459751:3341ad9b:fe3031a0' } # First argument in get_disk_serial() is device_name, key off this # for our dynamic mock return from s_map (serial map). @@ -1442,7 +1447,7 @@ def dyn_disk_serial_return(*args, **kwargs): return 'missing-mock-serial-data-for-dev-{}'.format(args[0]) self.mock_dyn_get_disk_serial.side_effect = dyn_disk_serial_return # Ensure we correctly mock our root_disk value away from file default. - self.mock_root_disk.return_value = 'sdd' + self.mock_root_disk.return_value = '/dev/sdd' # As we have an mdraid device of interest (the data disk) it's model # info field is used to present basic info on it's members serials: # We mock this as otherwise our wide scope run_command() mock breaks @@ -1477,13 +1482,13 @@ def test_scan_disks_nvme_sys_disk(self): # Test data based on 2 data drives (sdb, sdb) and an nvme system drive # /dev/nvme0n1 as the base device. out = [[ - 'NAME="sdb" MODEL="WDC WD100EFAX-68" SERIAL="7PKNDX1C" SIZE="9.1T" TRAN="sata" VENDOR="ATA " HCTL="1:0:0:0" TYPE="disk" FSTYPE="btrfs" LABEL="Data" UUID="d2f76ce6-85fd-4615-b4f8-77e1b6a69c60"', # noqa E501 - 'NAME="sda" MODEL="WDC WD100EFAX-68" SERIAL="7PKP0MNC" SIZE="9.1T" TRAN="sata" VENDOR="ATA " HCTL="0:0:0:0" TYPE="disk" FSTYPE="btrfs" LABEL="Data" UUID="d2f76ce6-85fd-4615-b4f8-77e1b6a69c60"', # noqa E501 - 'NAME="nvme0n1" MODEL="INTEL SSDPEKKW128G7 " SERIAL="BTPY72910KCW128A" SIZE="119.2G" TRAN="" VENDOR="" HCTL="" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 - 'NAME="nvme0n1p3" MODEL="" SERIAL="" SIZE="7.8G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="swap" LABEL="" UUID="d33115d8-3d8c-4f65-b560-8ebf72d08fbc"', # noqa E501 - 'NAME="nvme0n1p1" MODEL="" SERIAL="" SIZE="200M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="vfat" LABEL="" UUID="53DC-1323"', # noqa E501 - 'NAME="nvme0n1p4" MODEL="" SERIAL="" SIZE="110.8G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="btrfs" LABEL="rockstor_rockstor00" UUID="4a05477f-cd4a-4614-b264-d029d98928ab"', # noqa E501 - 'NAME="nvme0n1p2" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="ext4" LABEL="" UUID="497a9eda-a655-4fc4-bad8-2d9aa8661980"', # noqa E501 + 'NAME="/dev/sdb" MODEL="WDC WD100EFAX-68" SERIAL="7PKNDX1C" SIZE="9.1T" TRAN="sata" VENDOR="ATA " HCTL="1:0:0:0" TYPE="disk" FSTYPE="btrfs" LABEL="Data" UUID="d2f76ce6-85fd-4615-b4f8-77e1b6a69c60"', # noqa E501 + 'NAME="/dev/sda" MODEL="WDC WD100EFAX-68" SERIAL="7PKP0MNC" SIZE="9.1T" TRAN="sata" VENDOR="ATA " HCTL="0:0:0:0" TYPE="disk" FSTYPE="btrfs" LABEL="Data" UUID="d2f76ce6-85fd-4615-b4f8-77e1b6a69c60"', # noqa E501 + 'NAME="/dev/nvme0n1" MODEL="INTEL SSDPEKKW128G7 " SERIAL="BTPY72910KCW128A" SIZE="119.2G" TRAN="" VENDOR="" HCTL="" TYPE="disk" FSTYPE="" LABEL="" UUID=""', # noqa E501 + 'NAME="/dev/nvme0n1p3" MODEL="" SERIAL="" SIZE="7.8G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="swap" LABEL="" UUID="d33115d8-3d8c-4f65-b560-8ebf72d08fbc"', # noqa E501 + 'NAME="/dev/nvme0n1p1" MODEL="" SERIAL="" SIZE="200M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="vfat" LABEL="" UUID="53DC-1323"', # noqa E501 + 'NAME="/dev/nvme0n1p4" MODEL="" SERIAL="" SIZE="110.8G" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="btrfs" LABEL="rockstor_rockstor00" UUID="4a05477f-cd4a-4614-b264-d029d98928ab"', # noqa E501 + 'NAME="/dev/nvme0n1p2" MODEL="" SERIAL="" SIZE="500M" TRAN="" VENDOR="" HCTL="" TYPE="part" FSTYPE="ext4" LABEL="" UUID="497a9eda-a655-4fc4-bad8-2d9aa8661980"', # noqa E501 '']] err = [['']] rc = [0] @@ -1493,29 +1498,29 @@ def test_scan_disks_nvme_sys_disk(self): rc.append(0) # Setup expected results expected_result = [[ - Disk(name='sda', model='WDC WD100EFAX-68', serial='7PKP0MNC', + Disk(name='/dev/sda', model='WDC WD100EFAX-68', serial='7PKP0MNC', size=9771050598, transport='sata', vendor='ATA', hctl='0:0:0:0', type='disk', fstype='btrfs', label='Data', uuid='d2f76ce6-85fd-4615-b4f8-77e1b6a69c60', parted=False, root=False, partitions={}), - Disk(name='sdb', model='WDC WD100EFAX-68', serial='7PKNDX1C', + Disk(name='/dev/sdb', model='WDC WD100EFAX-68', serial='7PKNDX1C', size=9771050598, transport='sata', vendor='ATA', hctl='1:0:0:0', type='disk', fstype='btrfs', label='Data', uuid='d2f76ce6-85fd-4615-b4f8-77e1b6a69c60', parted=False, root=False, partitions={}) ], [ - Disk(name='nvme0n1p4', model='INTEL SSDPEKKW128G7', + Disk(name='/dev/nvme0n1p4', model='INTEL SSDPEKKW128G7', serial='BTPY72910KCW128A', size=116182220, transport=None, vendor=None, hctl=None, type='part', fstype='btrfs', label='rockstor_rockstor00', uuid='4a05477f-cd4a-4614-b264-d029d98928ab', parted=True, root=True, partitions={}), - Disk(name='sda', model='WDC WD100EFAX-68', serial='7PKP0MNC', + Disk(name='/dev/sda', model='WDC WD100EFAX-68', serial='7PKP0MNC', size=9771050598, transport='sata', vendor='ATA', hctl='0:0:0:0', type='disk', fstype='btrfs', label='Data', uuid='d2f76ce6-85fd-4615-b4f8-77e1b6a69c60', parted=False, root=False, partitions={}), - Disk(name='sdb', model='WDC WD100EFAX-68', serial='7PKNDX1C', + Disk(name='/dev/sdb', model='WDC WD100EFAX-68', serial='7PKNDX1C', size=9771050598, transport='sata', vendor='ATA', hctl='1:0:0:0', type='disk', fstype='btrfs', label='Data', uuid='d2f76ce6-85fd-4615-b4f8-77e1b6a69c60', parted=False, @@ -1528,7 +1533,7 @@ def test_scan_disks_nvme_sys_disk(self): # get_bcache_device_type() # Ensure we correctly mock our root_disk value away from file default # of sda as we now have a root_disk on an nvme device. - self.mock_root_disk.return_value = 'nvme0n1' + self.mock_root_disk.return_value = '/dev/nvme0n1' # Iterate the test data sets for run_command running lsblk. for o, e, r, expected in zip(out, err, rc, expected_result): self.mock_run_command.return_value = (o, e, r)