Пример #1
0
 def check_system(self):
     """
     After a system has had all of its packages installed and it's in
     stable-state, this is a method we can use to verify that everything
     is still kosher
     """
     Logger.info("System-check starting...")
     bom_pkns = self.config.get_bom_pkns()
     pdat = self.progress.get_progress_data()
     full_pdat = self.progress.get_progress_data(False)
     full_installed_pkns, _full_bpkns = Progress.get_installed(full_pdat)
     msg = "Packages that are installed: %s"
     Logger.info(msg % " ".join(full_installed_pkns))
     installed_pkns, broken_pkns = Progress.get_installed(pdat)
     should_be_installed, shouldnt_be_installed = self._check_bom(bom_pkns)
     # check the configuration for each installed package
     pkg_info = {
         "Packages installed properly": installed_pkns,
         "Packages to be RECONFIGURED": {},
         "Packages to be INSTALLED": should_be_installed,
         "Packages to be REMOVED": shouldnt_be_installed,
         "Packages that are BROKEN": broken_pkns,
     }
     for pkn in shouldnt_be_installed:
         pkg_info["Packages installed properly"].remove(pkn)
     for pkn in installed_pkns:
         differences = self._check_configuration_hash(pkn)
         if differences:
             if pkn in pkg_info["Packages installed properly"]:
                 pkg_info["Packages to be RECONFIGURED"][pkn] = differences
                 pkg_info["Packages installed properly"].remove(pkn)
     for key in pkg_info:
         Logger.info("==OUTPUT==:%s: %s" % (key, pkg_info[key]))
     return pkg_info
Пример #2
0
 def use_pkg(self, pkn, action, script_name, arguments):
     """
     Main entry point to the class. Performs an action using a package
     pkn -- name of the package to use
     action -- STATUS, INSTALL, UNINSTALL, CONFIGURE, VERIFY, or EXEC
     script_name -- the name of a method to run within the package
     arguments -- arguments to the executable, typically a restore target
     """
     try:
         pkg = self._get_new_pkg(pkn)
         if pkg.status == FAIL:
             self.operation_status = FAIL
             return self._cleanup()
         if action == INSTALL:
             pdat = self.progress.get_progress_data(False)
             installed_pkns, broken_pkns = Progress.get_installed(pdat)
             if pkn in [installed_pkns + broken_pkns]:
                 Logger.error("Package %s cannot be installed." % pkn)
                 self.operation_status = FAIL
                 return FAIL
             add_pkd = {pkn: pkg}
             status = self._install_pkgs(add_pkd)
         if action == UNINSTALL:
             pdat = self.progress.get_progress_data(False)
             installed_pkns, broken_pkns = Progress.get_installed(pdat)
             bom_pkns = installed_pkns
             if pkn in bom_pkns:
                 bom_pkns.remove(pkn)
             self.config.set_bom_pkgs(bom_pkns)
             add_pkd, del_pkd, uninstall_order = self._ck_inst_stat([])
             status = self._uninstall_pkgs(del_pkd, uninstall_order)
         if action == VERIFY:
             status = pkg.verify()
         if action == CONFIGURE:
             self._check_configuration(pkg)
             status = pkg.configure()
             hash_path = make_path(pkg.get_path(), HASH_FILE)
             msg = "Writing configuration fingerprint to %s" % hash_path
             Logger.info(msg)
             self.config.save_hash(hash_path)
         if action in [EXECUTE, BACKUP, RESTORE]:
             status = pkg.execute_maint_script(script_name, arguments)
             if status == FAIL:
                 self.operation_status = FAIL
         msg = "Finished %s for %s."
         msg = msg % (ACTION_REVERSE_LOOKUP[action], pkn)
         self.operation_output.append(msg)
         status = self._cleanup()
         return self._cleanup()
     except Exceptions.BadPackage, err:
         errmsg = "Cannot perform action %s on package %s: %s"
         errmsg = errmsg % (ACTION_REVERSE_LOOKUP[action], err.pkn, err.errmsg)
         Logger.warning(errmsg)
         Logger.info("RETURN FAIL 1")
         return FAIL
