import os import requests from subprocess import ( check_call, check_output ) from charmhelpers.core import host from charms.reactive import ( when, when_not, set_state, remove_state, endpoint_from_flag, hook, ) from charmhelpers.fetch import ( apt_install, apt_update, apt_purge, apt_autoremove, import_key ) from charmhelpers.core.hookenv import ( resource_get ) from charms.layer import status KATA_PACKAGES = [ 'kata-runtime', 'kata-proxy', 'kata-shim' ] @when_not('kata.installed') @when_not('endpoint.untrusted.departed') def install_kata(): """ Install the Kata container runtime. :returns: None """ dist = host.lsb_release() release = '{}_{}'.format( dist['DISTRIB_ID'], dist['DISTRIB_RELEASE'] ) arch = check_output(['arch']).decode().strip() archive = resource_get('kata-archive') if not archive or os.path.getsize(archive) == 0: status.maintenance('Installing Kata via apt') gpg_key = requests.get( 'http://download.opensuse.org/repositories/home:/katacontainers:/' 'releases:/{}:/master/x{}/Release.key'.format(arch, release)).text import_key(gpg_key) with open('/etc/apt/sources.list.d/kata-containers.list', 'w') as f: f.write( 'deb http://download.opensuse.org/repositories/home:/' 'katacontainers:/releases:/{}:/master/x{}/ /' .format(arch, release) ) apt_update() apt_install(KATA_PACKAGES) else: status.maintenance('Installing Kata via resource') unpack = '/tmp/kata-debs' if not os.path.isdir(unpack): os.makedirs(unpack, exist_ok=True) check_call(['tar', '-xvf', archive, '-C', unpack]) check_call('apt-get install -y {}/*.deb'.format(unpack), shell=True) status.active('Kata runtime available') set_state('kata.installed') @when('endpoint.untrusted.departed') def purge_kata(): """ Purge Kata containers. :return: None """ status.maintenance('Purging Kata') apt_purge(KATA_PACKAGES, fatal=False) source = '/etc/apt/sources.list.d/kata-containers.list' if os.path.isfile(source): os.remove(source) apt_autoremove() remove_state('kata.installed') @when('kata.installed') @when('endpoint.untrusted.joined') @when_not('endpoint.untrusted.departed') def publish_config(): """ Pass configuration over the interface. :return: None """ endpoint = endpoint_from_flag('endpoint.untrusted.joined') endpoint.set_config( name='kata', binary_path='/usr/bin/kata-runtime' ) @hook('pre-series-upgrade') def pre_series_upgrade(): """Set status during series upgrade.""" status.blocked('Series upgrade in progress') @hook('post-series-upgrade') def post_series_upgrade(): """Reset status to active after series upgrade.""" status.active('Kata runtime available')