PAN-OS-GetDeviceDiskSpace

Fetches disk space info from the target device and returns all information or a subset as specified in command arguments.

python · PAN-OS by Palo Alto Networks

Details

IDPAN-OS-GetDeviceDiskSpace
Languagepython
From Version6.10.0
Docker Imagedemisto/python3:3.12.13.10116658

README

This script fetches disk space info from the target device and returns all information or a subset as specified in command arguments.

Script Data


Name Description
Script Type python3
Cortex XSOAR Version 6.10.0

Dependencies


This script uses the following commands and scripts.

  • Panorama
  • pan-os

Used In


This script is used in the following playbooks and scripts.

  • PAN-OS - Firewall Upgrade Readiness Checks

Inputs


Argument Name Description
target The serial number of the device to get disk space info from.
panos_instance_name The instance name of the PAN-OS Integration to use. Specify only one instance.
disk_space_units  

Outputs


Path Description Type
PANOS.DiskSpace.hostid Serial number of the device. string
PANOS.DiskSpace.FileSystems.FileSystem The device file system. string
PANOS.DiskSpace.FileSystems.Size The size of the file system. number
PANOS.DiskSpace.FileSystems.Used The amount of used space on the file system. number
PANOS.DiskSpace.FileSystems.Avail The amount of free space on the file system. number
PANOS.DiskSpace.FileSystems.Used% The percentage of total size used. string
PANOS.DiskSpace.FileSystems.MountedOn The path where the file system is mounted. string
PANOS.DiskSpace.FileSystems.Units The unit used to represent disk space values. string
import demistomock as demisto  # noqa: F401
from CommonServerPython import *  # noqa: F401


import traceback


def show_disk_space_command(args: dict) -> dict:
    """show_disk_space_command Runs the `pan-os` command using the specified Integration Instance

    Args:
        args (dict): Script arguments

    Raises:
        Exception: Raises an exception if the `pan-os` command returned an error entry.

    Returns:
        dict: The output command results object from `pan-os`
    """
    # Set command args
    allowed_args = ["target", "panos_instance_name"]
    command_args = {k: args.get(k) for k in allowed_args if k in args}
    command_args["cmd"] = "<show><system><disk-space></disk-space></system></show>"
    command_args["type"] = "op"

    # Rename 'instance_name' key to 'using' to match the command syntax, if required
    if "panos_instance_name" in command_args:
        command_args["using"] = command_args.pop("panos_instance_name")

    # Execute the command
    res = demisto.executeCommand("pan-os", command_args)

    # Check if the command returned an error and raise exception if needed
    if is_error(res):
        raise Exception(f"Error executing pan-os: {get_error(res)}")

    # Return command results
    return res


def convert_space_units(original_value: str, desired_units: str) -> float:
    """convert_space_units Converts disk space units from `show system disk-space` into the desired unit.

    Disk space values from the `show system disk-space` command end in a single letter denoting the unit:
        T: Terabyte
        M: Megabyte
        G: Gigabyte
        K: Kilobyte

    Args:
        original_value (str): Disk space string including unit letter (e.g. "42G")
        desired_units (str): The unit to convert the original disk space value to (e.g. "M")

    Raises:
        ValueError: Unsupported original unit (not one of ['T', 'G', 'M', 'K'])
        ValueError: Unsupported desired unit (not one of ['T', 'G', 'M', 'K'])

    Returns:
        float: The converted disk space, rounded to one decimal
    """
    # Extract the numerical value and the unit from the input string, as long as it's not 0
    if original_value != "0":
        value = float(original_value[:-1])
        original_unit = original_value[-1]
    else:
        # Input value was 0 so no conversion is needed - return as a number
        return 0

    # Conversion dictionary with all units converted to kilobytes
    conversion_to_kilobytes = {"K": 1, "M": 1024, "G": 1024 * 1024, "T": 1024 * 1024 * 1024}

    # Convert original value to kilobytes first
    if original_unit in conversion_to_kilobytes:
        value_in_kilobytes = value * conversion_to_kilobytes[original_unit]
    else:
        raise ValueError("Unsupported original unit")

    # Conversion dictionary from kilobytes to desired unit
    conversion_from_kilobytes = {"K": 1, "M": 1 / 1024, "G": 1 / (1024 * 1024), "T": 1 / (1024 * 1024 * 1024)}

    # Convert from kilobytes to the desired unit
    if desired_units in conversion_from_kilobytes:
        converted_value = round(value_in_kilobytes * conversion_from_kilobytes[desired_units], 1)
    else:
        raise ValueError("Unsupported desired unit")

    return converted_value


def parse_disk_space_output(disk_space_string: str, desired_units: str) -> list[dict]:
    """parse_disk_space_output Parses string output from `show system disk-space` with all disk space values converted
    to the desired unit and returns it as a dictionary.

    Args:
        disk_space_string (str): The output string from the `show system disk-space` command.
        desired_units (str): The unit to represent disk space values (One of ['T', 'G', 'M', 'K'])

    Returns:
        list[dict]: _description_
    """
    # Split the disk space string into lines
    lines = disk_space_string.split("\n")

    # Initialize list of file system entries
    filesystems = []

    # Iterate over each line except the first one (which contains header information)
    for line in lines[1:]:
        # Split the line into components based on whitespace
        parts = line.split()

        # Ensure the line is not empty and has all necessary parts to form a dictionary
        if len(parts) >= 6:
            # Build a dictionary for the current filesystem
            filesystem_info = {
                "FileSystem": parts[0],
                "Size": convert_space_units(parts[1], desired_units),
                "Used": convert_space_units(parts[2], desired_units),
                "Avail": convert_space_units(parts[3], desired_units),
                "Use%": parts[4],
                "MountedOn": " ".join(parts[5:]),  # Joining in case the mount point has spaces
                "Units": desired_units,
            }

            # Append the dictionary to our list
            filesystems.append(filesystem_info)

    # Return the list of dictionaries
    return filesystems


def get_disk_space(args: dict) -> CommandResults:
    """get_disk_space Runs the `show system disk-space` operational command and formats its output as a list of
    dictionaries.

    Args:
        args (dict): Script arguments.

    Returns:
        CommandResults: CommandResults object containing entries for each file system on the device.
    """
    # Run PAN-OS command and get results
    command_result = show_disk_space_command(args)

    # Get the raw string returned by the PAN-OS command
    disk_space_string = command_result[0]["Contents"]["response"]["result"]

    # Parse the raw string into a list of dictionaries with disk space represented in the desired unit
    parsed_disk_space = parse_disk_space_output(disk_space_string, args.get("disk_space_units", ""))

    # Construct the output representing the disk space on the given device
    device_entry = {"hostid": args.get("target"), "FileSystems": parsed_disk_space}

    # Create markdown table to display in war room
    readable_result = tableToMarkdown(name="System Disk Space", t=parsed_disk_space)

    # Construct CommandResults object
    results = CommandResults(
        outputs_prefix="PANOS.DiskSpace", outputs=device_entry, outputs_key_field="hostid", readable_output=readable_result
    )

    return results


def main():
    args = demisto.args()

    try:
        return_results(get_disk_space(args))

    except Exception as ex:
        demisto.error(traceback.format_exc())  # print the traceback
        return_error(
            f"Failed to execute PAN-OS-GetDeviceDiskSpace. Error: {str(ex)}\n"
            f"Traceback: {fix_traceback_line_numbers(traceback.format_exc())}"
        )


if __name__ in ("__main__", "__builtin__", "builtins"):
    main()