Пример #3
0
    def _check_bom(self, bom_pkns):
        """ Check through what should be installed on the system and what
        is installed on the system and determine what packages aren't
        installed that should be and what packages are installed that
        shouldn't be.
        bom_pkns -- A list of package names that are intended to be
                    installed on the machine (i.e. the 'bill of
                    materials'
        """
        should_be_installed = []
        shouldnt_be_installed = []
        pdat = self.progress.get_progress_data(False)
        installed_pkns, broken_pkns = Progress.get_installed(pdat)

        all_pkns = set(installed_pkns).union(broken_pkns)
        all_plus_missing_pkns = self._examine_dependencies(all_pkns)
        missing_pkns = list(all_plus_missing_pkns - all_pkns)
        bom_pkns = bom_pkns + missing_pkns

        dependency_errors = self._get_dependency_errors(bom_pkns, pdat)
        if dependency_errors:
            errmsg = "The following packages are installed as " "dependencies %s" % dependency_errors
            Logger.debug(errmsg)
        bom_pkns += dependency_errors
        for pkn in installed_pkns:
            if pkn not in bom_pkns:
                shouldnt_be_installed.append(pkn)
        for pkn in bom_pkns:
            if pkn not in installed_pkns:
                should_be_installed.append(pkn)
        return should_be_installed, shouldnt_be_installed
Пример #4
0
    def _find_install_order(self, pkd):
        """Returns a list of pkns in the correct installation order
        - Create chains of package dependencies, the priority of each
        chain is the package with the highest priority in it, unless
        that package is already installed.
        - A package can appear in more than one chain
        - A package chain can have a single package in it if it does not
        have any dependencies and is not dependent on others.
        pkd -- dictionary of package objects
        """

        chains = self._create_pkg_chains(pkd)
        pdat = self.progress.get_progress_data(False)
        installed_pkns, _broken_pkns = Progress.get_installed(pdat)
        # - Put all the packages of each chain into the installation
        # order, excluding those that have already been installed in order
        # of chain priority. If a package is already in the installation
        # List, do not put it in twice.
        install_order = []
        while chains:
            top_priority = self._get_top_priority(chains)
            for priority, chain in chains:
                if priority == top_priority:
                    for pkn in chain:
                        if pkn not in installed_pkns:
                            if pkn not in install_order:
                                install_order.append(pkn)
                    chains.remove([priority, chain])
        return install_order
Пример #5
0
 def _create_pkg_chains(self, pkd):
     """
     Create package chains based on current set of packages
     pkd -- dictionary of package objects
     """
     chains = []
     pkg_data = self.progress.get_progress_data(False)
     installed_pkns, broken_pkns = Progress.get_installed(pkg_data)
     for pkn in pkd.keys():
         if pkn in broken_pkns:
             Logger.warning("Skipping broken package %s" % pkn)
             continue
         if pkn not in installed_pkns:
             chain_priority = pkd[pkn].priority
         else:
             chain_priority = 0
         try:
             new_chain = PackageChain(
                 chain_priority,
                 pkn,
                 pkd,
                 installed_pkns,
                 broken_pkns,
                 self.repository,
                 self.config,
                 self.instance_name,
                 self.record_errors,
             )
         except Exceptions.BadPackage, err:
             errmsg = "Package %s will not be installed because it is " "dependent upon one or more broken packages"
             Logger.warning(errmsg % pkn)
             Logger.warning(str(err))
             continue
         chains.append([new_chain.priority, new_chain.chain])
Пример #6
0
    def get_names_from_progress(self, stripped=False):
        progress_data = self.get_progress_data()
        if progress_data == None:
            (installed_package_names, broken_package_names) = ([], [])
        else:
            pkg_info = Progress.get_installed_uninstalled_times(progress_data)
            unstripped_inst_pkgs = [package_name[0] for package_name in pkg_info["installed"]]
            unstripped_broken_pkgs = [package_name[0] for package_name in pkg_info["broken_installed"]]
            unstripped_broken_pkgs += [package_name[0] for package_name in pkg_info["broken_uninstalled"]]

            if stripped:
                installed_package_names = [Progress.strip_version(x) for x in unstripped_inst_pkgs]
                broken_package_names = [Progress.strip_version(x) for x in unstripped_broken_pkgs]
            else:
                installed_package_names = unstripped_inst_pkgs
                broken_package_names = unstripped_broken_pkgs
        return (set(installed_package_names), set(broken_package_names))
