modified by Fusco, blame him it it does not work
This commit is contained in:
@@ -2,7 +2,6 @@ import subprocess
|
|||||||
import csv
|
import csv
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import re
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
# Configuration parameters
|
# Configuration parameters
|
||||||
@@ -17,7 +16,6 @@ OUTPUT_FILE = "/root/zpool_iostat.csv"
|
|||||||
def update_csv_file(output_file, data):
|
def update_csv_file(output_file, data):
|
||||||
"""
|
"""
|
||||||
Writes data to a CSV file and rotates the file if necessary.
|
Writes data to a CSV file and rotates the file if necessary.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
output_file (str): Path to the CSV file where data will be written.
|
output_file (str): Path to the CSV file where data will be written.
|
||||||
data (list): The data to be written to the file.
|
data (list): The data to be written to the file.
|
||||||
@@ -27,11 +25,9 @@ def update_csv_file(output_file, data):
|
|||||||
with open(output_file, "w", newline="") as csv_file:
|
with open(output_file, "w", newline="") as csv_file:
|
||||||
fieldnames = data[0].keys() if data else []
|
fieldnames = data[0].keys() if data else []
|
||||||
csv_writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
|
csv_writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
|
||||||
|
|
||||||
csv_writer.writeheader()
|
csv_writer.writeheader()
|
||||||
for row in data:
|
for row in data:
|
||||||
csv_writer.writerow(row)
|
csv_writer.writerow(row)
|
||||||
|
|
||||||
print(f"Data successfully written to {output_file}")
|
print(f"Data successfully written to {output_file}")
|
||||||
rotate_file_if_needed(output_file)
|
rotate_file_if_needed(output_file)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -41,7 +37,6 @@ def update_csv_file(output_file, data):
|
|||||||
def rotate_file_if_needed(file_path):
|
def rotate_file_if_needed(file_path):
|
||||||
"""
|
"""
|
||||||
Rotates the file if it exceeds a specified size. The existing file is renamed to '.old'.
|
Rotates the file if it exceeds a specified size. The existing file is renamed to '.old'.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
file_path (str): Path to the file that should be rotated.
|
file_path (str): Path to the file that should be rotated.
|
||||||
"""
|
"""
|
||||||
@@ -61,10 +56,8 @@ def rotate_file_if_needed(file_path):
|
|||||||
def load_existing_data(file_path):
|
def load_existing_data(file_path):
|
||||||
"""
|
"""
|
||||||
Loads existing data from a CSV file.
|
Loads existing data from a CSV file.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
file_path (str): Path to the CSV file.
|
file_path (str): Path to the CSV file.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list: The data loaded from the file, or an empty list if the file doesn't exist or an error occurs.
|
list: The data loaded from the file, or an empty list if the file doesn't exist or an error occurs.
|
||||||
"""
|
"""
|
||||||
@@ -86,10 +79,8 @@ def load_existing_data(file_path):
|
|||||||
def remove_k(value_with_unit):
|
def remove_k(value_with_unit):
|
||||||
"""
|
"""
|
||||||
Removes the 'K' unit from a value, if present, from the IOPS section.
|
Removes the 'K' unit from a value, if present, from the IOPS section.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
value_with_unit (str): The string containing the value and possibly a 'K' unit.
|
value_with_unit (str): The string containing the value and possibly a 'K' unit.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
float: The numerical value, with 'K' removed if it was present.
|
float: The numerical value, with 'K' removed if it was present.
|
||||||
"""
|
"""
|
||||||
@@ -102,24 +93,20 @@ def remove_k(value_with_unit):
|
|||||||
def convert_to_mib(value_with_unit):
|
def convert_to_mib(value_with_unit):
|
||||||
"""
|
"""
|
||||||
Converts a value with a unit (K, M, G, T) to MiB.
|
Converts a value with a unit (K, M, G, T) to MiB.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
value_with_unit (str): The string containing the value and unit.
|
value_with_unit (str): The string containing the value and unit.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
float: The value converted to MiB, or 0 if the input is invalid.
|
float: The value converted to MiB, or 0 if the input is invalid.
|
||||||
"""
|
"""
|
||||||
# Check if the string is valid
|
# Check if the string is valid
|
||||||
if not value_with_unit or not value_with_unit[-1].isalpha():
|
if not value_with_unit or not value_with_unit[-1].isalpha():
|
||||||
return 0.0
|
return 0.0
|
||||||
|
|
||||||
# Extract the unit and value
|
# Extract the unit and value
|
||||||
unit = value_with_unit[-1].upper() # Ensure unit is uppercase for consistency
|
unit = value_with_unit[-1].upper() # Ensure unit is uppercase for consistency
|
||||||
try:
|
try:
|
||||||
value = float(value_with_unit[:-1])
|
value = float(value_with_unit[:-1])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return 0.0
|
return 0.0
|
||||||
|
|
||||||
# Convert based on the unit
|
# Convert based on the unit
|
||||||
if unit == "K":
|
if unit == "K":
|
||||||
return round(value / 1024.0, 1) # Convert KiB to MiB
|
return round(value / 1024.0, 1) # Convert KiB to MiB
|
||||||
@@ -138,40 +125,32 @@ def convert_time_to_ms(value_with_unit):
|
|||||||
"""
|
"""
|
||||||
Converts a time value with a unit (ms, us, ns) to milliseconds (ms), rounded to three decimal places.
|
Converts a time value with a unit (ms, us, ns) to milliseconds (ms), rounded to three decimal places.
|
||||||
Returns 0 if the input is '-', indicating no data.
|
Returns 0 if the input is '-', indicating no data.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
value_with_unit (str): The string containing the value and unit.
|
value_with_unit (str): The string containing the value and unit.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
float: The value converted to milliseconds (ms), rounded to three decimal places, or 0 if the input is invalid or '-'.
|
float: The value converted to milliseconds (ms), rounded to three decimal places, or 0 if the input is invalid or '-'.
|
||||||
"""
|
"""
|
||||||
if value_with_unit == "-":
|
if value_with_unit == "-":
|
||||||
# Handle no data case
|
# Handle no data case
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Strip and lower case to normalize
|
# Strip and lower case to normalize
|
||||||
value_with_unit = value_with_unit.strip().lower()
|
value_with_unit = value_with_unit.strip().lower()
|
||||||
|
|
||||||
# Check for nanoseconds
|
# Check for nanoseconds
|
||||||
if value_with_unit.endswith("ns"):
|
if value_with_unit.endswith("ns"):
|
||||||
value = float(value_with_unit[:-2])
|
value = float(value_with_unit[:-2])
|
||||||
return round(value / 1e6, 1) # Convert ns to ms and round
|
return round(value / 1e6, 1) # Convert ns to ms and round
|
||||||
|
|
||||||
# Check for microseconds
|
# Check for microseconds
|
||||||
elif value_with_unit.endswith("us"):
|
elif value_with_unit.endswith("us"):
|
||||||
value = float(value_with_unit[:-2])
|
value = float(value_with_unit[:-2])
|
||||||
return round(value / 1000.0, 1) # Convert us to ms and round
|
return round(value / 1000.0, 1) # Convert us to ms and round
|
||||||
|
|
||||||
# Check for milliseconds
|
# Check for milliseconds
|
||||||
elif value_with_unit.endswith("ms"):
|
elif value_with_unit.endswith("ms"):
|
||||||
value = float(value_with_unit[:-2])
|
value = float(value_with_unit[:-2])
|
||||||
return round(value, 3) # Already in ms and round
|
return round(value, 3) # Already in ms and round
|
||||||
|
|
||||||
# If no known unit, assume it's in milliseconds and round
|
# If no known unit, assume it's in milliseconds and round
|
||||||
else:
|
else:
|
||||||
return round(float(value_with_unit), 1)
|
return round(float(value_with_unit), 1)
|
||||||
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# Log the error if conversion fails
|
# Log the error if conversion fails
|
||||||
print(f"Warning: Unrecognized or malformed time value '{value_with_unit}'.")
|
print(f"Warning: Unrecognized or malformed time value '{value_with_unit}'.")
|
||||||
@@ -182,27 +161,22 @@ def parse_iostat_output(output):
|
|||||||
"""
|
"""
|
||||||
Parses the output of the `zpool iostat` command to include pool, vdev, disk level data,
|
Parses the output of the `zpool iostat` command to include pool, vdev, disk level data,
|
||||||
and does not specifically skip the 'logs' line.
|
and does not specifically skip the 'logs' line.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
output (str): The output string from the `zpool iostat` command.
|
output (str): The output string from the `zpool iostat` command.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list: A list of dictionaries, each representing an entity (pool, vdev, or disk) and its metrics.
|
list: A list of dictionaries, each representing an entity (pool, vdev, or disk) and its metrics.
|
||||||
"""
|
"""
|
||||||
parsed_data = []
|
parsed_data = []
|
||||||
lines = output.strip().split("\n")
|
lines = output.strip().split("\n")
|
||||||
data_started = False
|
data_started = False
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
if "capacity" in line and "operations" in line and "bandwidth" in line:
|
if "capacity" in line and "operations" in line and "bandwidth" in line:
|
||||||
# This line indicates the end of the headers and the start of relevant data.
|
# This line indicates the end of the headers and the start of relevant data.
|
||||||
data_started = True
|
data_started = True
|
||||||
continue # Skip the header line itself
|
continue # Skip the header line itself
|
||||||
|
|
||||||
if data_started and "-----" in line or line.startswith("pool"):
|
if data_started and "-----" in line or line.startswith("pool"):
|
||||||
# Skip separator lines and the column headers repeated in the output.
|
# Skip separator lines and the column headers repeated in the output.
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if data_started:
|
if data_started:
|
||||||
# Process lines containing pool, vdev, and disk level data.
|
# Process lines containing pool, vdev, and disk level data.
|
||||||
fields = line.split()
|
fields = line.split()
|
||||||
@@ -216,7 +190,6 @@ def parse_iostat_output(output):
|
|||||||
):
|
):
|
||||||
# Skip lines that do not contain numeric data where expected.
|
# Skip lines that do not contain numeric data where expected.
|
||||||
continue
|
continue
|
||||||
|
|
||||||
data_entry = {
|
data_entry = {
|
||||||
"time": time.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
"time": time.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||||
"name": fields[0],
|
"name": fields[0],
|
||||||
@@ -263,7 +236,6 @@ def parse_iostat_output(output):
|
|||||||
parsed_data.append(data_entry)
|
parsed_data.append(data_entry)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error processing line: '{line}' - {e}")
|
print(f"Error processing line: '{line}' - {e}")
|
||||||
|
|
||||||
return parsed_data
|
return parsed_data
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user