Add method for checking OS version.
This commit is contained in:
parent
62d1724db6
commit
5b14f8d820
4 changed files with 64 additions and 0 deletions
|
|
@ -5,6 +5,7 @@ the microscope, server, and thing states to the web API.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
|
|
@ -22,6 +23,8 @@ from openflexure_microscope_server.utilities import VersionData, robust_version_
|
||||||
SHUTDOWN_CMD = ["sudo", "shutdown", "-h", "now"]
|
SHUTDOWN_CMD = ["sudo", "shutdown", "-h", "now"]
|
||||||
REBOOT_CMD = ["sudo", "shutdown", "-r", "now"]
|
REBOOT_CMD = ["sudo", "shutdown", "-r", "now"]
|
||||||
|
|
||||||
|
OS_VERSION_FILE = "/usr/lib/os-release"
|
||||||
|
|
||||||
|
|
||||||
class CommandOutput(BaseModel):
|
class CommandOutput(BaseModel):
|
||||||
"""A pydantic model passing the STDOUT and STDERR from a subprocess over HTTP."""
|
"""A pydantic model passing the STDOUT and STDERR from a subprocess over HTTP."""
|
||||||
|
|
@ -81,6 +84,24 @@ class OpenFlexureSystem(lt.Thing):
|
||||||
"""Return True if running on a Raspberry Pi."""
|
"""Return True if running on a Raspberry Pi."""
|
||||||
return os.path.exists("/usr/bin/raspi-config")
|
return os.path.exists("/usr/bin/raspi-config")
|
||||||
|
|
||||||
|
@lt.property
|
||||||
|
def os_version(self) -> Optional[str]:
|
||||||
|
"""Return the OS version of the Pi. Returns None if not on a Pi."""
|
||||||
|
if not self.is_raspberrypi:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if not os.path.isfile(OS_VERSION_FILE):
|
||||||
|
return "unknown"
|
||||||
|
|
||||||
|
with open(OS_VERSION_FILE, "r", encoding="utf-8") as os_file:
|
||||||
|
os_data = os_file.read()
|
||||||
|
|
||||||
|
version_match = re.search(r"^VERSION_CODENAME=(.+)$", os_data, re.MULTILINE)
|
||||||
|
if not version_match:
|
||||||
|
return "unknown"
|
||||||
|
|
||||||
|
return version_match.group(1)
|
||||||
|
|
||||||
@lt.action
|
@lt.action
|
||||||
def shutdown(self) -> CommandOutput:
|
def shutdown(self) -> CommandOutput:
|
||||||
"""Attempt to shutdown the device."""
|
"""Attempt to shutdown the device."""
|
||||||
|
|
|
||||||
10
tests/unit_tests/assets/os-release
Normal file
10
tests/unit_tests/assets/os-release
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
|
||||||
|
NAME="Debian GNU/Linux"
|
||||||
|
VERSION_ID="13"
|
||||||
|
VERSION="13 (trixie)"
|
||||||
|
VERSION_CODENAME=trixie
|
||||||
|
DEBIAN_VERSION_FULL=13.4
|
||||||
|
ID=debian
|
||||||
|
HOME_URL="https://www.debian.org/"
|
||||||
|
SUPPORT_URL="https://www.debian.org/support"
|
||||||
|
BUG_REPORT_URL="https://bugs.debian.org/"
|
||||||
1
tests/unit_tests/assets/os-release-broken
Normal file
1
tests/unit_tests/assets/os-release-broken
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
This doesn't contain the data we are looking for.
|
||||||
|
|
@ -11,6 +11,11 @@ from labthings_fastapi.testing import create_thing_without_server
|
||||||
from openflexure_microscope_server.things import system
|
from openflexure_microscope_server.things import system
|
||||||
from openflexure_microscope_server.utilities import VersionData, robust_version_strings
|
from openflexure_microscope_server.utilities import VersionData, robust_version_strings
|
||||||
|
|
||||||
|
THIS_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
FAKE_OS_FILE = os.path.join(THIS_DIR, "assets", "os-release")
|
||||||
|
BROKEN_OS_FILE = os.path.join(THIS_DIR, "assets", "os-release-broken")
|
||||||
|
MISSING_OS_FILE = os.path.join(THIS_DIR, "assets", "this-does-not-exist")
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def system_thing():
|
def system_thing():
|
||||||
|
|
@ -37,6 +42,33 @@ def test_is_raspberry(system_thing):
|
||||||
assert system_thing.is_raspberrypi == _is_raspberrypi()
|
assert system_thing.is_raspberrypi == _is_raspberrypi()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("version_file", "expected_result"),
|
||||||
|
[
|
||||||
|
(MISSING_OS_FILE, "unknown"),
|
||||||
|
(FAKE_OS_FILE, "trixie"),
|
||||||
|
(BROKEN_OS_FILE, "unknown"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_os_version_pi(version_file, expected_result, system_thing, mocker):
|
||||||
|
"""Check reading the operating system version from a Pi (mocked!)."""
|
||||||
|
type(system_thing).is_raspberrypi = mocker.PropertyMock(return_value=True)
|
||||||
|
|
||||||
|
mocker.patch(
|
||||||
|
"openflexure_microscope_server.things.system.OS_VERSION_FILE", version_file
|
||||||
|
)
|
||||||
|
assert system_thing.os_version == expected_result
|
||||||
|
|
||||||
|
|
||||||
|
def test_os_version_not_pi(system_thing, mocker):
|
||||||
|
"""Check reading the operating system when not on a Pi returns None."""
|
||||||
|
mocker.patch(
|
||||||
|
"openflexure_microscope_server.things.system.OS_VERSION_FILE", FAKE_OS_FILE
|
||||||
|
)
|
||||||
|
type(system_thing).is_raspberrypi = mocker.PropertyMock(return_value=False)
|
||||||
|
assert system_thing.os_version is None
|
||||||
|
|
||||||
|
|
||||||
def test_version_data(system_thing):
|
def test_version_data(system_thing):
|
||||||
"""Check VersionData is returned.
|
"""Check VersionData is returned.
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue