mirror of
https://github.com/osm-search/Nominatim.git
synced 2026-02-16 15:47:58 +00:00
made collect_os_info script in Python
This commit is contained in:
158
utils/collect_os_info.py
Normal file
158
utils/collect_os_info.py
Normal file
@@ -0,0 +1,158 @@
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import Optional, Union
|
||||
|
||||
# external requirement
|
||||
import psutil
|
||||
|
||||
# from nominatim.version import NOMINATIM_VERSION
|
||||
# from nominatim.db.connection import connect
|
||||
|
||||
|
||||
class ReportSystemInformation:
|
||||
"""Generate a report about the host system including software versions, memory,
|
||||
storage, and database configuration."""
|
||||
def __init__(self):
|
||||
self._memory: int = psutil.virtual_memory().total
|
||||
self.friendly_memory: str = self._friendly_memory_string(self._memory)
|
||||
# psutil.cpu_count(logical=False) returns the number of CPU cores.
|
||||
# For number of logical cores (Hypthreaded), call psutil.cpu_count() or os.cpu_count()
|
||||
self.num_cpus: int = psutil.cpu_count(logical=False)
|
||||
self.os_info: str = self._os_name_info()
|
||||
|
||||
### These are commented out because they have not been tested.
|
||||
# self.nominatim_ver: str = '{0[0]}.{0[1]}.{0[2]}-{0[3]}'.format(NOMINATIM_VERSION)
|
||||
# self._pg_version = conn.server_version_tuple()
|
||||
# self._postgis_version = conn.postgis_version_tuple()
|
||||
# self.postgresql_ver: str = self._convert_version(self._pg_version)
|
||||
# self.postgis_ver: str = self._convert_version(self._postgis_version)
|
||||
|
||||
self.nominatim_ver: str = ""
|
||||
self.postgresql_ver: str = ""
|
||||
self.postgresql_config: str = ""
|
||||
self.postgis_ver: str = ""
|
||||
|
||||
# the below commands require calling the shell to gather information
|
||||
self.disk_free: str = self._run_command(["df", "-h"])
|
||||
self.lsblk: str = self._run_command("lsblk")
|
||||
# psutil.disk_partitions() <- this function is similar to the above, but it is cross platform
|
||||
|
||||
# Note: `systemd-detect-virt` command only works on Linux, on other OSes
|
||||
# should give a message: "Unknown (unable to find the 'systemd-detect-virt' command)"
|
||||
self.container_vm_env: str = self._run_command("systemd-detect-virt")
|
||||
|
||||
def _convert_version(self, ver_tup: tuple) -> str:
|
||||
"""converts tuple version (ver_tup) to a string representation"""
|
||||
return ".".join(map(str,ver_tup))
|
||||
|
||||
def _friendly_memory_string(self, mem: int) -> str:
|
||||
"""Create a user friendly string for the amount of memory specified as mem"""
|
||||
mem_magnitude = ('bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB')
|
||||
mag = 0
|
||||
# determine order of magnitude
|
||||
while mem > 1000:
|
||||
mem /= 1000
|
||||
mag += 1
|
||||
|
||||
return f"{mem:.1f} {mem_magnitude[mag]}"
|
||||
|
||||
|
||||
def _run_command(self, cmd: Union[str, list]) -> str:
|
||||
"""Runs a command using the shell and returns the output from stdout"""
|
||||
try:
|
||||
if sys.version_info < (3, 7):
|
||||
cap_out = subprocess.run(cmd, stdout=subprocess.PIPE)
|
||||
else:
|
||||
cap_out = subprocess.run(cmd, capture_output=True)
|
||||
return cap_out.stdout.decode("utf-8")
|
||||
except FileNotFoundError:
|
||||
# non-Linux system should end up here
|
||||
return f"Unknown (unable to find the '{cmd}' command)"
|
||||
|
||||
|
||||
def _os_name_info(self) -> str:
|
||||
"""Obtain Operating System Name (and possibly the version)"""
|
||||
|
||||
os_info = None
|
||||
# man page os-release(5) details meaning of the fields
|
||||
if Path("/etc/os-release").is_file():
|
||||
os_info = self._from_file_find_line_portion("/etc/os-release", "PRETTY_NAME", "=")
|
||||
# alternative location
|
||||
elif Path("/usr/lib/os-release").is_file():
|
||||
os_info = self._from_file_find_line_portion("/usr/lib/os-release", "PRETTY_NAME", "=")
|
||||
|
||||
# fallback on Python's os name
|
||||
if(os_info is None or os_info == ""):
|
||||
os_info = os.name
|
||||
|
||||
# if the above is insufficient, take a look at neofetch's approach to OS detection
|
||||
return os_info
|
||||
|
||||
|
||||
# Note: Intended to be used on informational files like /proc
|
||||
def _from_file_find_line_portion(self, filename: str, start: str, sep: str,
|
||||
fieldnum: int = 1) -> Optional[str]:
|
||||
"""open filename, finds the line starting with the 'start' string.
|
||||
Splits the line using seperator and returns a "fieldnum" from the split."""
|
||||
with open(filename) as fh:
|
||||
for line in fh:
|
||||
if line.startswith(start):
|
||||
result = line.split(sep)[fieldnum].strip()
|
||||
return result
|
||||
|
||||
def report(self, out = sys.stdout, err = sys.stderr) -> None:
|
||||
"""Generates the Markdown report.
|
||||
|
||||
Optionally pass out or err parameters to redirect the output of stdout
|
||||
and stderr to other file objects."""
|
||||
|
||||
# NOTE: This should be a report format. Any conversions or lookup has be
|
||||
# done, do that action in the __init__() or another function.
|
||||
message = """
|
||||
Use this information in your issue report at https://github.com/osm-search/Nominatim/issues
|
||||
Copy and paste or redirect the output of the file:
|
||||
$ ./collect_os_info.py > report.md
|
||||
"""
|
||||
report = f"""
|
||||
**Software Environment:**
|
||||
- Python version: {sys.version}
|
||||
- Nominatim version: {self.nominatim_ver}
|
||||
- PostgreSQL version: {self.postgresql_ver}
|
||||
- PostGIS version: {self.postgis_ver}
|
||||
- OS: {self.os_info}
|
||||
|
||||
|
||||
**Hardware Configuration:**
|
||||
- RAM: {self.friendly_memory}
|
||||
- number of CPUs: {self.num_cpus}
|
||||
- bare metal/AWS/other cloud service (per systemd-detect-virt(1)): {self.container_vm_env}
|
||||
- type and size of disks:
|
||||
**`df -h` - df - report file system disk space usage: **
|
||||
```
|
||||
{self.disk_free}
|
||||
```
|
||||
|
||||
**lsblk - list block devices: **
|
||||
```
|
||||
{self.lsblk}
|
||||
```
|
||||
|
||||
|
||||
**Postgresql Configuration:**
|
||||
```
|
||||
{self.postgresql_config}
|
||||
```
|
||||
**Notes**
|
||||
Please add any notes about anything above anything above that is incorrect.
|
||||
"""
|
||||
|
||||
print(message, file = err)
|
||||
print(report, file = out)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys_info = ReportSystemInformation()
|
||||
sys_info.report()
|
||||
Reference in New Issue
Block a user