Skip to content

Commit

Permalink
BUGFIX: attempt to umount all partitions on a disk before nuking.
Browse files Browse the repository at this point in the history
If we are unable to unmount the partitions, raise an error unless attribute 'halt_install_on_error=False'.
  • Loading branch information
bsanders committed May 21, 2019
1 parent c791f0d commit 5d4d61f
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 33 deletions.
74 changes: 59 additions & 15 deletions common/src/stack/storage-config/bin/initialize-storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,28 @@
## functions
##

# util wrapper around subprocess
def _exec(cmd, *args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', shlexsplit=False, **kwargs):
'''
wrapper around subprocess to default common arguments while allowing overriding.
'''
if shlexsplit:
cmd = shlex.split(cmd)
return subprocess.run(cmd, **kwargs, stdout=stdout, stderr=stderr, encoding=encoding)


# util to try to guess the truthiness of a string
def str2bool(s):
"""Converts an on/off, yes/no, true/false string to
True/False."""
if type(s) == bool:
return s
if s and s.upper() in [ 'ON', 'YES', 'Y', 'TRUE', '1' ]:
return True
else:
return False


def nukeLVM(volumegroup):
for (display, remove) in [
('lvdisplay --all -c', 'lvremove --force'),
Expand All @@ -48,6 +70,7 @@ def nukeLVM(volumegroup):
stdout = FNULL,
stderr = subprocess.STDOUT)


def stopMD():
#
# we need to stop all MDs before we can remove them
Expand All @@ -63,34 +86,51 @@ def nukeMD(part):
stderr = subprocess.STDOUT)


def nukeDisk(disk):
if 'disklabel' in attributes:
disklabel = attributes['disklabel']
else:
disklabel = 'gpt'
def nukeDisk(disk, disklabel, halt_on_error):
'''
destroy the master boot record (via dd),
create a new partition label (msdos/gpt) based on the 'disklabel' attribute
attempts to unmount any partitions on that disk that may be mounted
'''

# unmount everything on the disk first.
# NOTE: sles11 does not have the version of umount that allows recursive `umount -A /dev/some/`
# so instead, iterate over partitions per disk, umounting parts only if mounted.

subproc_args = {'stdout': subprocess.PIPE, 'stderr': subprocess.STDOUT, 'check': halt_on_error}

cmd = f'lsblk --raw --noheadings -o name,mountpoint /dev/{disk}'
proc = _exec(cmd, shlexsplit=True, **subproc_args)

cmd = 'umount -f /dev/{}'
for line in proc.stdout.splitlines():
line = line.split()

if len(line) == 2:
_exec(cmd.format(f'{line[0]}'), shlexsplit=True, **subproc_args)

#
# Clear out the master boot record of the drive
#
cmd = 'dd if=/dev/zero of=/dev/%s count=512 bs=1' % disk
subprocess.call(shlex.split(cmd),
stdout = FNULL, stderr = subprocess.STDOUT)
_exec(cmd, shlexsplit=True, **subproc_args)

# install new partition table
cmd = 'parted -s /dev/%s mklabel %s' % (disk, disklabel)
subprocess.call(shlex.split(cmd),
stdout = FNULL, stderr = subprocess.STDOUT)

return
_exec(cmd, shlexsplit=True, **subproc_args)

##
## MAIN
##

# get info about attributes

if 'nukecontroller' in attributes:
nukecontroller = attributes['nukecontroller']
else:
nukecontroller = 'false'

halt_on_error = str2bool(attributes.get('halt_install_on_error', True))
disklabel = attributes.get('disklabel', 'gpt')

if 'nukedisks' in attributes:
n = attributes['nukedisks']

Expand Down Expand Up @@ -199,5 +239,9 @@ def nukeDisk(disk):
#
for disk in disks:
if disk['nuke']:
nukeDisk(disk['device'])

try:
nukeDisk(disk['device'], disklabel, halt_on_error)
except subprocess.CalledProcessError as e:
print(' '.join(e.cmd))
print(f'output: {e.stdout}')
sys.exit(1)
4 changes: 2 additions & 2 deletions common/src/stack/storage-config/lib/stacki_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,12 +320,12 @@ def get_sles11_media_type(dev_name):
arr = l.strip().split()

# line 0
if len(arr) == 1 and arr[0] == 'partition':
if len(arr) == 1 and arr[0] == 'partition:':
blk_type = 'part'
continue

# line 0
if len(arr) == 1 and arr[0] == 'disk':
if len(arr) == 1 and arr[0] == 'disk:':
blk_type = 'disk'
continue

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,20 @@
unset PYTHONPATH
export LD_LIBRARY_PATH=/opt/stack/lib

# util func to pause the install, alert the console user, alert the MQ
function halt_install {
console_err_msg=$1
mq_health_msg=$2

touch /tmp/wait
echo $console_err_msg
while [ -f /tmp/wait ]
do
sleep 1
/opt/stack/bin/smq-publish -chealth $mq_health_msg
done
}

/opt/stack/bin/stacki-profile.py

#
Expand Down Expand Up @@ -54,23 +68,22 @@ echo "tracker = ${FRONTEND}:3825" > /tmp/stack.conf

# nuke the disks, if appropriate
/opt/stack/bin/initialize-storage.py
if [ $? -ne 0 ]
then
halt_install "Unable to initialize internal storage configuration." \
'{"state": "nukedisk failed - check console or reinstall with halt_install_on_error=False"}'
fi

#
# configure the hardware disk array controller first
#
/opt/stack/bin/configure-controllers.py
if [ $? -ne 0 ]
then
touch /tmp/wait
echo "Unable to complete storage controller configuration."
while [ -f /tmp/wait ]
do
sleep 1
/opt/stack/bin/smq-publish -chealth '{"state": "controller config failed - check console or reinstall with halt_install_on_error=False"}'
done
halt_install "Unable to complete storage controller configuration." \
'{"state": "controller config failed - check console or reinstall with halt_install_on_error=False"}'
fi


udevadm settle --timeout=60

# NOTE: we initialize storage twice in RHEL, so do the same thing here, too
Expand All @@ -80,6 +93,11 @@ udevadm settle --timeout=60
# master boot record on a LUN may be corrupted and require initialization.

/opt/stack/bin/initialize-storage.py
if [ $? -ne 0 ]
then
halt_install "Unable to initialize internal storage configuration after storage controller config." \
'{"state": "nukedisk failed - check console or reinstall with halt_install_on_error=False"}'
fi

#
# then configure the partitions
Expand All @@ -90,17 +108,11 @@ udevadm settle --timeout=60
/opt/stack/bin/output-bootloader.py > /tmp/bootloader.xml

# give ourselves the ability to hold the installation prior to the start of yast
#
grep stack-debug /proc/cmdline 2>&1 > /dev/null
if [ $? -eq 0 ]
then
touch /tmp/wait
echo "Stacki debug wait loop - remove /tmp/wait to continue"
while [ -f /tmp/wait ]
do
sleep 1
/opt/stack/bin/smq-publish -chealth '{"state": "install wait"}'
done
halt_install "Stacki debug wait loop - remove /tmp/wait to continue" \
'{"state": "install wait"}'
fi

if [[ -n $YUMSERVER ]]
Expand Down

0 comments on commit 5d4d61f

Please sign in to comment.