#!/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//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])