diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 96ba572..4beb4ca 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,6 +21,7 @@ jobs: pylint python3-dbus python3-dbus-python-client-gen + python3-justbytes python3-matplotlib python3-numpy python3-pygithub diff --git a/.github/workflows/weekly.yml b/.github/workflows/weekly.yml index 081b927..849d451 100644 --- a/.github/workflows/weekly.yml +++ b/.github/workflows/weekly.yml @@ -19,6 +19,7 @@ jobs: pylint python3-dbus python3-dbus-python-client-gen + python3-justbytes python3-matplotlib python3-numpy python3-pygithub diff --git a/misc_scripts/pool_metadata_size_estimate.py b/misc_scripts/pool_metadata_size_estimate.py new file mode 100755 index 0000000..e5a5267 --- /dev/null +++ b/misc_scripts/pool_metadata_size_estimate.py @@ -0,0 +1,117 @@ +#!/usr/bin/python3 +""" +pool_metadata_size_estimate: estimate the inrease of pool level metadata due +to addition of blockdevs. +""" + +# isort: STDLIB +import argparse + +# isort: THIRDPARTY +from justbytes import Range + +STRING = 255 +UUID = 36 + + +def metadata_str(value): + """ + Parse a value representing the size of a metadata string. + """ + value = int(value) + if value > 255: + raise argparse.ArgumentTypeError( + f"Exceeds maximum length {STRING} for metadata string." + ) + + if value < 0: + raise argparse.ArgumentTypeError("Negative lengths prohbited.") + + return value + + +def nat(value): + """ + Parse a value representing a natural number. + """ + value = int(value) + if value < 0: + raise argparse.ArgumentTypeError("Must be a natural number.") + return value + + +def gen_parser(): + """ + Generate parser. + """ + parser = argparse.ArgumentParser( + description=( + "Calculate size increase in Stratis pool-level metadata due to " + "addition of new devices." + ) + ) + + parser.add_argument( + "num_devices", + help="Number of devices to be added", + type=nat, + ) + + parser.add_argument( + "--hardware-info", + dest="hardware_info", + help="Bytes required to represent hardware info.", + type=metadata_str, + ) + + parser.add_argument( + "--user-info", + dest="user_info", + help="Bytes required to represent user info.", + type=metadata_str, + ) + + return parser + + +def f(*, hardware_info=None, user_info=None): + """ + Calculate the bytes required to store num_devices in metadata. + + :param hardware_info: the len of the hardware info + :param user_info: the len of the user info + """ + commas = (0 if hardware_info is None else 1) + (0 if user_info is None else 1) + + m = ( + commas + + (0 if hardware_info is None else hardware_info + 18) + + (0 if user_info is None else user_info + 13) + + (UUID + 9) + + 3 + ) + + return m + + +def main(): + """ + Main method + """ + + parser = gen_parser() + args = parser.parse_args() + + num_devices = args.num_devices + + user_info = args.user_info + hardware_info = args.hardware_info + + m = f(hardware_info=hardware_info, user_info=user_info) + print(f"Slope: {m} bytes") + prediction = m * num_devices + print(f"Predicted use: {prediction} bytes, approx {Range(prediction)}") + + +if __name__ == "__main__": + main()