diff --git a/defaults/main.yaml b/defaults/main.yaml index a2aa348..fa4e99e 100644 --- a/defaults/main.yaml +++ b/defaults/main.yaml @@ -11,6 +11,7 @@ cosmostat_packages: - python3-venv - lm-sensors - jc + - smartmontools # python venv packages cosmostat_venv_packages: | @@ -25,6 +26,7 @@ cosmostat_venv_packages: | # cosmostat sudoers file cosmostat_sudoers_content: | cosmos ALL=(root) NOPASSWD: /usr/bin/lshw + cosmos ALL=(root) NOPASSWD: /usr/sbin/smartctl # subnet for service docker_subnet: "192.168.37.0/24" diff --git a/files/api/Components.py b/files/api/Components.py index 98c35f4..2145458 100644 --- a/files/api/Components.py +++ b/files/api/Components.py @@ -20,9 +20,11 @@ component_types = [{"name": entry["name"], "multi_check": entry["multi_check"] = class Component: - def __init__(self, name: str, comp_type: str ): + def __init__(self, name: str, comp_type: str, this_device="None"): self.name = name self.type = comp_type + self.this_device = this_device + print(f"This device - {self.this_device}") for component in component_class_tree: if component["name"] == self.type: COMPONENT_DESCRIPTORS = component @@ -39,7 +41,12 @@ class Component: self.multi_check = self.is_multi() self._properties: Dict[str, str] = {} for key, command in descriptor.get('properties', {}).items(): - self._properties[key] = run_command(command, True) + if self.this_device != "None": + print(f"command - {command}; this_device - {self.this_device}") + formatted_command = command.format(this_device=self.this_device) + self._properties[key] = run_command(formatted_command, True) + else: + self._properties[key] = run_command(command, True) # build the description string self._description_template: str | None = descriptor.get("description") self.description = self._description_template.format(**self._properties) @@ -59,7 +66,11 @@ class Component: def update_metrics(self): for key, command in self._descriptor.get('metrics', {}).items(): - self._metrics[key] = run_command(command, True) + if self.this_device != "None": + formatted_command = command.format(this_device=self.this_device) + self._properties[key] = run_command(formatted_command, True) + else: + self._metrics[key] = run_command(command, True) # complex data type return def get_metrics(self, type = None): @@ -207,15 +218,25 @@ class System: for component in component_types: component_name = component["name"] multi_check = component["multi_check"] + # if multi, note that the command in device_list creates the list of things to pipe into this_device if multi_check: - print("placeholder...") + letters = [chr(c) for c in range(ord('a'), ord('z')+1)] + print(f"Creating one component of type {component_name} for each one found") + component_type_device_list = get_device_list(component_name) + + for this_device in component_type_device_list: + this_component_letter = letters[component_type_device_list.index(this_device)] + this_component_name = f"{this_device}_{this_component_letter}" + print(f"{this_component_name} - {component_name} - {this_device}") + self.add_components(Component(this_component_name, component_name, this_device)) + else: if debug_output: print(f"Creating component {component["name"]}") self.add_components(Component(component_name, component_name)) # Add a component to the system - def add_components(self, component: Component): + def add_components(self, component: Component,): if debug_output: print(f"Component description: {component.description}") self.components.append(component) @@ -357,3 +378,13 @@ def run_command(cmd, zero_only=False): return output_lines[0] if zero_only else output_lines except: return output_lines + +def get_device_list(device_type_name: str): + result = [] + for component in component_class_tree: + if component["name"] == device_type_name: + device_list_command = component["device_list"] + device_list_result = run_command(device_list_command) + result = device_list_result + + return result diff --git a/files/api/component_descriptors.json b/files/api/component_descriptors.json index 028f969..13945a1 100644 --- a/files/api/component_descriptors.json +++ b/files/api/component_descriptors.json @@ -25,5 +25,22 @@ "used_capacity_mb": "free -m | grep Mem | awk '{print $3}'", "free_capacity_mb": "free -m | grep Mem | awk '{print $4}'" } + }, + { + "name": "Block_Storage", + "description": "{device_id} is of type {drive_type} with capacity of {drive_capacity}.", + "multi_check": "True", + "device_list": "lsblk -d -o NAME,SIZE | grep -v -e 0B -e NAME | awk '{print $1}'", + "properties": { + "device_name": "lsblk -d -o NAME,SIZE | grep -v -e 0B -e NAME | awk '{{print $1}}' | grep {this_device}", + "device_id": "lsblk -d -o NAME,SIZE | grep -v -e 0B -e NAME | awk '{{print \"/dev/\"$1}}' | grep {this_device}", + "drive_type": "lsblk -d -o NAME,TRAN | grep {this_device} | awk '{{print $2}}'", + "drive_capacity": "lsblk -d -o NAME,SIZE | grep {this_device} | awk '{{print $2}}'" + }, + "metrics": { + "smart_status": "sudo smartctl -x --json /dev/{this_device} | jq -r .smart_status.passed", + "ssd_endurance_string": "sudo smartctl -x --json /dev/{this_device} | jq -r '.physical_block_size as $block |.ata_device_statistics.pages[] | select(.name == \"General Statistics\") | .table[] | select(.name == \"Logical Sectors Written\") | .value as $sectors | ($sectors * $block) / 1073741824 ' | awk '{{printf \"%.2f GiB Written\\n\", $0}}' || true", + "nvme_endurance_string": "sudo smartctl -x --json /dev/{this_device} | jq -r ' .nvme_smart_health_information_log.data_units_written as $dw | .logical_block_size as $ls | ($dw * $ls) / 1073741824 ' | awk '{{printf \"%.2f GiB Written\\n\", $0}}' || true" + } } ] \ No newline at end of file diff --git a/files/web/html/test-2.html b/files/web/html/test-2.html deleted file mode 100644 index af6e01d..0000000 --- a/files/web/html/test-2.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - Matt-Cloud Cosmostat - - - - - -
-

Matt-Cloud Cosmostat Dashboard

- This dashboard shows the local Matt-Cloud system stats.

-

-
-

System Stats

-
Connecting…
-
- - - - - - - - \ No newline at end of file diff --git a/files/web/html/test.html b/files/web/html/test.html deleted file mode 100644 index 512cf31..0000000 --- a/files/web/html/test.html +++ /dev/null @@ -1,181 +0,0 @@ - - - - - Matt-Cloud Cosmostat - - - - - -
-

Matt-Cloud Cosmostat Dashboard

- This dashboard shows the local Matt-Cloud system stats.

-

-
-

System Stats

-
Connecting...
-
- -
-

System Graphs

-
-
- -
-
-
- - - - - - - - \ No newline at end of file