Beispiel #1
0
def get_history_deltas(hostname, search_timestamp=None):
    if '/' in hostname:
        return None  # just for security reasons

    inventory_path = "%s/inventory/%s" % (cmk.utils.paths.var_dir, hostname)
    if not os.path.exists(inventory_path):
        return []

    latest_timestamp = str(int(os.stat(inventory_path).st_mtime))
    inventory_archive_dir = "%s/inventory_archive/%s" % (
        cmk.utils.paths.var_dir, hostname)
    try:
        archived_timestamps = sorted(os.listdir(inventory_archive_dir))
    except OSError:
        return []

    all_timestamps = archived_timestamps + [latest_timestamp]
    previous_timestamp = None

    if not search_timestamp:
        required_timestamps = all_timestamps
    else:
        new_timestamp_idx = all_timestamps.index(search_timestamp)
        if new_timestamp_idx == 0:
            required_timestamps = [search_timestamp]
        else:
            previous_timestamp = all_timestamps[new_timestamp_idx - 1]
            required_timestamps = [search_timestamp]

    tree_lookup = {}

    def get_tree(timestamp):
        if timestamp is None:
            return StructuredDataTree()

        if timestamp in tree_lookup:
            return tree_lookup[timestamp]

        if timestamp == latest_timestamp:
            inventory_tree = load_filtered_inventory_tree(hostname)
            if inventory_tree is None:
                return
            tree_lookup[timestamp] = inventory_tree
        else:
            inventory_archive_path = "%s/%s" % (inventory_archive_dir,
                                                timestamp)
            tree_lookup[timestamp] = _filter_tree(
                StructuredDataTree().load_from(inventory_archive_path))
        return tree_lookup[timestamp]

    delta_history = []
    for _idx, timestamp in enumerate(required_timestamps):
        cached_delta_path = os.path.join(
            cmk.utils.paths.var_dir, "inventory_delta_cache", hostname,
            "%s_%s" % (previous_timestamp, timestamp))

        cached_data = None
        try:
            cached_data = cmk.utils.store.load_data_from_file(
                cached_delta_path)
        except MKGeneralException:
            pass

        if cached_data:
            new, changed, removed, delta_tree_data = cached_data
            delta_tree = StructuredDataTree()
            delta_tree.create_tree_from_raw_tree(delta_tree_data)
            delta_history.append(
                (timestamp, (new, changed, removed, delta_tree)))
            previous_timestamp = timestamp
            continue

        try:
            previous_tree = get_tree(previous_timestamp)
            current_tree = get_tree(timestamp)
            delta_data = current_tree.compare_with(previous_tree)
            new, changed, removed, delta_tree = delta_data

            cmk.utils.store.save_file(
                cached_delta_path,
                repr((new, changed, removed, delta_tree.get_raw_tree())))
            delta_history.append((timestamp, delta_data))
        except RequestTimeout:
            raise
        except Exception:
            return []  # No inventory for this host

        previous_timestamp = timestamp

    return delta_history
Beispiel #2
0
def get_history_deltas(
    hostname: HostName,
    search_timestamp: Optional[str] = None
) -> Tuple[List[Tuple[str, InventoryDeltaData]], List[str]]:
    if '/' in hostname:
        return [], []  # just for security reasons

    inventory_path = "%s/%s" % (cmk.utils.paths.inventory_output_dir, hostname)
    if not os.path.exists(inventory_path):
        return [], []

    latest_timestamp = str(int(os.stat(inventory_path).st_mtime))
    inventory_archive_dir = "%s/%s" % (cmk.utils.paths.inventory_archive_dir,
                                       hostname)
    try:
        archived_timestamps = sorted(os.listdir(inventory_archive_dir))
    except OSError:
        return [], []

    all_timestamps: List[str] = archived_timestamps + [latest_timestamp]
    previous_timestamp: Optional[str] = None

    if not search_timestamp:
        required_timestamps = all_timestamps
    else:
        new_timestamp_idx = all_timestamps.index(search_timestamp)
        if new_timestamp_idx == 0:
            required_timestamps = [search_timestamp]
        else:
            previous_timestamp = all_timestamps[new_timestamp_idx - 1]
            required_timestamps = [search_timestamp]

    tree_lookup: Dict[str, Any] = {}

    def get_tree(timestamp: Optional[str]) -> StructuredDataTree:
        if timestamp is None:
            return StructuredDataTree()

        if timestamp in tree_lookup:
            return tree_lookup[timestamp]

        if timestamp == latest_timestamp:
            inventory_tree = load_filtered_inventory_tree(hostname)
            if inventory_tree is None:
                raise LoadStructuredDataError()
            tree_lookup[timestamp] = inventory_tree
        else:
            inventory_archive_path = "%s/%s" % (inventory_archive_dir,
                                                timestamp)
            tree_lookup[timestamp] = _filter_tree(
                StructuredDataTree().load_from(inventory_archive_path))
        return tree_lookup[timestamp]

    corrupted_history_files = []
    delta_history: List[Tuple[str, InventoryDeltaData]] = []
    for _idx, timestamp in enumerate(required_timestamps):
        cached_delta_path = os.path.join(
            cmk.utils.paths.var_dir, "inventory_delta_cache", hostname,
            "%s_%s" % (previous_timestamp, timestamp))

        cached_data = None
        try:
            cached_data = store.load_object_from_file(cached_delta_path)
        except MKGeneralException:
            pass

        if cached_data:
            new, changed, removed, delta_tree_data = cached_data
            delta_tree = StructuredDataTree()
            delta_tree.create_tree_from_raw_tree(delta_tree_data)
            delta_history.append(
                (timestamp, (new, changed, removed, delta_tree)))
            previous_timestamp = timestamp
            continue

        try:
            previous_tree = get_tree(previous_timestamp)
            current_tree = get_tree(timestamp)
            delta_data: InventoryDeltaData = current_tree.compare_with(
                previous_tree)
            new, changed, removed, delta_tree = delta_data
            if new or changed or removed:
                store.save_file(
                    cached_delta_path,
                    repr((new, changed, removed, delta_tree.get_raw_tree())),
                )
                delta_history.append((timestamp, delta_data))
        except LoadStructuredDataError:
            corrupted_history_files.append(
                str(get_short_inventory_history_filepath(hostname, timestamp)))

        previous_timestamp = timestamp

    return delta_history, corrupted_history_files