Skip to content

Commit

Permalink
use by-id disk names in db and consequent btrfs commands rockstor#1320
Browse files Browse the repository at this point in the history
Initial conversion of disk name entries in db from 'sda' type to
those created by udev in the /dev/disk/by-id directory. Also
involves changing hard coded paths in low level btrfs functions.
  • Loading branch information
phillxnet committed Jun 24, 2016
1 parent 1312b1a commit aeba752
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 14 deletions.
24 changes: 14 additions & 10 deletions src/rockstor/fs/btrfs.py
Expand Up @@ -57,7 +57,7 @@ def add_pool(pool, disks):
"""
pool is a btrfs filesystem.
"""
disks_fp = ['/dev/' + d for d in disks]
disks_fp = ['/dev/disk/by-id/' + d for d in disks]
cmd = [MKFS_BTRFS, '-f', '-d', pool.raid, '-m', pool.raid, '-L',
pool.name, ]
cmd.extend(disks_fp)
Expand All @@ -67,7 +67,8 @@ def add_pool(pool, disks):


def get_pool_info(disk):
cmd = [BTRFS, 'fi', 'show', '/dev/%s' % disk]
# cmd = [BTRFS, 'fi', 'show', '/dev/%s' % disk]
cmd = [BTRFS, 'fi', 'show', '/dev/disk/by-id/%s' % disk]
o, e, rc = run_command(cmd)
pool_info = {'disks': [],}
for l in o:
Expand Down Expand Up @@ -148,7 +149,7 @@ def mount_root(pool):
raise Exception('Cannot mount Pool(%s) as it has no disks in it.' % pool.name)
last_device = pool.disk_set.last()
for device in pool.disk_set.all():
mnt_device = ('/dev/%s' % device.name)
mnt_device = ('/dev/disk/by-id/%s' % device.name)
if (os.path.exists(mnt_device)):
mnt_cmd = [MOUNT, mnt_device, root_pool_mnt, ]
if (len(mnt_options) > 0):
Expand Down Expand Up @@ -232,15 +233,15 @@ def mount_share(share, mnt_pt):
if (is_mounted(mnt_pt)):
return
mount_root(share.pool)
pool_device = ('/dev/%s' % share.pool.disk_set.first().name)
pool_device = ('/dev/disk/by-id/%s' % share.pool.disk_set.first().name)
subvol_str = 'subvol=%s' % share.subvol_name
create_tmp_dir(mnt_pt)
mnt_cmd = [MOUNT, '-t', 'btrfs', '-o', subvol_str, pool_device, mnt_pt]
return run_command(mnt_cmd)


