client_update_v0.001
This commit is contained in:
Binary file not shown.
@@ -28,7 +28,14 @@ DEFAULT_TOKEN = "change-me-client-token"
|
||||
CONNECTION_TIMEOUT_SECONDS = 10
|
||||
HEARTBEAT_INTERVAL_SECONDS = 10
|
||||
HEARTBEAT_TIMEOUT_SECONDS = 5
|
||||
DEVICE_TYPES = ("Компьютер", "Ноутбук", "Моноблок", "Тонкий клиент", "Сервер")
|
||||
DEVICE_TYPES = (
|
||||
"Компьютер",
|
||||
"Ноутбук",
|
||||
"Моноблок",
|
||||
"Тонкий клиент",
|
||||
"Сервер",
|
||||
"Виртуальная машина",
|
||||
)
|
||||
CLIENT_ICON_RELATIVE = Path("picture") / "ICON" / "icon_client.png"
|
||||
|
||||
BG = "#c0c0c0"
|
||||
@@ -506,6 +513,106 @@ def detect_os_info():
|
||||
return f"{platform.system()} {platform.release()} {platform.version()} {platform.machine()}".strip()
|
||||
|
||||
|
||||
def contains_virtual_machine_signature(value):
|
||||
text = str(value or "").lower()
|
||||
signatures = (
|
||||
"vmware",
|
||||
"virtualbox",
|
||||
"virtual machine",
|
||||
"virtual pc",
|
||||
"virtio",
|
||||
"qemu",
|
||||
"kvm",
|
||||
"xen",
|
||||
"parallels",
|
||||
"bhyve",
|
||||
"bochs",
|
||||
)
|
||||
return any(signature in text for signature in signatures)
|
||||
|
||||
|
||||
def contains_server_os_signature(value):
|
||||
text = str(value or "").lower()
|
||||
return any(
|
||||
signature in text
|
||||
for signature in (
|
||||
"windows server",
|
||||
"server edition",
|
||||
"ubuntu server",
|
||||
"red hat enterprise linux server",
|
||||
"suse linux enterprise server",
|
||||
"oracle linux server",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def detect_windows_device_type(os_info):
|
||||
evidence = run_powershell(
|
||||
"$cs=Get-CimInstance Win32_ComputerSystem; "
|
||||
"$battery=@(Get-CimInstance Win32_Battery -ErrorAction SilentlyContinue).Count; "
|
||||
"$vmDrivers=(Get-CimInstance Win32_PnPSignedDriver -ErrorAction SilentlyContinue | "
|
||||
"Where-Object { ($_.DeviceName + ' ' + $_.Manufacturer) -match "
|
||||
"'VMware|VirtualBox|VirtIO|QEMU|Xen|Parallels' } | "
|
||||
"Select-Object -ExpandProperty DeviceName) -join ', '; "
|
||||
'"SYSTEM=$($cs.Manufacturer) $($cs.Model)`nBATTERY=$battery`nDRIVERS=$vmDrivers"',
|
||||
timeout=15,
|
||||
)
|
||||
if contains_virtual_machine_signature(evidence):
|
||||
return "Виртуальная машина"
|
||||
if contains_server_os_signature(os_info):
|
||||
return "Сервер"
|
||||
battery_match = re.search(r"(?im)^BATTERY=(\d+)\s*$", evidence)
|
||||
if battery_match and int(battery_match.group(1)) > 0:
|
||||
return "Ноутбук"
|
||||
return "Компьютер"
|
||||
|
||||
|
||||
def detect_macos_device_type(os_info):
|
||||
hardware = run_command(["system_profiler", "SPHardwareDataType"], timeout=15)
|
||||
if contains_virtual_machine_signature(hardware):
|
||||
return "Виртуальная машина"
|
||||
if contains_server_os_signature(os_info):
|
||||
return "Сервер"
|
||||
battery = run_command(["pmset", "-g", "batt"])
|
||||
if "InternalBattery" in battery and "No batteries" not in battery:
|
||||
return "Ноутбук"
|
||||
return "Компьютер"
|
||||
|
||||
|
||||
def detect_linux_device_type(os_info):
|
||||
evidence_parts = [run_command(["systemd-detect-virt"])]
|
||||
for path in (
|
||||
Path("/sys/class/dmi/id/sys_vendor"),
|
||||
Path("/sys/class/dmi/id/product_name"),
|
||||
Path("/sys/class/dmi/id/board_vendor"),
|
||||
):
|
||||
try:
|
||||
evidence_parts.append(path.read_text(encoding="utf-8", errors="ignore"))
|
||||
except OSError:
|
||||
pass
|
||||
if contains_virtual_machine_signature(" ".join(evidence_parts)):
|
||||
return "Виртуальная машина"
|
||||
if contains_server_os_signature(os_info):
|
||||
return "Сервер"
|
||||
power_supply = Path("/sys/class/power_supply")
|
||||
if power_supply.exists():
|
||||
for type_path in power_supply.glob("*/type"):
|
||||
try:
|
||||
if type_path.read_text(encoding="utf-8").strip().lower() == "battery":
|
||||
return "Ноутбук"
|
||||
except OSError:
|
||||
pass
|
||||
return "Компьютер"
|
||||
|
||||
|
||||
def detect_device_type(os_info=""):
|
||||
if is_windows():
|
||||
return detect_windows_device_type(os_info)
|
||||
if is_macos():
|
||||
return detect_macos_device_type(os_info)
|
||||
return detect_linux_device_type(os_info)
|
||||
|
||||
|
||||
def rustdesk_config_paths():
|
||||
paths = []
|
||||
if is_windows():
|
||||
@@ -753,11 +860,19 @@ class ClientV2App:
|
||||
self.cabinet_id_by_label = {}
|
||||
self.saved_cabinet_id = str(config.get("cabinet_id") or "").strip()
|
||||
self.detected_payload = build_detected_payload()
|
||||
self.detected_device_type = detect_device_type(self.detected_payload.get("os_info", ""))
|
||||
self.device_type_is_manual = bool(config.get("device_type_manual", False))
|
||||
configured_device_type = str(config.get("device_type") or "").strip()
|
||||
initial_device_type = (
|
||||
configured_device_type
|
||||
if self.device_type_is_manual and configured_device_type
|
||||
else self.detected_device_type
|
||||
)
|
||||
|
||||
self.server_var = tk.StringVar(value=config.get("server", DEFAULT_SERVER))
|
||||
self.token_var = tk.StringVar(value=config.get("token", DEFAULT_TOKEN))
|
||||
self.inventory_var = tk.StringVar(value=config.get("inventory_number", ""))
|
||||
self.device_type_var = tk.StringVar(value=config.get("device_type", DEVICE_TYPES[0]))
|
||||
self.device_type_var = tk.StringVar(value=initial_device_type)
|
||||
self.model_var = tk.StringVar(value=config.get("model", ""))
|
||||
self.serial_var = tk.StringVar(value=config.get("serial_number", ""))
|
||||
self.building_var = tk.StringVar(value=config.get("building", ""))
|
||||
@@ -885,8 +1000,11 @@ class ClientV2App:
|
||||
manual.columnconfigure(3, weight=1, uniform="manual_field")
|
||||
self.add_grid_control(manual, "Инв. №", self.entry(manual, self.inventory_var), 0, 0, 1, entry=True)
|
||||
self.device_type_box = self.combobox(manual, self.device_type_var, DEVICE_TYPES)
|
||||
self.device_type_box.configure(state="normal")
|
||||
self.add_grid_control(manual, "Тип", self.device_type_box, 0, 2, 3)
|
||||
self.device_type_box.bind("<<ComboboxSelected>>", self.on_device_type_changed)
|
||||
self.device_type_box.bind("<FocusOut>", self.on_device_type_changed)
|
||||
self.device_type_box.bind("<Return>", self.on_device_type_changed)
|
||||
self.add_grid_control(manual, "Модель", self.entry(manual, self.model_var), 1, 0, 1, entry=True)
|
||||
self.add_grid_control(manual, "Серийный №", self.entry(manual, self.serial_var), 1, 2, 3, entry=True)
|
||||
self.building_box = self.combobox(manual, self.building_var, ())
|
||||
@@ -1132,6 +1250,7 @@ class ClientV2App:
|
||||
)
|
||||
|
||||
def on_device_type_changed(self, _event=None):
|
||||
self.device_type_is_manual = True
|
||||
self.motherboard_var.set(self.motherboard_display_value())
|
||||
|
||||
def refresh_detected_data(self):
|
||||
@@ -1288,6 +1407,7 @@ class ClientV2App:
|
||||
"token": self.token_var.get().strip(),
|
||||
"inventory_number": self.inventory_var.get().strip(),
|
||||
"device_type": self.device_type_var.get().strip(),
|
||||
"device_type_manual": self.device_type_is_manual,
|
||||
"model": self.model_var.get().strip(),
|
||||
"serial_number": self.serial_var.get().strip(),
|
||||
"building": self.building_var.get().strip(),
|
||||
@@ -1417,6 +1537,9 @@ class ClientV2App:
|
||||
self.heartbeat_context = None
|
||||
|
||||
def start_tray(self):
|
||||
if not is_windows():
|
||||
self.tray_available = False
|
||||
return False
|
||||
try:
|
||||
import pystray
|
||||
from PIL import Image
|
||||
@@ -1588,8 +1711,9 @@ def run_gui(args):
|
||||
config["server"] = normalize_server_url(args.server)
|
||||
if args.token:
|
||||
config["token"] = args.token.strip()
|
||||
windows_startup = bool(args.startup and is_windows())
|
||||
root = tk.Tk()
|
||||
if args.startup:
|
||||
if windows_startup:
|
||||
root.withdraw()
|
||||
app = ClientV2App(root, config)
|
||||
if app.is_bound_to_server:
|
||||
@@ -1597,12 +1721,12 @@ def run_gui(args):
|
||||
enable_windows_autostart()
|
||||
except OSError as error:
|
||||
app.status_var.set(f"Не удалось обновить автозагрузку: {error}")
|
||||
tray_started = app.start_tray()
|
||||
if args.startup and tray_started:
|
||||
tray_started = app.start_tray() if is_windows() else False
|
||||
if windows_startup and tray_started:
|
||||
app.hide_window()
|
||||
elif not tray_started:
|
||||
elif is_windows() and not tray_started:
|
||||
app.status_var.set("Трей недоступен: установите pystray и Pillow, затем пересоберите клиент")
|
||||
if args.startup:
|
||||
if windows_startup:
|
||||
app.show_window()
|
||||
root.mainloop()
|
||||
|
||||
@@ -1617,7 +1741,7 @@ def run_once(args):
|
||||
payload.update(
|
||||
{
|
||||
"inventory_number": (args.inventory_number or "").strip(),
|
||||
"device_type": args.device_type or DEVICE_TYPES[0],
|
||||
"device_type": args.device_type or detect_device_type(payload.get("os_info", "")),
|
||||
"model": args.model or "",
|
||||
"serial_number": args.serial_number or "",
|
||||
"building": args.building or "",
|
||||
|
||||
Reference in New Issue
Block a user