def back(data):
    logger.critical("back here ----------------------------")
    logger.critical(data)
    return {
        'last_log': data[0],
        'last_error_log': data[1],
    }
def forth(data):
    logger.critical("forth here ----------------------------")
    logger.critical(data)
    if type(data) is dict and len(data) == 2:
        return (
            data.get('last_log', '.*'),
            data.get('last_error_log', '.*'),
        )
    else:
        return ('.*', '.*')

    return ('foo', 'bar')
Ejemplo n.º 3
0
def extract_snapshot(tar: tarfile.TarFile, domains: Dict[str,
                                                         DomainSpec]) -> None:
    """Used to restore a configuration snapshot for "discard changes"""
    tar_domains = {}
    for member in tar.getmembers():
        try:
            if member.name.endswith(".tar.gz"):
                tar_domains[member.name[:-7]] = member
        except Exception:
            pass

    # We are using the var_dir, because tmp_dir might not have enough space
    restore_dir = cmk.utils.paths.var_dir + "/wato/snapshots/restore_snapshot"
    if not os.path.exists(restore_dir):
        os.makedirs(restore_dir)

    def check_domain(domain: DomainSpec,
                     tar_member: tarfile.TarInfo) -> List[str]:
        errors = []

        prefix = domain["prefix"]

        def check_exists_or_writable(path_tokens: List[str]) -> bool:
            if not path_tokens:
                return False
            if os.path.exists("/".join(path_tokens)):
                if os.access("/".join(path_tokens), os.W_OK):
                    return True  # exists and writable

                errors.append(
                    _("Permission problem: Path not writable %s") %
                    "/".join(path_tokens))
                return False  # not writable

            return check_exists_or_writable(path_tokens[:-1])

        # The complete tar file never fits in stringIO buffer..
        tar.extract(tar_member, restore_dir)

        # Older versions of python tarfile handle empty subtar archives :(
        # This won't work: subtar = tarfile.open("%s/%s" % (restore_dir, tar_member.name))
        p = subprocess.Popen(
            ["tar", "tzf",
             "%s/%s" % (restore_dir, tar_member.name)],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            encoding="utf-8",
        )
        stdout, stderr = p.communicate()
        if stderr:
            errors.append(_("Contains corrupt file %s") % tar_member.name)
            return errors

        for line in stdout:
            full_path = prefix + "/" + line
            path_tokens = full_path.split("/")
            check_exists_or_writable(path_tokens)

        # Cleanup
        os.unlink("%s/%s" % (restore_dir, tar_member.name))

        return errors

    def cleanup_domain(domain: DomainSpec) -> List[str]:
        # Some domains, e.g. authorization, do not get a cleanup
        if domain.get("cleanup") is False:
            return []

        def path_valid(prefix: str, path: str) -> bool:
            if path.startswith("/") or path.startswith(".."):
                return False
            return True

        # Remove old stuff
        for what, path in domain.get("paths", {}):
            if not path_valid(domain["prefix"], path):
                continue
            full_path = "%s/%s" % (domain["prefix"], path)
            if os.path.exists(full_path):
                if what == "dir":
                    exclude_files = []
                    for pattern in domain.get("exclude", []):
                        if "*" in pattern:
                            exclude_files.extend(
                                glob.glob("%s/%s" %
                                          (domain["prefix"], pattern)))
                        else:
                            exclude_files.append("%s/%s" %
                                                 (domain["prefix"], pattern))
                    _cleanup_dir(full_path, exclude_files)
                else:
                    os.remove(full_path)
        return []

    def extract_domain(domain: DomainSpec,
                       tar_member: tarfile.TarInfo) -> List[str]:
        try:
            target_dir = domain.get("prefix")
            if not target_dir:
                return []
            # The complete tar.gz file never fits in stringIO buffer..
            tar.extract(tar_member, restore_dir)

            command = [
                "tar", "xzf",
                "%s/%s" % (restore_dir, tar_member.name), "-C", target_dir
            ]
            p = subprocess.Popen(
                command,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                encoding="utf-8",
            )
            _stdout, stderr = p.communicate()
            exit_code = p.wait()
            if exit_code:
                return ["%s - %s" % (domain["title"], stderr)]
        except Exception as e:
            return ["%s - %s" % (domain["title"], str(e))]

        return []

    def execute_restore(domain: DomainSpec,
                        is_pre_restore: bool = True) -> List[str]:
        if is_pre_restore:
            if "pre_restore" in domain:
                return domain["pre_restore"]()
        else:
            if "post_restore" in domain:
                return domain["post_restore"]()
        return []

    total_errors = []
    logger.info("Restoring snapshot: %s", tar.name)
    logger.info("Domains: %s", ", ".join(tar_domains.keys()))
    for what, abort_on_error, handler in [
        ("Permissions", True, check_domain),
        ("Pre-Restore", True, lambda domain, tar_member: execute_restore(
            domain, is_pre_restore=True)),
        ("Cleanup", False, lambda domain, tar_member: cleanup_domain(domain)),
        ("Extract", False, extract_domain),
        ("Post-Restore", False, lambda domain, tar_member: execute_restore(
            domain, is_pre_restore=False))
    ]:
        errors: List[str] = []
        for name, tar_member in tar_domains.items():
            if name in domains:
                try:
                    dom_errors = handler(domains[name], tar_member)
                    errors.extend(dom_errors or [])
                except Exception:
                    # This should NEVER happen
                    err_info = "Restore-Phase: %s, Domain: %s\nError: %s" % (
                        what, name, traceback.format_exc())
                    errors.append(err_info)
                    logger.critical(err_info)
                    if not abort_on_error:
                        # At this state, the restored data is broken.
                        # We still try to apply the rest of the snapshot
                        # Hopefully the log entry helps in identifying the problem..
                        logger.critical(
                            "Snapshot restore FAILED! (possible loss of snapshot data)"
                        )
                        continue
                    break

        if errors:
            if what == "Permissions":
                errors = list(set(errors))
                errors.append(
                    _("<br>If there are permission problems, please ensure the site user has write permissions."
                      ))
            if abort_on_error:
                raise MKGeneralException(
                    _("%s - Unable to restore snapshot:<br>%s") %
                    (what, "<br>".join(errors)))
            total_errors.extend(errors)

    # Cleanup
    _wipe_directory(restore_dir)

    if total_errors:
        raise MKGeneralException(
            _("Errors on restoring snapshot:<br>%s") %
            "<br>".join(total_errors))
Ejemplo n.º 4
0
 def as_canonical_dict(self):
     """Returns the RMK Config as the canonical dictionary"""
     logger.critical("ASDICT -------")
     logger.critical(self._cfg_dict)
     return self._cfg_dict