Пример #7
0
 def get_all_package_names(self, config_packages):
     "Get package names from status and this object and union them together."
     try:
         package_list = self.get_package_names_from_progress().get(PROGRESS, {})
     except MachineStatusException:
         package_list = []
     package_names = set([Progress.strip_version(x) for x in package_list])
     package_names = package_names.union(set(config_packages))
     return list(package_names)
Пример #8
0
 def __init__(self, repository, config, instance_name):
     """
     repository -- object that keeps track of package data
     config -- object that keeps track of this machine's configuration
     instance_name -- the name of this machine
     """
     self.repository = repository
     self.config = config
     self.instance_name = instance_name
     self.record_errors = True
     self.operation_status = OK
     self.operation_output = []
     self.progress = Progress(instance_name)
Пример #9
0
 def _get_pkd_to_remove(self, del_pkns):
     """
     Given a list of package names that we want to delete, let's create a
     proper dictionary of package objects which provide complete dependency
     information and specify the proper uninstallation order
     del_pkns -- a list of package names that need to be removed
     """
     "Getting packages to remove..."
     uninstall_order = []
     pdat = self.progress.get_progress_data(False)
     installed_pkns, _broken_pkns = Progress.get_installed(pdat)
     del_pkd = self._get_del_pkd(del_pkns)
     if set(installed_pkns) == set(del_pkd.keys()):
         return del_pkd, del_pkd.keys()
     if del_pkns:
         del_pkd, uninstall_order = self._get_uninst_pkg_dep(del_pkd, del_pkns, installed_pkns)
     return del_pkd, uninstall_order
Пример #10
0
class Bombardier:
    """Master class for managing system actions"""

    def __init__(self, repository, config, instance_name):
        """
        repository -- object that keeps track of package data
        config -- object that keeps track of this machine's configuration
        instance_name -- the name of this machine
        """
        self.repository = repository
        self.config = config
        self.instance_name = instance_name
        self.record_errors = True
        self.operation_status = OK
        self.operation_output = []
        self.progress = Progress(instance_name)

    def _get_dependency_errors(self, bom_pkns, pdat):
        """
        Pulls dependency error data out of status.yml
        bom_pkns -- the names of packages which are on the bill of
                    materials for this machine
        pdat -- a dictionary which maintains information about what
                packages are installed, uninstalled, verified, etc.
        """
        dependency_names = set([])
        install_progress = pdat.get("install-progress", {})
        for pkn in install_progress:
            pkd = install_progress[pkn]
            dep_errors = set(pkd.get("DEPENDENCY_ERRORS", []))
            dependency_names = dependency_names.union(dep_errors)
        dependency_names = list(dependency_names - set(bom_pkns))
        return dependency_names

    def _create_pkg_chains(self, pkd):
        """
        Create package chains based on current set of packages
        pkd -- dictionary of package objects
        """
        chains = []
        pkg_data = self.progress.get_progress_data(False)
        installed_pkns, broken_pkns = Progress.get_installed(pkg_data)
        for pkn in pkd.keys():
            if pkn in broken_pkns:
                Logger.warning("Skipping broken package %s" % pkn)
                continue
            if pkn not in installed_pkns:
                chain_priority = pkd[pkn].priority
            else:
                chain_priority = 0
            try:
                new_chain = PackageChain(
                    chain_priority,
                    pkn,
                    pkd,
                    installed_pkns,
                    broken_pkns,
                    self.repository,
                    self.config,
                    self.instance_name,
                    self.record_errors,
                )
            except Exceptions.BadPackage, err:
                errmsg = "Package %s will not be installed because it is " "dependent upon one or more broken packages"
                Logger.warning(errmsg % pkn)
                Logger.warning(str(err))
                continue
            chains.append([new_chain.priority, new_chain.chain])
        return chains