def purge_containerd(): """ Purge Containerd from the cluster. :return: None """ status_set('maintenance', 'Removing containerd from principal') host.service_stop('containerd.service') apt_purge('containerd', fatal=True) if is_state('containerd.nvidia.ready'): apt_purge(NVIDIA_PACKAGES, fatal=True) sources = [ '/etc/apt/sources.list.d/cuda.list', '/etc/apt/sources.list.d/nvidia-container-runtime.list' ] for f in sources: if os.path.isfile(f): os.remove(f) apt_autoremove(purge=True, fatal=True) remove_state('containerd.ready') remove_state('containerd.installed') remove_state('containerd.nvidia.ready') remove_state('containerd.nvidia.checked') remove_state('containerd.nvidia.available')
def purge(packages): """Purge one or more deb packages from the system""" fetch.apt_purge(packages, fatal=True) store = unitdata.kv() store.unsetrange(packages, prefix='apt.install_queue.') for package in packages: reactive.remove_state('apt.installed.{}'.format(package))
def install_nodejs(): """ Installs defined node runtime Emits: nodejs.available: Emitted once the runtime has been installed """ remove_state('nodejs.available') hookenv.status_set('maintenance', 'Installing Node.js {}'.format(config['node-version'])) if os.path.isfile('/etc/apt/sources.list.d/nodesource.list'): os.remove('/etc/apt/sources.list.d/nodesource.list') url = node_version_map[config['node-version']]['remote'] hookenv.status_set('maintenance', 'Using Node.js Repo: {}'.format(url)) try: curl_cmd = ['curl', '-sl', url] bash_cmd = ['bash', '-e'] pipe1 = Popen(curl_cmd, stdout=PIPE) pipe2 = Popen(bash_cmd, stdin=pipe1.stdout, stdout=PIPE) pipe1.stdout.close() output = pipe2.communicate()[0] hookenv.log('Added nodesource archive, output: {}'.format(output), 'debug') except: hookenv.log('Problem installing: {}'.format(output), 'debug') sys.exit(1) apt_purge(['nodejs']) apt_install(['nodejs']) hookenv.status_set('maintenance', 'Installing Node.js completed.') hookenv.status_set('active', 'Node.js is ready!') set_state('nodejs.available')
def install_packages(): c = config() if c.changed('source') or c.changed('key'): add_source(c.get('source'), c.get('key')) apt_update(fatal=True) if is_container(): PACKAGES.remove('ntp') # NOTE: just use full package list if we're in an upgrade # config-changed execution pkgs = (PACKAGES if upgrade_available() else filter_installed_packages(PACKAGES)) if pkgs: status_set('maintenance', 'Installing radosgw packages') if ('apache2' in pkgs): # NOTE(lourot): Apache's default config makes it listen on port 80, # which will prevent HAProxy from listening on that same port. We # use Apache in this setup however for SSL (different port). We # need to let Apache free port 80 before we can install HAProxy # otherwise HAProxy will crash. See lp:1904411 log('Installing Apache') apt_install(['apache2'], fatal=True) disable_unused_apache_sites() apt_install(pkgs, fatal=True) pkgs = filter_missing_packages(APACHE_PACKAGES) if pkgs: apt_purge(pkgs)
def purge_containerd(): """ Purge Containerd from the cluster. :return: None """ status.maintenance('Removing containerd from principal') host.service_stop('containerd.service') apt_unhold(CONTAINERD_PACKAGE) apt_purge(CONTAINERD_PACKAGE, fatal=True) if is_state('containerd.nvidia.ready'): nvidia_packages = config('nvidia_apt_packages').split() apt_purge(nvidia_packages, fatal=True) sources = ['/etc/apt/sources.list.d/nvidia.list'] for f in sources: if os.path.isfile(f): os.remove(f) apt_autoremove(purge=True, fatal=True) remove_state('containerd.ready') remove_state('containerd.installed') remove_state('containerd.nvidia.ready') remove_state('containerd.nvidia.checked') remove_state('containerd.nvidia.available') remove_state('containerd.version-published')
def remove_plugin_config(): """Called when a dashboard plugin is leaving. This is necessary so that the packages that the plugin asked to install are removed and any conflicting packages are restored and the config updated. This ensures that when changing plugins the system isn't left in a broken state. """ resolve_CONFIGS() rid = juju_relation_id() runit = juju_remote_unit() pkg_data = get_plugin_packages_from_kv(rid, runit) changed = False if pkg_data['install_packages']: remove_packages = filter_missing_packages(pkg_data['install_packages']) if remove_packages: status_set('maintenance', 'Removing packages') apt_purge(remove_packages, fatal=True) apt_autoremove(purge=True, fatal=True) changed = True if pkg_data['conflicting_packages']: install_packages = filter_installed_packages( pkg_data['conflicting_packages']) if install_packages: status_set('maintenance', 'Installing packages') apt_install(install_packages, fatal=True) changed = True if changed: log("Package installation/purge detected, restarting services", "INFO") for s in services(): service_restart(s) CONFIGS.write(LOCAL_SETTINGS)
def toggle_docker_daemon_source(): ''' A disruptive toggleable action which will swap out the installed docker daemon for the configured source. If true, installs the latest available docker from the upstream PPA. Else installs docker from universe. ''' # this returns a list of packages not currently installed on the system # based on the parameters input. Use this to check if we have taken # prior action against a docker deb package. packages = filter_installed_packages(['docker.io', 'docker-engine']) if 'docker.io' in packages and 'docker_engine' in packages: # we have not reached installation phase, return until # we can reasonably re-test this scenario hookenv.log('Neither docker.io nor docker-engine are installed. Noop.') return install_ppa = config('install_from_upstream') # Remove the inverse package from what is declared. Only take action if # we meet having a package installed. if install_ppa and 'docker.io' not in packages: host.service_stop('docker') hookenv.log('Removing docker.io package.') apt_purge('docker.io') remove_state('docker.ready') remove_state('docker.available') elif not install_ppa and 'docker-engine' not in packages: host.service_stop('docker') hookenv.log('Removing docker-engine package.') apt_purge('docker-engine') remove_state('docker.ready') remove_state('docker.available') else: hookenv.log('Not touching packages.')
def neutron_plugin_changed(): settings = relation_get() if 'metadata-shared-secret' in settings: apt_update() apt_install('nova-api-metadata', fatal=True) else: apt_purge('nova-api-metadata', fatal=True) CONFIGS.write(NOVA_CONF)
def install_packages(): add_source(config('source'), config('key')) apt_update(fatal=True) pkgs = filter_installed_packages(PACKAGES) if pkgs: status_set('maintenance', 'Installing radosgw packages') apt_install(PACKAGES, fatal=True) apt_purge(APACHE_PACKAGES)
def stop(): # The pcmk.delete_node handles several known failure modes so # failure_is_fatal=True actually helps as it causes retries. node = get_hostname() pcmk.set_node_status_to_maintenance(node) pcmk.delete_node(node, failure_is_fatal=True) apt_purge(['corosync', 'pacemaker'], fatal=True)
def neutron_plugin_changed(): enable_nova_metadata, _ = nova_metadata_requirement() if enable_nova_metadata: apt_update() apt_install(filter_installed_packages(['nova-api-metadata']), fatal=True) else: apt_purge('nova-api-metadata', fatal=True) CONFIGS.write(NOVA_CONF)
def config_changed(): configure_deferred_restarts(deferrable_services()) if not config('action-managed-upgrade'): if openstack_upgrade_available(NEUTRON_COMMON): status_set('maintenance', 'Running openstack upgrade') do_openstack_upgrade(CONFIGS) update_nrpe_config() module_settings = config('kernel-modules') if module_settings: if is_container(): log("Cannot load modules inside of a container", level=WARNING) else: for module in module_settings.split(): try: modprobe(module) except Exception: message = "Failed to load kernel module '%s'" % module log(message, level=WARNING) sysctl_settings = config('sysctl') if sysctl_settings: if is_container(): log("Cannot create sysctls inside of a container", level=WARNING) else: create_sysctl(sysctl_settings, '/etc/sysctl.d/50-quantum-gateway.conf') # Re-run joined hooks as config might have changed for r_id in relation_ids('amqp'): amqp_joined(relation_id=r_id) for r_id in relation_ids('amqp-nova'): amqp_nova_joined(relation_id=r_id) if valid_plugin(): CONFIGS.write_all() configure_ovs() configure_apparmor() else: message = 'Please provide a valid plugin config' log(message, level=ERROR) status_set('blocked', message) sys.exit(1) if config('plugin') == 'n1kv': if config('enable-l3-agent'): status_set('maintenance', 'Installing apt packages') apt_install(filter_installed_packages('neutron-l3-agent')) else: apt_purge('neutron-l3-agent') # Setup legacy ha configurations update_legacy_ha_files() # Disable nova metadata if possible, if disable_nova_metadata(): remove_legacy_nova_metadata() if disable_neutron_lbaas(): remove_legacy_neutron_lbaas()
def test_purges_apt_packages_nofatal(self, log, mock_call): packages = ['foo', 'bar'] fetch.apt_purge(packages) log.assert_called() mock_call.assert_called_with( ['apt-get', '--assume-yes', 'purge', 'foo', 'bar'], env=getenv({'DEBIAN_FRONTEND': 'noninteractive'}))
def purge_packages(pkg_list): status_set('maintenance', 'Purging unused apt packages') purge_pkgs = [] required_packages = determine_packages() for pkg in pkg_list: if pkg not in required_packages: purge_pkgs.append(pkg) if purge_pkgs: apt_purge(purge_pkgs, fatal=True)
def neutron_plugin_changed(): enable_nova_metadata, _ = nova_metadata_requirement() if enable_nova_metadata: apt_update() apt_install(filter_installed_packages(['nova-api-metadata']), fatal=True) else: apt_purge('nova-api-metadata', fatal=True) service_restart_handler(default_service='nova-compute') CONFIGS.write(NOVA_CONF)
def pre_write(self): # Always remove? for pkg in ['libpam-ccreds', 'libpam-cracklib']: log("Purging package '%s'" % pkg, level=DEBUG), apt_purge(pkg) apt_update(fatal=True) for pkg in ['libpam-passwdqc']: log("Installing package '%s'" % pkg, level=DEBUG), apt_install(pkg)
def puppet_version_config_changed(): '''React to pin-puppet version changed ''' p = PuppetConfigs() # Reinstall puppet to specified version hookenv.status_set('maintenance', 'Re-installing puppet.') if config.previous('pin-puppet') != config['pin-puppet']: apt_unhold(p.puppet_purge) apt_purge(p.puppet_purge) PuppetConfigs.install_puppet(p)
def remove_old_packages(): '''Purge any packages that need ot be removed. :returns: bool Whether packages were removed. ''' installed_packages = filter_missing_packages(determine_purge_packages()) if installed_packages: apt_purge(installed_packages, fatal=True) apt_autoremove(purge=True, fatal=True) return bool(installed_packages)
def install_packages(): add_source(config('source'), config('key')) apt_update(fatal=True) if is_container(): PACKAGES.remove('ntp') pkgs = filter_installed_packages(PACKAGES) if pkgs: status_set('maintenance', 'Installing radosgw packages') apt_install(PACKAGES, fatal=True) apt_purge(APACHE_PACKAGES) disable_unused_apache_sites()
def purge_packages(pkg_list): purge_pkgs = [] required_packages = determine_packages() for pkg in pkg_list: if pkg not in required_packages: purge_pkgs.append(pkg) purge_pkgs = filter_missing_packages(purge_pkgs) if purge_pkgs: status_set('maintenance', 'Purging unused packages') apt_purge(purge_pkgs, fatal=True) apt_autoremove(purge=True, fatal=True)
def toggle_docker_daemon_source(): """ A disruptive reaction to config changing that will remove the existing docker daemon and install the latest available deb from the upstream PPA, Nvidia PPA, or Universe depending on the docker_runtime setting. :return: None or False """ # This returns a list of packages not currently installed on the system # based on the parameters input. Use this to check if we have taken # prior action against a docker deb package. installed = [] for k in docker_packages.keys(): packages = filter_installed_packages(docker_packages[k]) if packages == []: installed.append(k) # None of the docker packages are installed. if len(installed) == 0: # We have not reached installation phase, return until # we can reasonably re-test this scenario. hookenv.log('No supported docker runtime is installed. Noop.') return runtime = determine_apt_source() if not docker_packages.get(runtime): hookenv.log('Unknown runtime {}'.format(runtime)) return False hookenv.log('Runtime to install {}'.format(runtime)) # Workaround # https://bugs.launchpad.net/ubuntu/+source/docker.io/+bug/1724353. if os.path.exists('/var/lib/docker/nuke-graph-directory.sh'): hookenv.log('Workaround bug 1724353') cmd = "sed -i '1i#!/bin/bash' /var/lib/docker/nuke-graph-directory.sh" check_call(split(cmd)) # The package we want is not installed # so we need to uninstall either of the others that are installed # and reset the state to forcea reinstall. if runtime not in installed: host.service_stop('docker') for k in docker_packages.keys(): package_list = " ".join(docker_packages[k]) hookenv.log('Removing package(s): {}.'.format(package_list)) apt_unhold(docker_packages[k]) apt_purge(docker_packages[k]) remove_state('docker.ready') remove_state('docker.available') else: hookenv.log('Not touching packages.')
def remove_old_packages(): '''Purge any packages that need to be removed. :returns: bool Whether packages were removed. ''' installed_packages = filter_missing_packages(determine_purge_packages()) if installed_packages: log('Removing apt packages') status_set('maintenance', 'Removing apt packages') apt_purge(installed_packages, fatal=True) apt_autoremove(purge=True, fatal=True) return bool(installed_packages)
def disable_unattended_upgrades(): """ """ try: packages = ['unattended-upgrades'] apt_purge(packages) os.remove("/etc/apt/apt.conf.d/50unattended-upgrades") except subprocess.CalledProcessError as e: action_fail('Command failed: %s (%s)' % (' '.join(e.cmd), str(e.output))) finally: remove_state('actions.disable-unattended-upgrades')
def neutron_plugin_changed(): settings = relation_get() if settings.get('enable-metadata'): enable_metadata = bool_from_string(settings['enable-metadata']) else: enable_metadata = False if 'metadata-shared-secret' in settings or enable_metadata: apt_update() apt_install(filter_installed_packages(['nova-api-metadata']), fatal=True) else: apt_purge('nova-api-metadata', fatal=True) CONFIGS.write(NOVA_CONF)
def remove(): """ Remove the docker daemon after relation departs. :return: None """ host.service_stop('docker') for k in docker_packages.keys(): package_list = " ".join(docker_packages[k]) hookenv.log('Removing package(s): {}.'.format(package_list)) apt_unhold(docker_packages[k]) apt_purge(docker_packages[k])
def config_changed(): global CONFIGS if git_install_requested(): if config_value_changed('openstack-origin-git'): status_set('maintenance', 'Running Git install') git_install(config('openstack-origin-git')) CONFIGS.write_all() elif not config('action-managed-upgrade'): if openstack_upgrade_available(NEUTRON_COMMON): status_set('maintenance', 'Running openstack upgrade') do_openstack_upgrade(CONFIGS) update_nrpe_config() sysctl_dict = config('sysctl') if sysctl_dict: create_sysctl(sysctl_dict, '/etc/sysctl.d/50-quantum-gateway.conf') # Re-run joined hooks as config might have changed for r_id in relation_ids('amqp'): amqp_joined(relation_id=r_id) for r_id in relation_ids('amqp-nova'): amqp_nova_joined(relation_id=r_id) for rid in relation_ids('zeromq-configuration'): zeromq_configuration_relation_joined(rid) if valid_plugin(): CONFIGS.write_all() configure_ovs() else: message = 'Please provide a valid plugin config' log(message, level=ERROR) status_set('blocked', message) sys.exit(1) if config('plugin') == 'n1kv': if not git_install_requested(): if config('enable-l3-agent'): status_set('maintenance', 'Installing apt packages') apt_install(filter_installed_packages('neutron-l3-agent')) else: apt_purge('neutron-l3-agent') # Setup legacy ha configurations update_legacy_ha_files() # Remove legacy MTU & network configs remove_file('/etc/init/os-charm-phy-nic-mtu.conf') # Trigger udev update for MTU subprocess.check_call(["udevadm", "trigger", "--subsystem-match=net"])
def install(): execd_preinstall() add_source(config('source'), config('key')) apt_update(fatal=True) apt_install(packages=ceph.determine_packages(), fatal=True) rm_packages = ceph.determine_packages_to_remove() if rm_packages: apt_purge(packages=rm_packages, fatal=True) try: # we defer and explicitly run `ceph-create-keys` from # add_keyring_to_ceph() as part of bootstrap process # LP: #1719436. service_pause('ceph-create-keys') except ValueError: pass
def remove(): """ Remove the docker daemon after relation departs. :return: None """ host.service_stop("docker") for k in docker_packages.keys(): package_list = " ".join(docker_packages[k]) hookenv.log("Removing package(s): {}.".format(package_list)) apt_unhold(docker_packages[k]) apt_purge(docker_packages[k]) shutil.rmtree("/etc/systemd/system/docker.service.d/", ignore_errors=True)
def config_changed(): global CONFIGS if git_install_requested(): if config_value_changed('openstack-origin-git'): status_set('maintenance', 'Running Git install') git_install(config('openstack-origin-git')) CONFIGS.write_all() elif not config('action-managed-upgrade'): if openstack_upgrade_available(get_common_package()): status_set('maintenance', 'Running openstack upgrade') do_openstack_upgrade(CONFIGS) update_nrpe_config() sysctl_dict = config('sysctl') if sysctl_dict: create_sysctl(sysctl_dict, '/etc/sysctl.d/50-quantum-gateway.conf') # Re-run joined hooks as config might have changed for r_id in relation_ids('shared-db'): db_joined(relation_id=r_id) for r_id in relation_ids('pgsql-db'): pgsql_db_joined(relation_id=r_id) for r_id in relation_ids('amqp'): amqp_joined(relation_id=r_id) for r_id in relation_ids('amqp-nova'): amqp_nova_joined(relation_id=r_id) for rid in relation_ids('zeromq-configuration'): zeromq_configuration_relation_joined(rid) if valid_plugin(): CONFIGS.write_all() configure_ovs() else: message = 'Please provide a valid plugin config' log(message, level=ERROR) status_set('blocked', message) sys.exit(1) if config('plugin') == 'n1kv': if not git_install_requested(): if config('enable-l3-agent'): status_set('maintenance', 'Installing apt packages') apt_install(filter_installed_packages('neutron-l3-agent')) else: apt_purge('neutron-l3-agent') # Setup legacy ha configurations update_legacy_ha_files()
def remove_old_packages(): '''Purge any packages that need ot be removed. :returns: bool Whether packages were removed. ''' installed_packages = filter_missing_packages(get_purge_packages()) if installed_packages: if 'neutron-lbaasv2-agent' in installed_packages: # Remove policyrd entry that would stop dpkg from stopping # service when package is removed. Bug #1931655 policy_rcd.remove_policy_block('neutron-lbaasv2-agent', ['restart', 'stop', 'try-restart']) deferred_events.clear_deferred_restarts('neutron-lbaasv2-agent') apt_purge(installed_packages, fatal=True) apt_autoremove(purge=True, fatal=True) return bool(installed_packages)
def remove_obsolete_packages(self): """Remove any packages that are no longer needed for operation :returns: boolean indication where packages where removed. """ if self.purge_packages: # NOTE(jamespage): # Ensure packages that should be purged are actually installed installed_packages = list( set(self.purge_packages) - set(fetch.filter_installed_packages(self.purge_packages))) if installed_packages: fetch.apt_purge(packages=installed_packages, fatal=True) fetch.apt_autoremove(purge=True, fatal=True) return True return False
def install(): '''Install lxd here''' status_set('maintenance', 'Installing charm packages') apt_purge('lxd lxd-client') apt_update() apt_install('zfsutils-linux') snap_install('lxd') status_set('maintenance', 'Setting up zfs pool') log('Creating lxc storage "local" using zpool at {}.'.format( config('host-block-device'))) subprocess.call([ 'lxc', 'storage', 'create', 'local', 'zfs', 'source={}'.format(config('host-block-device')) ]) status_set('active', 'Unit is ready')
def config_changed(): global CONFIGS if not config('action-managed-upgrade'): if openstack_upgrade_available(NEUTRON_COMMON): status_set('maintenance', 'Running openstack upgrade') do_openstack_upgrade(CONFIGS) update_nrpe_config() sysctl_settings = config('sysctl') if sysctl_settings: create_sysctl(sysctl_settings, '/etc/sysctl.d/50-quantum-gateway.conf') if config('vendor-data'): write_vendordata(config('vendor-data')) # Re-run joined hooks as config might have changed for r_id in relation_ids('amqp'): amqp_joined(relation_id=r_id) for r_id in relation_ids('amqp-nova'): amqp_nova_joined(relation_id=r_id) if valid_plugin(): CONFIGS.write_all() configure_ovs() configure_apparmor() else: message = 'Please provide a valid plugin config' log(message, level=ERROR) status_set('blocked', message) sys.exit(1) if config('plugin') == 'n1kv': if config('enable-l3-agent'): status_set('maintenance', 'Installing apt packages') apt_install(filter_installed_packages('neutron-l3-agent')) else: apt_purge('neutron-l3-agent') # Setup legacy ha configurations update_legacy_ha_files() # Disable nova metadata if possible, if disable_nova_metadata(): remove_legacy_nova_metadata()
def delete_package(self, cache, pkg): """Deletes the package from the system. Deletes the package form the system, properly handling virtual packages. :param cache: the apt cache :param pkg: the package to remove """ if self.is_virtual_package(pkg): log("Package '%s' appears to be virtual - purging provides" % pkg.name, level=DEBUG) for _p in pkg.provides_list: self.delete_package(cache, _p[2].parent_pkg) elif not pkg.current_ver: log("Package '%s' not installed" % pkg.name, level=DEBUG) return else: log("Purging package '%s'" % pkg.name, level=DEBUG) apt_purge(pkg.name)
def install_packages(): c = config() if c.changed('source') or c.changed('key'): add_source(c.get('source'), c.get('key')) apt_update(fatal=True) if is_container(): PACKAGES.remove('ntp') # NOTE: just use full package list if we're in an upgrade # config-changed execution pkgs = ( PACKAGES if upgrade_available() else filter_installed_packages(PACKAGES) ) if pkgs: status_set('maintenance', 'Installing radosgw packages') apt_install(pkgs, fatal=True) pkgs = filter_missing_packages(APACHE_PACKAGES) if pkgs: apt_purge(pkgs) disable_unused_apache_sites()
def stop(): cmd = 'crm -w -F node delete %s' % socket.gethostname() pcmk.commit(cmd) apt_purge(['corosync', 'pacemaker'], fatal=True)
def uninstall_packages(): db = kv() if db.get('installed'): status_set('maintenance', 'Purging packages') apt_purge(PACKAGES) db.unset('installed')
def pre_write(self): # Always remove? apt_purge('libpam-ccreds') apt_update(fatal=True) apt_install('libpam-modules')
def uninstall(self): apt_purge(self.packages()) _run_apt_command(['apt-get', 'autoremove', '--purge', '--assume-yes'])