microstack/snap/hooks/remove

80 lines
3.2 KiB
Python
Executable File

#!/usr/bin/env python3
import os
import sys
import logging
from subprocess import check_call, check_output, call, run
from pyroute2 import netns
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
if __name__ == '__main__':
# Work around the lack of modified LD_LIBRARY_PATH and PATH variables with
# snap-specific content.
snap_dir = os.environ['SNAP']
snap_libs = (f'{snap_dir}/lib:{snap_dir}/usr/lib:'
f'{snap_dir}/lib/x86_64-linux-gnu:'
f'{snap_dir}/usr/lib/x86_64-linux-gnu')
os.environ['LD_LIBRARY_PATH'] = snap_libs
check_call(['snapctl', 'start', 'microstack.ovsdb-server'])
check_call(['snapctl', 'start', 'microstack.ovs-vswitchd'])
logging.info('Attempting to remove br-ex.')
check_call(['ovs-vsctl', '--if-exists', 'del-br', 'br-ex'])
check_call(['snapctl', 'stop', 'microstack.ovsdb-server'])
check_call(['snapctl', 'stop', 'microstack.ovs-vswitchd'])
for ns in netns.listnetns():
if ns.startswith('ovnmeta-'):
logging.info(f'Removing the {ns} network namespace.')
netns.remove(ns)
# Need to expose targets prior to starting iscsid in order to properly log out
# of iSCSI sessions.
check_call(['snapctl', 'start', 'microstack.target'])
check_call(['snapctl', 'start', 'microstack.iscsid'])
check_call(['sync'])
# Assuming the QEMU processes have already been killed by snapd,
# log out of all targets prior to removing the snap to clean up
# the kernel state.
# TODO: be more selective about logging out since there may be sessions
# unrelated to MicroStack in the kernel.
# TODO: also clean up block devices by writing to
# /sys/class/block/<dev>/device/delete since those do not get deleted on
# session logout.
logging.info('Attempting to remove iscsi sessions from the kernel.')
res = run(['iscsiadm', '-m', 'node', '-u'])
# ISCSI_ERR_NO_OBJS_FOUND
if res.returncode == 21:
logging.debug('No iscsi sessions were found.')
elif res.returncode == 0:
logging.debug('Successfully logged the existing iscsi sessions out.')
else:
# Albeit this is an error condition we cannot do much in the remove
# hook to fix this besides logging since snapd does not stop the
# snap removal on error in the remove hook.
logging.error('Unexpected error code received from iscsiadm: '
f'{res.returncode}')
check_call(['snapctl', 'stop', 'microstack.iscsid'])
check_call(['snapctl', 'stop', 'microstack.target'])
# File-backed LVM resource cleanup (if present).
loop_file = f'{os.environ["SNAP_COMMON"]}/cinder-lvm.img'
allocated_loop_dev = check_output(
f'losetup -j {loop_file} | cut -d ":" -f 1', shell=True
).decode('utf-8').strip()
if allocated_loop_dev:
cinder_lvm_vg = check_output([
'snapctl', 'get', 'config.cinder.lvm-backend-volume-group']
).strip()
if not call(['vgdisplay', cinder_lvm_vg]):
check_call(['vgremove', '-f', cinder_lvm_vg])
if not call(['pvdisplay', allocated_loop_dev]):
check_call(['pvremove', '-f', allocated_loop_dev])
check_call(['losetup', '-d', allocated_loop_dev])