From f9511932ad996a4cd75b569cfa0eb7ccc223b608 Mon Sep 17 00:00:00 2001 From: "Jose M. Guisado" Date: Thu, 18 Nov 2021 10:38:25 +0100 Subject: #1065 Add windows mode Add agent mode for windows platform. Subprocess module for shell/run is cross-platform an no change was needed. The subprocess will run with the same privilege as its parent, ogclient. TODO: Provide a windows installer. As of now, an administrator needs to install python and required libraries for this mode to be usable. --- src/ogClient.py | 2 +- src/ogRest.py | 4 +- src/windows/__init__.py | 1 + src/windows/ogOperations.py | 113 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 src/windows/__init__.py create mode 100644 src/windows/ogOperations.py diff --git a/src/ogClient.py b/src/ogClient.py index d842ee5..13a55f4 100644 --- a/src/ogClient.py +++ b/src/ogClient.py @@ -30,7 +30,7 @@ class ogClient: self.CONFIG = config self.mode = self.CONFIG['opengnsys']['mode'] - if self.mode not in {'virtual', 'live', 'linux'}: + if self.mode not in {'virtual', 'live', 'linux', 'windows'}: raise ValueError('Mode not supported.') if self.CONFIG['samba']['activate']: diff --git a/src/ogRest.py b/src/ogRest.py index 954b2be..db6a60e 100644 --- a/src/ogRest.py +++ b/src/ogRest.py @@ -15,7 +15,6 @@ import queue import sys import os import signal -import syslog import logging from logging.handlers import SysLogHandler @@ -269,6 +268,9 @@ class ogRest(): elif self.mode == 'linux': from src.linux.ogOperations import OgLinuxOperations self.operations = OgLinuxOperations() + elif self.mode == 'windows': + from src.windows.ogOperations import OgWindowsOperations + self.operations = OgWindowsOperations() else: raise ValueError('Mode not supported.') diff --git a/src/windows/__init__.py b/src/windows/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/windows/__init__.py @@ -0,0 +1 @@ + diff --git a/src/windows/ogOperations.py b/src/windows/ogOperations.py new file mode 100644 index 0000000..0af7250 --- /dev/null +++ b/src/windows/ogOperations.py @@ -0,0 +1,113 @@ +# +# Copyright (C) 2021 Soleta Networks +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the +# Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +import os +import subprocess +from subprocess import CalledProcessError +import multiprocessing as mp +from multiprocessing import Process + +from PIL import Image, ImageDraw +from pystray import Icon, Menu, MenuItem + +from src.ogRest import ThreadState + + +def _create_default_image(): + """ + Creates a default image for the tray icon. Use in case + no favicon.ico is found. + """ + width = height = 250 + color1 = (255, 255, 255) + color2 = (255, 0, 255) + + image = Image.new('RGB', (width, height), color1) + dc = ImageDraw.Draw(image) + dc.rectangle( + (width // 2, 0, width, height // 2), + fill=color2) + dc.rectangle( + (0, height // 2, width // 2, height), + fill=color2) + + return image + + +def create_image(): + try: + image = Image.open(r'./favicon.ico') + image = Image.composite(image, Image.new('RGB', image.size, 'white'), image) + except: + image = _create_default_image() + return image + + +def create_systray(): + menu = Menu(MenuItem('Powered by Soleta Networks!', + lambda icon, item: 1)) + icon = Icon('ogClient', create_image(), menu=menu) + assert icon.icon + icon.run() + + +systray_p = Process(target=create_systray) + + +class OgWindowsOperations: + + def __init__(self): + mp.set_start_method('spawn') + systray_p.start() + + def _restartBrowser(self, url): + raise NotImplementedError + + def poweroff(self): + systray_p.terminate() + + def reboot(self): + systray_p.terminate() + + def shellrun(self, request, ogRest): + cmd = request.getrun() + try: + result = subprocess.run(cmd, + shell=True, + stdin=subprocess.DEVNULL, + capture_output=True, + text=True, + check=True) + except CalledProcessError as error: + if error.stderr: + return error.stderr + if error.stdout: + return error.stdout + return "{Non zero exit code and empty output}" + return result.stdout + + def session(self, request, ogRest): + raise NotImplementedError + + def hardware(self, path, ogRest): + raise NotImplementedError + + def setup(self, request, ogRest): + raise NotImplementedError + + def image_restore(self, request, ogRest): + raise NotImplementedError + + def image_create(self, path, request, ogRest): + raise NotImplementedError + + def refresh(self, ogRest): + return {"status": "WIN"} + + def probe(self, ogRest): + return {'status': 'WIN' if ogRest.state != ThreadState.BUSY else 'BSY'} -- cgit v1.2.3-18-g5258