def mount_snap(share, snap_name, snap_mnt=None):
pool_device = ('/dev/%s' % share.pool.disk_set.first().name)
pool_device = ('/dev/disk/by-id/%s' % share.pool.disk_set.first().name)
share_path = ('%s%s' % (DEFAULT_MNT_DIR, share.name))
rel_snap_path = ('.snapshots/%s/%s' % (share.name, snap_name))
snap_path = ('%s%s/%s' %
Expand Down Expand Up @@ -782,17 +783,20 @@ def device_scan():

def btrfs_uuid(disk):
"""return uuid of a btrfs filesystem"""
o, e, rc = run_command([BTRFS, 'filesystem', 'show', '/dev/%s' % disk])
o, e, rc = run_command(
[BTRFS, 'filesystem', 'show', '/dev/disk/by-id/%s' % disk])
return o[0].split()[3]


def btrfs_label(disk):
o, e, rc = run_command([BTRFS, 'filesystem', 'label', '/dev/%s' % disk])
o, e, rc = run_command(
[BTRFS, 'filesystem', 'label', '/dev/disk/by-id/%s' % disk])
return o[0]


def btrfs_importable(disk):
o, e, rc = run_command([BTRFS, 'check', '/dev/%s' % disk], throw=False)
o, e, rc = run_command([BTRFS, 'check', '/dev/disk/by-id/%s' % disk],
throw=False)
if (rc == 0):
return True
return False
Expand Down Expand Up @@ -1100,13 +1104,13 @@ def scan_disks(min_size):

def wipe_disk(disk):
# todo candidate for move to system/osi as not btrfs related
disk = ('/dev/%s' % disk)
disk = ('/dev/disk/by-id/%s' % disk)
return run_command([WIPEFS, '-a', disk])


def blink_disk(disk, total_exec, read, sleep):
# todo candidate for move to system/osi as not btrfs related
DD_CMD = [DD, 'if=/dev/%s' % disk, 'of=/dev/null', 'bs=512',
DD_CMD = [DD, 'if=/dev/disk/by-id/%s' % disk, 'of=/dev/null', 'bs=512',
'conv=noerror']
p = subprocess.Popen(DD_CMD, shell=False, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
Expand Down
26 changes: 22 additions & 4 deletions src/rockstor/storageadmin/views/disk.py
Expand Up @@ -30,7 +30,8 @@
from django.conf import settings
import rest_framework_custom as rfc
from system import smart
from system.osi import set_disk_spindown, enter_standby
from system.osi import set_disk_spindown, enter_standby, get_dev_byid_name, \
get_devname
from copy import deepcopy
import uuid
import json
Expand Down Expand Up @@ -74,10 +75,14 @@ def _update_disk_state():
# N.B. do not optimize by re-using uuid index as this could lead
# to a non refreshed webui acting upon an entry that is different
# from that shown to the user.
#todo - re-address in light of new by-id names which are much longer
#todo - so will cause collision, and hence false positive on missing
#todo - by having 32 char long name flag, ie add 'missing-' to this.
do.name = str(uuid.uuid4()).replace('-', '') # 32 chars long
# Delete duplicate or fake by serial number db disk entries.
# It makes no sense to save fake serial number drives between scans
# as on each scan the serial number is re-generated anyway.
# N.B. serial number len 48 assumed fake as uuid4 from scan_disks.
if (do.serial in serial_numbers_seen) or (len(do.serial) == 48):
logger.info('Deleting duplicate or fake (by serial) Disk db '
'entry. Serial = %s' % do.serial)
Expand All @@ -100,15 +105,21 @@ def _update_disk_state():
for d in disks:
# start with an empty disk object
dob = None
# 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 = get_dev_byid_name(d.name, True)
logger.debug('Converting %s to by-id of %s' % (d.name, byid_disk_name))
# If the db has an entry with this disk's serial number then
# use this db entry and update the device name from our recent scan.
if (Disk.objects.filter(serial=d.serial).exists()):
dob = Disk.objects.get(serial=d.serial)
dob.name = d.name
#dob.name = d.name
dob.name = byid_disk_name
else:
# We have an assumed new disk entry as no serial match in db.
# Build a new entry for this disk.
dob = Disk(name=d.name, serial=d.serial)
#dob = Disk(name=d.name, serial=d.serial)
dob = Disk(name=byid_disk_name, serial=d.serial)
# Update the db disk object (existing or new) with our scanned info
dob.size = d.size
dob.parted = d.parted
Expand Down Expand Up @@ -212,6 +223,11 @@ def _update_disk_state():
# find all the not offline db entries
if (not do.offline):
# We have an attached disk db entry
# Since our Disk.name model now uses by-id we need to convert
# this back to a /dev/vd*, /dev/md*, /dev/mmcblk* type name
# as a cheap evaluation of it's type ie virtio, md, or sdcard.
bus_based_devname = get_devname('/dev/disk/by-id/%s' % do.name)
logger.debug('bus-type-name for %s = %s' % (do.name, bus_based_devname))
if (re.match('vd|md|mmcblk', do.name) is not None):
# Virtio disks (named vd*), md devices (named md*), and
# an sdcard reader that provides devs named mmcblk* have
Expand All @@ -222,8 +238,10 @@ def _update_disk_state():
# try to establish smart availability and status and update db
try:
# for non ata/sata drives
#do.smart_available, do.smart_enabled = smart.available(
# do.name, do.smart_options)
do.smart_available, do.smart_enabled = smart.available(
do.name, do.smart_options)
bus_based_devname, do.smart_options)
except Exception, e:
logger.exception(e)
do.smart_available = do.smart_enabled = False
Expand Down

0 comments on commit aeba752

Please sign in to comment.