forked from platypush/platypush
Converted system.processes
to the new data model.
This commit is contained in:
parent
387616ea96
commit
27b1048789
8 changed files with 183 additions and 133 deletions
|
@ -1,77 +0,0 @@
|
||||||
from datetime import datetime
|
|
||||||
from typing import Optional, List
|
|
||||||
|
|
||||||
from platypush.message.response import Response
|
|
||||||
|
|
||||||
|
|
||||||
class SystemResponse(Response):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class ProcessResponse(SystemResponse):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
pid: int,
|
|
||||||
name: str,
|
|
||||||
started: datetime,
|
|
||||||
ppid: Optional[int],
|
|
||||||
children: Optional[List[int]] = None,
|
|
||||||
exe: Optional[List[str]] = None,
|
|
||||||
status: Optional[str] = None,
|
|
||||||
username: Optional[str] = None,
|
|
||||||
terminal: Optional[str] = None,
|
|
||||||
cpu_user_time: Optional[float] = None,
|
|
||||||
cpu_system_time: Optional[float] = None,
|
|
||||||
cpu_children_user_time: Optional[float] = None,
|
|
||||||
cpu_children_system_time: Optional[float] = None,
|
|
||||||
mem_rss: Optional[int] = None,
|
|
||||||
mem_vms: Optional[int] = None,
|
|
||||||
mem_shared: Optional[int] = None,
|
|
||||||
mem_text: Optional[int] = None,
|
|
||||||
mem_data: Optional[int] = None,
|
|
||||||
mem_lib: Optional[int] = None,
|
|
||||||
mem_dirty: Optional[int] = None,
|
|
||||||
mem_percent: Optional[float] = None,
|
|
||||||
*args,
|
|
||||||
**kwargs
|
|
||||||
):
|
|
||||||
super().__init__(
|
|
||||||
*args,
|
|
||||||
output={
|
|
||||||
'pid': pid,
|
|
||||||
'name': name,
|
|
||||||
'started': started,
|
|
||||||
'ppid': ppid,
|
|
||||||
'exe': exe,
|
|
||||||
'status': status,
|
|
||||||
'username': username,
|
|
||||||
'terminal': terminal,
|
|
||||||
'cpu_user_time': cpu_user_time,
|
|
||||||
'cpu_system_time': cpu_system_time,
|
|
||||||
'cpu_children_user_time': cpu_children_user_time,
|
|
||||||
'cpu_children_system_time': cpu_children_system_time,
|
|
||||||
'mem_rss': mem_rss,
|
|
||||||
'mem_vms': mem_vms,
|
|
||||||
'mem_shared': mem_shared,
|
|
||||||
'mem_text': mem_text,
|
|
||||||
'mem_data': mem_data,
|
|
||||||
'mem_lib': mem_lib,
|
|
||||||
'mem_dirty': mem_dirty,
|
|
||||||
'mem_percent': mem_percent,
|
|
||||||
'children': children or [],
|
|
||||||
},
|
|
||||||
**kwargs
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class SystemResponseList(SystemResponse):
|
|
||||||
def __init__(self, responses: List[SystemResponse], *args, **kwargs):
|
|
||||||
super().__init__(output=[r.output for r in responses], *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class ProcessResponseList(SystemResponseList):
|
|
||||||
def __init__(self, responses: List[ProcessResponse], *args, **kwargs):
|
|
||||||
super().__init__(responses=responses, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
# vim:sw=4:ts=4:et:
|
|
|
@ -1,6 +1,5 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from datetime import datetime
|
|
||||||
from typing import Tuple, Union, List, Optional
|
from typing import Tuple, Union, List, Optional
|
||||||
from typing_extensions import override
|
from typing_extensions import override
|
||||||
|
|
||||||
|
@ -23,10 +22,6 @@ from platypush.entities.system import (
|
||||||
SystemFan,
|
SystemFan,
|
||||||
SystemTemperature,
|
SystemTemperature,
|
||||||
)
|
)
|
||||||
from platypush.message.response.system import (
|
|
||||||
ProcessResponseList,
|
|
||||||
ProcessResponse,
|
|
||||||
)
|
|
||||||
from platypush.plugins import action
|
from platypush.plugins import action
|
||||||
from platypush.plugins.sensor import SensorPlugin
|
from platypush.plugins.sensor import SensorPlugin
|
||||||
from platypush.schemas.system import (
|
from platypush.schemas.system import (
|
||||||
|
@ -49,6 +44,8 @@ from platypush.schemas.system import (
|
||||||
MemoryStatsSchema,
|
MemoryStatsSchema,
|
||||||
NetworkInterface,
|
NetworkInterface,
|
||||||
NetworkInterfaceSchema,
|
NetworkInterfaceSchema,
|
||||||
|
Process,
|
||||||
|
ProcessSchema,
|
||||||
SwapStats,
|
SwapStats,
|
||||||
SwapStatsSchema,
|
SwapStatsSchema,
|
||||||
SystemInfoSchema,
|
SystemInfoSchema,
|
||||||
|
@ -366,7 +363,8 @@ class SystemPlugin(SensorPlugin, EntityManager):
|
||||||
"""
|
"""
|
||||||
return TemperatureSchema().dump(self._sensors_temperature(), many=True)
|
return TemperatureSchema().dump(self._sensors_temperature(), many=True)
|
||||||
|
|
||||||
def _sensors_fan(self) -> List[Fan]:
|
@staticmethod
|
||||||
|
def _sensors_fan() -> List[Fan]:
|
||||||
return FanSchema().load( # type: ignore
|
return FanSchema().load( # type: ignore
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
@ -389,7 +387,8 @@ class SystemPlugin(SensorPlugin, EntityManager):
|
||||||
"""
|
"""
|
||||||
return FanSchema().dump(self._sensors_fan(), many=True)
|
return FanSchema().dump(self._sensors_fan(), many=True)
|
||||||
|
|
||||||
def _sensors_battery(self) -> Optional[Battery]:
|
@staticmethod
|
||||||
|
def _sensors_battery() -> Optional[Battery]:
|
||||||
battery = psutil.sensors_battery()
|
battery = psutil.sensors_battery()
|
||||||
return BatterySchema().load(battery) if battery else None # type: ignore
|
return BatterySchema().load(battery) if battery else None # type: ignore
|
||||||
|
|
||||||
|
@ -403,7 +402,8 @@ class SystemPlugin(SensorPlugin, EntityManager):
|
||||||
battery = self._sensors_battery()
|
battery = self._sensors_battery()
|
||||||
return BatterySchema().dump(battery) if battery else None # type: ignore
|
return BatterySchema().dump(battery) if battery else None # type: ignore
|
||||||
|
|
||||||
def _connected_users(self) -> List[User]:
|
@staticmethod
|
||||||
|
def _connected_users() -> List[User]:
|
||||||
return UserSchema().load(psutil.users(), many=True) # type: ignore
|
return UserSchema().load(psutil.users(), many=True) # type: ignore
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
@ -415,64 +415,40 @@ class SystemPlugin(SensorPlugin, EntityManager):
|
||||||
"""
|
"""
|
||||||
return UserSchema().dump(self._connected_users(), many=True)
|
return UserSchema().dump(self._connected_users(), many=True)
|
||||||
|
|
||||||
@action
|
@classmethod
|
||||||
def processes(self, filter: Optional[str] = '') -> ProcessResponseList:
|
def _processes(cls) -> List[Process]:
|
||||||
"""
|
"""
|
||||||
Get the list of running processes.
|
Get the list of running processes.
|
||||||
|
|
||||||
:param filter: Filter the list by name.
|
:param filter: Filter the list by name.
|
||||||
:return: List of :class:`platypush.message.response.system.ProcessResponse`.
|
:return: List of :class:`platypush.message.response.system.ProcessResponse`.
|
||||||
"""
|
"""
|
||||||
processes = [psutil.Process(pid) for pid in psutil.pids()]
|
return ProcessSchema().load( # type: ignore
|
||||||
p_list = []
|
filter( # type: ignore
|
||||||
|
lambda proc: proc is not None,
|
||||||
for p in processes:
|
[cls._get_process_if_exists(pid) for pid in psutil.pids()],
|
||||||
if filter and filter not in p.name():
|
),
|
||||||
continue
|
many=True,
|
||||||
|
|
||||||
args = {}
|
|
||||||
|
|
||||||
try:
|
|
||||||
mem = p.memory_info()
|
|
||||||
times = p.cpu_times()
|
|
||||||
args.update(
|
|
||||||
pid=p.pid,
|
|
||||||
name=p.name(),
|
|
||||||
started=datetime.fromtimestamp(p.create_time()),
|
|
||||||
ppid=p.ppid(),
|
|
||||||
children=[pp.pid for pp in p.children()],
|
|
||||||
status=p.status(),
|
|
||||||
username=p.username(),
|
|
||||||
terminal=p.terminal(),
|
|
||||||
cpu_user_time=times.user,
|
|
||||||
cpu_system_time=times.system,
|
|
||||||
cpu_children_user_time=times.children_user,
|
|
||||||
cpu_children_system_time=times.children_system,
|
|
||||||
mem_rss=mem.rss,
|
|
||||||
mem_vms=mem.vms,
|
|
||||||
mem_shared=mem.shared,
|
|
||||||
mem_text=mem.text,
|
|
||||||
mem_data=mem.data,
|
|
||||||
mem_lib=mem.lib,
|
|
||||||
mem_dirty=mem.dirty,
|
|
||||||
mem_percent=p.memory_percent(),
|
|
||||||
)
|
)
|
||||||
except psutil.Error:
|
|
||||||
continue
|
|
||||||
|
|
||||||
|
@action
|
||||||
|
def processes(self) -> List[dict]:
|
||||||
|
"""
|
||||||
|
Get the list of running processes.
|
||||||
|
|
||||||
|
:return: .. schema:: system.ProcessSchema
|
||||||
|
"""
|
||||||
|
return ProcessSchema().dump(self._processes(), many=True)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_process_if_exists(cls, pid: int) -> Optional[psutil.Process]:
|
||||||
try:
|
try:
|
||||||
args.update(
|
return cls._get_process(pid)
|
||||||
exe=p.exe(),
|
except psutil.NoSuchProcess:
|
||||||
)
|
return None
|
||||||
except psutil.Error:
|
|
||||||
pass
|
|
||||||
|
|
||||||
p_list.append(ProcessResponse(**args))
|
|
||||||
|
|
||||||
return ProcessResponseList(p_list)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_process(pid: int):
|
def _get_process(pid: int) -> psutil.Process:
|
||||||
return psutil.Process(pid)
|
return psutil.Process(pid)
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
|
|
@ -16,6 +16,7 @@ from ._fan import Fan, FanSchema
|
||||||
from ._memory import MemoryStats, MemoryStatsSchema, SwapStats, SwapStatsSchema
|
from ._memory import MemoryStats, MemoryStatsSchema, SwapStats, SwapStatsSchema
|
||||||
from ._model import SystemInfo
|
from ._model import SystemInfo
|
||||||
from ._network import NetworkInterface, NetworkInterfaceSchema
|
from ._network import NetworkInterface, NetworkInterfaceSchema
|
||||||
|
from ._process import Process, ProcessSchema
|
||||||
from ._schemas import SystemInfoSchema
|
from ._schemas import SystemInfoSchema
|
||||||
from ._temperature import Temperature, TemperatureSchema
|
from ._temperature import Temperature, TemperatureSchema
|
||||||
from ._user import User, UserSchema
|
from ._user import User, UserSchema
|
||||||
|
@ -41,6 +42,8 @@ __all__ = [
|
||||||
"FanSchema",
|
"FanSchema",
|
||||||
"MemoryStats",
|
"MemoryStats",
|
||||||
"MemoryStatsSchema",
|
"MemoryStatsSchema",
|
||||||
|
"Process",
|
||||||
|
"ProcessSchema",
|
||||||
"SwapStats",
|
"SwapStats",
|
||||||
"SwapStatsSchema",
|
"SwapStatsSchema",
|
||||||
"NetworkInterface",
|
"NetworkInterface",
|
||||||
|
|
4
platypush/schemas/system/_process/__init__.py
Normal file
4
platypush/schemas/system/_process/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
from ._model import Process
|
||||||
|
from ._schemas import ProcessSchema
|
||||||
|
|
||||||
|
__all__ = ['Process', 'ProcessSchema']
|
28
platypush/schemas/system/_process/_base.py
Normal file
28
platypush/schemas/system/_process/_base.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from dateutil.tz import gettz
|
||||||
|
from marshmallow import pre_load
|
||||||
|
|
||||||
|
from .._base import SystemBaseSchema
|
||||||
|
|
||||||
|
|
||||||
|
class ProcessBaseSchema(SystemBaseSchema):
|
||||||
|
"""
|
||||||
|
Base schema for system processes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@pre_load
|
||||||
|
def pre_load(self, data, **_) -> dict:
|
||||||
|
if hasattr(data, 'as_dict'):
|
||||||
|
data = data.as_dict()
|
||||||
|
|
||||||
|
started_ts = data.pop('create_time', None)
|
||||||
|
if started_ts is not None:
|
||||||
|
data['started'] = datetime.fromtimestamp(started_ts).replace(tzinfo=gettz())
|
||||||
|
|
||||||
|
data['command_line'] = data.pop('cmdline', None)
|
||||||
|
data['cpu_percent'] = data.pop('cpu_percent') / 100
|
||||||
|
data['current_directory'] = data.pop('cwd', None)
|
||||||
|
data['memory_percent'] = data.pop('memory_percent') / 100
|
||||||
|
data['parent_pid'] = data.pop('ppid', None)
|
||||||
|
return data
|
110
platypush/schemas/system/_process/_model.py
Normal file
110
platypush/schemas/system/_process/_model.py
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from datetime import datetime
|
||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
|
from platypush.schemas.dataclasses import percent_field
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Process:
|
||||||
|
"""
|
||||||
|
System process data class.
|
||||||
|
"""
|
||||||
|
|
||||||
|
pid: int = field(
|
||||||
|
metadata={
|
||||||
|
'metadata': {
|
||||||
|
'description': 'Process PID',
|
||||||
|
'example': 12345,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
name: str = field(
|
||||||
|
metadata={
|
||||||
|
'metadata': {
|
||||||
|
'description': 'Process name',
|
||||||
|
'example': 'python',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
parent_pid: Optional[int] = field(
|
||||||
|
metadata={
|
||||||
|
'metadata': {
|
||||||
|
'description': 'PID of the parent process',
|
||||||
|
'example': 1000,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
username: str = field(
|
||||||
|
metadata={
|
||||||
|
'metadata': {
|
||||||
|
'description': 'Username that owns the process',
|
||||||
|
'example': 'root',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
command_line: List[str] = field(
|
||||||
|
metadata={
|
||||||
|
'metadata': {
|
||||||
|
'description': 'Command line of the process',
|
||||||
|
'example': ['/usr/bin/python', '-m', 'platypush'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
status: str = field(
|
||||||
|
metadata={
|
||||||
|
'metadata': {
|
||||||
|
'description': 'Process status',
|
||||||
|
'example': 'running',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
terminal: Optional[str] = field(
|
||||||
|
metadata={
|
||||||
|
'metadata': {
|
||||||
|
'description': 'Terminal the process is running on',
|
||||||
|
'example': 'pts/1',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
current_directory: Optional[str] = field(
|
||||||
|
metadata={
|
||||||
|
'metadata': {
|
||||||
|
'description': 'Current directory of the process',
|
||||||
|
'example': '/root',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
started: Optional[datetime] = field(
|
||||||
|
metadata={
|
||||||
|
'metadata': {
|
||||||
|
'description': 'When the process started',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
cpu_percent: float = percent_field(
|
||||||
|
metadata={
|
||||||
|
'metadata': {
|
||||||
|
'description': 'Percentage of CPU used by the process, between 0 and 1',
|
||||||
|
'example': 0.1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
memory_percent: float = percent_field(
|
||||||
|
metadata={
|
||||||
|
'metadata': {
|
||||||
|
'description': 'Percentage of memory used by the process, between 0 and 1',
|
||||||
|
'example': 0.05,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
7
platypush/schemas/system/_process/_schemas.py
Normal file
7
platypush/schemas/system/_process/_schemas.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
from marshmallow_dataclass import class_schema
|
||||||
|
|
||||||
|
from ._base import ProcessBaseSchema
|
||||||
|
from ._model import Process
|
||||||
|
|
||||||
|
|
||||||
|
ProcessSchema = class_schema(Process, base_schema=ProcessBaseSchema)
|
|
@ -31,7 +31,6 @@ class User:
|
||||||
metadata={
|
metadata={
|
||||||
'metadata': {
|
'metadata': {
|
||||||
'description': 'When the user session started',
|
'description': 'When the user session started',
|
||||||
'example': 'pts/1',
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue