def test_correct_command_called(self, m_subp): get_installed_packages() expected_call = mock.call( ["dpkg-query", "-W", "--showformat=${Package}\\n"] ) assert [expected_call] == m_subp.call_args_list
def enable(self, *, silent_if_inapplicable: bool = False) -> bool: """Enable specific entitlement. :param silent_if_inapplicable: Don't emit any messages until after it has been determined that this entitlement is applicable to the current machine. @return: True on success, False otherwise. """ if not self.can_enable(silent=silent_if_inapplicable): return False if not util.which('/snap/bin/canonical-livepatch'): if not util.which(SNAP_CMD): print('Installing snapd') util.subp(['apt-get', 'install', '--assume-yes', 'snapd'], capture=True, retry_sleeps=apt.APT_RETRIES) util.subp([SNAP_CMD, 'wait', 'system', 'seed.loaded'], capture=True) elif 'snapd' not in apt.get_installed_packages(): raise exceptions.UserFacingError( '/usr/bin/snap is present but snapd is not installed;' ' cannot enable {}'.format(self.title)) print('Installing canonical-livepatch snap') try: util.subp([SNAP_CMD, 'install', 'canonical-livepatch'], capture=True, retry_sleeps=SNAP_INSTALL_RETRIES) except util.ProcessExecutionError as e: msg = 'Unable to install Livepatch client: ' + str(e) print(msg) logging.error(msg) return False return self.setup_livepatch_config(process_directives=True, process_token=True)
def packages(self) -> "List[str]": packages = list(self.fips_required_packages) installed_packages = apt.get_installed_packages() for pkg_name, extra_pkgs in self.fips_packages.items(): if pkg_name in installed_packages: packages.append(pkg_name) packages.extend(extra_pkgs) return packages
def enable(self, *, silent_if_inapplicable: bool = False) -> bool: """Enable specific entitlement. :param silent_if_inapplicable: Don't emit any messages until after it has been determined that this entitlement is applicable to the current machine. @return: True on success, False otherwise. """ if not self.can_enable(silent=silent_if_inapplicable): return False if not util.which("/snap/bin/canonical-livepatch"): if not util.which(SNAP_CMD): print("Installing snapd") print(status.MESSAGE_APT_UPDATING_LISTS) try: apt.run_apt_command( ["apt-get", "update"], status.MESSAGE_APT_UPDATE_FAILED ) except exceptions.UserFacingError as e: logging.debug( "Trying to install snapd." " Ignoring apt-get update failure: %s", str(e), ) util.subp( ["apt-get", "install", "--assume-yes", "snapd"], capture=True, retry_sleeps=apt.APT_RETRIES, ) elif "snapd" not in apt.get_installed_packages(): raise exceptions.UserFacingError( "/usr/bin/snap is present but snapd is not installed;" " cannot enable {}".format(self.title) ) util.subp( [SNAP_CMD, "wait", "system", "seed.loaded"], capture=True ) print("Installing canonical-livepatch snap") try: util.subp( [SNAP_CMD, "install", "canonical-livepatch"], capture=True, retry_sleeps=SNAP_INSTALL_RETRIES, ) except util.ProcessExecutionError as e: msg = "Unable to install Livepatch client: " + str(e) raise exceptions.UserFacingError(msg) return self.setup_livepatch_config( process_directives=True, process_token=True )
def packages(self) -> "List[str]": packages = super().packages installed_packages = apt.get_installed_packages() pkg_groups = groupby( self.conditional_packages, key=lambda pkg_name: pkg_name.replace("-hmac", ""), ) for pkg_name, pkg_list in pkg_groups: if pkg_name in installed_packages: packages += pkg_list return packages
def install_packages( self, package_list: List[str] = None, cleanup_on_failure: bool = True, verbose: bool = True, ) -> None: """Install contract recommended packages for the entitlement. :param package_list: Optional package list to use instead of self.packages. :param cleanup_on_failure: Cleanup apt files if apt install fails. :param verbose: If true, print messages to stdout """ if verbose: event.info("Installing {title} packages".format(title=self.title)) # We need to guarantee that the metapackage is installed. # While the other packages should still be installed, if they # fail, we should not block the enable operation. mandatory_packages = self.packages super().install_packages( package_list=mandatory_packages, verbose=False ) # Any conditional packages should still be installed, but if # they fail to install we should not block the enable operation. desired_packages = [] # type: List[str] installed_packages = apt.get_installed_packages() pkg_groups = groupby( sorted(self.conditional_packages), key=lambda pkg_name: pkg_name.replace("-hmac", ""), ) for pkg_name, pkg_list in pkg_groups: if pkg_name in installed_packages: desired_packages += pkg_list for pkg in desired_packages: try: super().install_packages( package_list=[pkg], cleanup_on_failure=False, verbose=False ) except exceptions.UserFacingError: event.info( messages.FIPS_PACKAGE_NOT_AVAILABLE.format( service=self.title, pkg=pkg ) )
def packages(self) -> "List[str]": packages = [] # type: List[str] installed_packages = apt.get_installed_packages() pkg_groups = groupby( super().packages, key=lambda pkg_name: pkg_name.replace("-hmac", ""), ) for pkg_name, pkg_list in pkg_groups: if pkg_name in installed_packages: packages += pkg_list elif pkg_name in self.fips_required_packages: packages += pkg_list return packages
def remove_packages(self) -> None: """Remove fips meta package to disable the service. FIPS meta-package will unset grub config options which will deactivate FIPS on any related packages. """ installed_packages = set(apt.get_installed_packages()) fips_metapackage = set(self.packages).difference( set(self.conditional_packages) ) remove_packages = fips_metapackage.intersection(installed_packages) if remove_packages: env = {"DEBIAN_FRONTEND": "noninteractive"} apt_options = [ '-o Dpkg::Options::="--force-confdef"', '-o Dpkg::Options::="--force-confold"', ] apt.run_apt_command( ["apt-get", "remove", "--assume-yes"] + apt_options + list(remove_packages), messages.DISABLE_FAILED_TMPL.format(title=self.title), env=env, )
def test_assert_missing_eof_newline_works(self, m_subp): assert ["a", "b"] == get_installed_packages()
def test_lines_are_split(self, m_subp): assert ["a", "b"] == get_installed_packages()
def test_empty_output_means_empty_list(self, m_subp): assert [] == get_installed_packages()
def _perform_enable(self, silent: bool = False) -> bool: """Enable specific entitlement. @return: True on success, False otherwise. """ if not util.which(snap.SNAP_CMD): event.info("Installing snapd") event.info(messages.APT_UPDATING_LISTS) try: apt.run_apt_update_command() except exceptions.UserFacingError as e: logging.debug( "Trying to install snapd." " Ignoring apt-get update failure: %s", str(e), ) util.subp( ["apt-get", "install", "--assume-yes", "snapd"], capture=True, retry_sleeps=apt.APT_RETRIES, ) elif "snapd" not in apt.get_installed_packages(): raise exceptions.SnapdNotProperlyInstalledError( snap_cmd=snap.SNAP_CMD, service=self.title ) try: util.subp( [snap.SNAP_CMD, "wait", "system", "seed.loaded"], capture=True ) except exceptions.ProcessExecutionError as e: if re.search(r"unknown command .*wait", str(e).lower()): logging.warning(messages.SNAPD_DOES_NOT_HAVE_WAIT_CMD) else: raise http_proxy = util.validate_proxy( "http", self.cfg.http_proxy, util.PROXY_VALIDATION_SNAP_HTTP_URL ) https_proxy = util.validate_proxy( "https", self.cfg.https_proxy, util.PROXY_VALIDATION_SNAP_HTTPS_URL ) snap.configure_snap_proxy( http_proxy=http_proxy, https_proxy=https_proxy, retry_sleeps=snap.SNAP_INSTALL_RETRIES, ) if not util.which(LIVEPATCH_CMD): event.info("Installing canonical-livepatch snap") try: util.subp( [snap.SNAP_CMD, "install", "canonical-livepatch"], capture=True, retry_sleeps=snap.SNAP_INSTALL_RETRIES, ) except exceptions.ProcessExecutionError as e: raise exceptions.ErrorInstallingLivepatch(error_msg=str(e)) configure_livepatch_proxy(http_proxy, https_proxy) return self.setup_livepatch_config( process_directives=True, process_token=True )
def test_lines_are_split(self, m_subp): assert ['a', 'b'] == get_installed_packages()
def is_installed() -> bool: """Returns whether or not snap is installed""" return "snapd" in apt.get_installed_packages()