mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2025-12-13 01:30:31 +08:00
using dbus_next
This commit is contained in:
parent
e566364b75
commit
d83e32fc51
1
PKGBUILD
1
PKGBUILD
@ -50,6 +50,7 @@ depends=(
|
|||||||
python-netifaces
|
python-netifaces
|
||||||
python-systemd
|
python-systemd
|
||||||
python-dbus
|
python-dbus
|
||||||
|
python-dbus-next
|
||||||
python-pygments
|
python-pygments
|
||||||
python-pyghmi
|
python-pyghmi
|
||||||
python-pam
|
python-pam
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import asyncio
|
||||||
|
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
@ -31,9 +32,10 @@ from ....logging import get_logger
|
|||||||
from ....yamlconf import Section
|
from ....yamlconf import Section
|
||||||
from ....yamlconf.loader import load_yaml_file
|
from ....yamlconf.loader import load_yaml_file
|
||||||
|
|
||||||
|
from .... import tools
|
||||||
from .... import aiotools
|
from .... import aiotools
|
||||||
|
|
||||||
from ..sysunit import get_service_status
|
from .. import sysunit
|
||||||
|
|
||||||
from .base import BaseInfoSubmanager
|
from .base import BaseInfoSubmanager
|
||||||
|
|
||||||
@ -44,37 +46,57 @@ class ExtrasInfoSubmanager(BaseInfoSubmanager):
|
|||||||
self.__global_config = global_config
|
self.__global_config = global_config
|
||||||
|
|
||||||
async def get_state(self) -> Optional[Dict]:
|
async def get_state(self) -> Optional[Dict]:
|
||||||
return (await aiotools.run_async(self.__inner_get_state))
|
|
||||||
|
|
||||||
# =====
|
|
||||||
|
|
||||||
def __inner_get_state(self) -> Optional[Dict]:
|
|
||||||
try:
|
try:
|
||||||
extras_path = self.__global_config.kvmd.info.extras
|
sui = sysunit.SystemdUnitInfo()
|
||||||
|
await sui.open()
|
||||||
|
except Exception as err:
|
||||||
|
get_logger(0).error("Can't open systemd bus to get extras state: %s", tools.efmt(err))
|
||||||
|
sui = None
|
||||||
|
try:
|
||||||
extras: Dict[str, Dict] = {}
|
extras: Dict[str, Dict] = {}
|
||||||
for name in os.listdir(extras_path):
|
for extra in (await asyncio.gather(*[
|
||||||
if name[0] != "." and os.path.isdir(os.path.join(extras_path, name)):
|
self.__read_extra(sui, name)
|
||||||
app = re.sub(r"[^a-zA-Z0-9_]+", "_", name)
|
for name in os.listdir(self.__get_extras_path())
|
||||||
extras[app] = load_yaml_file(os.path.join(extras_path, name, "manifest.yaml"))
|
if name[0] != "." and os.path.isdir(self.__get_extras_path(name))
|
||||||
self.__rewrite_app_daemon(extras[app])
|
])):
|
||||||
self.__rewrite_app_port(extras[app])
|
extras.update(extra)
|
||||||
return extras
|
return extras
|
||||||
except Exception:
|
except Exception:
|
||||||
get_logger(0).exception("Can't parse extras")
|
get_logger(0).exception("Can't read extras")
|
||||||
return None
|
return None
|
||||||
|
finally:
|
||||||
|
if sui is not None:
|
||||||
|
await sui.close()
|
||||||
|
|
||||||
def __rewrite_app_daemon(self, extras: Dict) -> None:
|
def __get_extras_path(self, *parts: str) -> str:
|
||||||
daemon = extras.get("daemon", "")
|
return os.path.join(self.__global_config.kvmd.info.extras, *parts)
|
||||||
|
|
||||||
|
async def __read_extra(self, sui: Optional[sysunit.SystemdUnitInfo], name: str) -> Dict:
|
||||||
|
try:
|
||||||
|
extra = await aiotools.run_async(load_yaml_file, self.__get_extras_path(name, "manifest.yaml"))
|
||||||
|
await self.__rewrite_app_daemon(sui, extra)
|
||||||
|
self.__rewrite_app_port(extra)
|
||||||
|
return {re.sub(r"[^a-zA-Z0-9_]+", "_", name): extra}
|
||||||
|
except Exception:
|
||||||
|
get_logger(0).exception("Can't read extra %r", name)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
async def __rewrite_app_daemon(self, sui: Optional[sysunit.SystemdUnitInfo], extra: Dict) -> None:
|
||||||
|
daemon = extra.get("daemon", "")
|
||||||
if isinstance(daemon, str) and daemon.strip():
|
if isinstance(daemon, str) and daemon.strip():
|
||||||
status = get_service_status(daemon)
|
extra["enabled"] = extra["started"] = False
|
||||||
(extras["enabled"], extras["started"]) = (status if status is not None else (False, False))
|
if sui is not None:
|
||||||
|
try:
|
||||||
|
(extra["enabled"], extra["started"]) = await sui.get_status(daemon)
|
||||||
|
except Exception as err:
|
||||||
|
get_logger(0).error("Can't get info about the service %r: %s", daemon, tools.efmt(err))
|
||||||
|
|
||||||
def __rewrite_app_port(self, extras: Dict) -> None:
|
def __rewrite_app_port(self, extra: Dict) -> None:
|
||||||
port_path = extras.get("port", "")
|
port_path = extra.get("port", "")
|
||||||
if isinstance(port_path, str) and port_path.strip():
|
if isinstance(port_path, str) and port_path.strip():
|
||||||
extras["port"] = 0
|
extra["port"] = 0
|
||||||
config = self.__global_config
|
config = self.__global_config
|
||||||
for item in filter(None, map(str.strip, port_path.split("/"))):
|
for item in filter(None, map(str.strip, port_path.split("/"))):
|
||||||
config = getattr(config, item, None) # type: ignore
|
config = getattr(config, item, None) # type: ignore
|
||||||
if isinstance(config, int):
|
if isinstance(config, int):
|
||||||
extras["port"] = config
|
extra["port"] = config
|
||||||
|
|||||||
@ -31,10 +31,11 @@ import aiohttp
|
|||||||
|
|
||||||
from ....logging import get_logger
|
from ....logging import get_logger
|
||||||
|
|
||||||
|
from .... import tools
|
||||||
from .... import aiotools
|
from .... import aiotools
|
||||||
from .... import htclient
|
from .... import htclient
|
||||||
|
|
||||||
from ..sysunit import get_service_status
|
from .. import sysunit
|
||||||
|
|
||||||
from .base import BaseInfoSubmanager
|
from .base import BaseInfoSubmanager
|
||||||
|
|
||||||
@ -84,9 +85,12 @@ class FanInfoSubmanager(BaseInfoSubmanager):
|
|||||||
|
|
||||||
async def __get_monitored(self) -> bool:
|
async def __get_monitored(self) -> bool:
|
||||||
if self.__unix_path:
|
if self.__unix_path:
|
||||||
status = await aiotools.run_async(get_service_status, self.__daemon)
|
try:
|
||||||
if status is not None:
|
async with sysunit.SystemdUnitInfo() as sui:
|
||||||
|
status = await sui.get_status(self.__daemon)
|
||||||
return (status[0] or status[1])
|
return (status[0] or status[1])
|
||||||
|
except Exception as err:
|
||||||
|
get_logger(0).error("Can't get info about the service %r: %s", self.__daemon, tools.efmt(err))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
async def __get_fan_state(self) -> Optional[Dict]:
|
async def __get_fan_state(self) -> Optional[Dict]:
|
||||||
|
|||||||
@ -20,37 +20,78 @@
|
|||||||
# ========================================================================== #
|
# ========================================================================== #
|
||||||
|
|
||||||
|
|
||||||
import contextlib
|
import types
|
||||||
|
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
from typing import Type
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
import dbus # pylint: disable=import-error
|
import dbus_next
|
||||||
import dbus.exceptions
|
import dbus_next.aio
|
||||||
|
import dbus_next.aio.proxy_object
|
||||||
from ...logging import get_logger
|
import dbus_next.introspection
|
||||||
|
import dbus_next.errors
|
||||||
from ... import tools
|
|
||||||
|
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
def get_service_status(name: str) -> Optional[Tuple[bool, bool]]:
|
class SystemdUnitInfo:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.__bus: Optional[dbus_next.aio.MessageBus] = None
|
||||||
|
self.__intr: Optional[dbus_next.introspection.Node] = None
|
||||||
|
self.__manager: Optional[dbus_next.aio.proxy_object.ProxyInterface] = None
|
||||||
|
|
||||||
|
async def get_status(self, name: str) -> Tuple[bool, bool]:
|
||||||
|
assert self.__bus is not None
|
||||||
|
assert self.__intr is not None
|
||||||
|
assert self.__manager is not None
|
||||||
|
|
||||||
if not name.endswith(".service"):
|
if not name.endswith(".service"):
|
||||||
name += ".service"
|
name += ".service"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with contextlib.closing(dbus.SystemBus()) as bus:
|
unit_p = await self.__manager.call_get_unit(name) # type: ignore
|
||||||
systemd = bus.get_object("org.freedesktop.systemd1", "/org/freedesktop/systemd1") # pylint: disable=no-member
|
unit = self.__bus.get_proxy_object("org.freedesktop.systemd1", unit_p, self.__intr)
|
||||||
manager = dbus.Interface(systemd, dbus_interface="org.freedesktop.systemd1.Manager")
|
unit_props = unit.get_interface("org.freedesktop.DBus.Properties")
|
||||||
try:
|
started = ((await unit_props.call_get("org.freedesktop.systemd1.Unit", "ActiveState")).value == "active") # type: ignore
|
||||||
unit_proxy = bus.get_object("org.freedesktop.systemd1", manager.GetUnit(name)) # pylint: disable=no-member
|
except dbus_next.errors.DBusError as err:
|
||||||
unit_properties = dbus.Interface(unit_proxy, dbus_interface="org.freedesktop.DBus.Properties")
|
if err.type != "org.freedesktop.systemd1.NoSuchUnit":
|
||||||
started = (unit_properties.Get("org.freedesktop.systemd1.Unit", "ActiveState") == "active")
|
|
||||||
except dbus.exceptions.DBusException as err:
|
|
||||||
if "NoSuchUnit" not in str(err):
|
|
||||||
raise
|
raise
|
||||||
started = False
|
started = False
|
||||||
enabled = (manager.GetUnitFileState(name) in ["enabled", "enabled-runtime", "static", "indirect", "generated"])
|
enabled = ((await self.__manager.call_get_unit_file_state(name)) in [ # type: ignore
|
||||||
|
"enabled",
|
||||||
|
"enabled-runtime",
|
||||||
|
"static",
|
||||||
|
"indirect",
|
||||||
|
"generated",
|
||||||
|
])
|
||||||
return (enabled, started)
|
return (enabled, started)
|
||||||
except Exception as err:
|
|
||||||
get_logger(0).error("Can't get info about the service %r: %s", name, tools.efmt(err))
|
async def open(self) -> None:
|
||||||
return None
|
self.__bus = await dbus_next.aio.MessageBus(bus_type=dbus_next.BusType.SYSTEM).connect()
|
||||||
|
self.__intr = await self.__bus.introspect("org.freedesktop.systemd1", "/org/freedesktop/systemd1")
|
||||||
|
systemd = self.__bus.get_proxy_object("org.freedesktop.systemd1", "/org/freedesktop/systemd1", self.__intr)
|
||||||
|
self.__manager = systemd.get_interface("org.freedesktop.systemd1.Manager")
|
||||||
|
|
||||||
|
async def __aenter__(self) -> "SystemdUnitInfo":
|
||||||
|
await self.open()
|
||||||
|
return self
|
||||||
|
|
||||||
|
async def close(self) -> None:
|
||||||
|
try:
|
||||||
|
if self.__bus is not None:
|
||||||
|
self.__bus.disconnect()
|
||||||
|
await self.__bus.wait_for_disconnect()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
self.__manager = None
|
||||||
|
self.__intr = None
|
||||||
|
self.__bus = None
|
||||||
|
|
||||||
|
async def __aexit__(
|
||||||
|
self,
|
||||||
|
_exc_type: Type[BaseException],
|
||||||
|
_exc: BaseException,
|
||||||
|
_tb: types.TracebackType,
|
||||||
|
) -> None:
|
||||||
|
|
||||||
|
await self.close()
|
||||||
|
|||||||
@ -45,6 +45,7 @@ RUN pacman --noconfirm --ask=4 -Syy \
|
|||||||
python-netifaces \
|
python-netifaces \
|
||||||
python-systemd \
|
python-systemd \
|
||||||
python-dbus \
|
python-dbus \
|
||||||
|
python-dbus-next \
|
||||||
python-pygments \
|
python-pygments \
|
||||||
python-pam \
|
python-pam \
|
||||||
python-pillow \
|
python-pillow \
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user