From 9ec08cbc84b01ce82f58892556637d8934ede0a5 Mon Sep 17 00:00:00 2001 From: Jonathan Weth Date: Mon, 28 Jun 2021 11:01:45 +0200 Subject: Support multiple hosts --- poetry.lock | 19 ++++++++- pyproject.toml | 1 + rwa/support/sessionservice/config.py | 5 +++ rwa/support/sessionservice/service.py | 74 ++++++++++++++++++++++++++++++++++- rwa/support/sessionservice/session.py | 28 ++++++------- test_client.py | 6 ++- 6 files changed, 112 insertions(+), 21 deletions(-) diff --git a/poetry.lock b/poetry.lock index 4b90dfe..c501ed0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -46,7 +46,7 @@ sphinxcontrib-django = ">=0.5.0,<0.6.0" name = "appdirs" version = "1.4.4" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" +category = "main" optional = false python-versions = "*" @@ -1213,6 +1213,17 @@ brotli = ["brotlipy (>=0.6.0)"] secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +[[package]] +name = "usersettings" +version = "1.1.5" +description = "Portable Local Settings Storage" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +appdirs = ">=1.2" + [[package]] name = "websockify" version = "0.9.0" @@ -1251,7 +1262,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pyt [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "b9992b58f505b297a099abda504337cc6a7dae5f0291e63c9ae8da725fda63f3" +content-hash = "4477f63dce4f7591677d1eaa2bc01265e56d3aa06811958fdaaab7b1f93c920e" [metadata.files] alabaster = [ @@ -1926,6 +1937,10 @@ urllib3 = [ {file = "urllib3-1.26.5-py2.py3-none-any.whl", hash = "sha256:753a0374df26658f99d826cfe40394a686d05985786d946fbe4165b5148f5a7c"}, {file = "urllib3-1.26.5.tar.gz", hash = "sha256:a7acd0977125325f516bda9735fa7142b909a8d01e8b2e4c8108d0984e6e0098"}, ] +usersettings = [ + {file = "usersettings-1.1.5-py3-none-any.whl", hash = "sha256:503be61d30d0cfd98f16bb6c9be86c29e78dc476c794ffae6333ab26f38994bf"}, + {file = "usersettings-1.1.5.tar.gz", hash = "sha256:9f84b282982622d8ebfd2d42b482317ae50fb2b3a7fba22e0b0c36cac61ad673"}, +] websockify = [ {file = "websockify-0.9.0.tar.gz", hash = "sha256:c35b5b79ebc517d3b784dacfb993be413a93cda5222c6f382443ce29c1a6cada"}, ] diff --git a/pyproject.toml b/pyproject.toml index 2582378..1ffeb05 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,6 +24,7 @@ psutil = "^5.7.2" flask = "^1.1.2" argparse = "^1.0.10" dynaconf = "^3.0.0" +usersettings = "^1.1.5" [tool.poetry.dev-dependencies] aleksis-builddeps = "*" diff --git a/rwa/support/sessionservice/config.py b/rwa/support/sessionservice/config.py index f0f8369..4f39a4e 100644 --- a/rwa/support/sessionservice/config.py +++ b/rwa/support/sessionservice/config.py @@ -23,8 +23,13 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import usersettings from dynaconf import Dynaconf settings = Dynaconf( envvar_prefix="RWA", settings_files=["/etc/rwa/support/sessionservice/settings.toml"] ) + +user_settings = usersettings.Settings("org.ArcticaProject.RWASupportSessionService") +user_settings.add_setting("web_app_hosts", list, ["http://127.0.0.1:8000"]) +user_settings.load_settings() diff --git a/rwa/support/sessionservice/service.py b/rwa/support/sessionservice/service.py index c50da26..4798df6 100755 --- a/rwa/support/sessionservice/service.py +++ b/rwa/support/sessionservice/service.py @@ -38,6 +38,7 @@ import dbus.mainloop.glib import dbus.service from gi.repository import GLib +from .config import user_settings from .lock import is_locked, lock, unlock from .session import Session from .trigger import TriggerServerThread @@ -76,10 +77,73 @@ class RWASupportSessionService(dbus.service.Object): logging.info("D-Bus service has been started.") + def _get_web_app_hosts(self) -> str: + """Get all registered RWA.Support.WebApp hosts. + + Helper function: No D-Bus API. + """ + hosts = user_settings.web_app_hosts + return json.dumps(hosts) + @dbus.service.method("org.ArcticaProject.RWASupportSessionService", out_signature="s") - def start(self) -> str: + def get_web_app_hosts(self) -> str: + """Get all registered RWA.Support.WebApp hosts. + + :return: All registered hosts as JSON array (D-Bus string) + + **Structure of returned JSON:** + + :: + + ["https://example.org", "http://127.0.0.1:8000"] + """ + return self._get_web_app_hosts() + + @dbus.service.method( + "org.ArcticaProject.RWASupportSessionService", in_signature="s", out_signature="s" + ) + def add_web_app_host(self, host: str) -> str: + """Add a RWA.Support.WebApp host. + + :param host: Exact hostname of the RWA.Support.WebApp host (D-Bus string) + :return: All registered hosts as JSON array (D-Bus string) + + **Structure of returned JSON:** + + :: + + ["https://example.org", "http://127.0.0.1:8000"] + """ + user_settings.web_app_hosts.append(host) + user_settings.save_settings() + return self._get_web_app_hosts() + + @dbus.service.method( + "org.ArcticaProject.RWASupportSessionService", in_signature="i", out_signature="s" + ) + def remove_web_app_host(self, idx: int) -> str: + """Remove a RWA.Support.WebApp host. + + :param idx: Index of web app host (D-Bus integer) + :return: All registered hosts as JSON array (D-Bus string) + + **Structure of returned JSON:** + + :: + + ["https://example.org", "http://127.0.0.1:8000"] + """ + del user_settings.web_app_hosts[idx] + user_settings.save_settings() + return self._get_web_app_hosts() + + @dbus.service.method( + "org.ArcticaProject.RWASupportSessionService", in_signature="i", out_signature="s" + ) + def start(self, host_idx: int) -> str: """Start a new remote session and register it in RWA.Support.WebApp. + :param host_idx: Index of web app host (D-Bus integer) :return: Result as JSON (D-Bus string) **Structure of returned JSON (success):** @@ -103,10 +167,16 @@ class RWASupportSessionService(dbus.service.Object): "session, so this session won't be started." ) return json.dumps({"status": "error", "type": "multiple"}) + print(host_idx, user_settings.web_app_hosts) + + try: + host = user_settings.web_app_hosts[host_idx] + except IndexError: + return json.dumps({"status": "error", "type": "host_not_found"}) # Start session try: - session = Session(self.trigger_service.port, self.mockup_mode) + session = Session(host, self.trigger_service.port, self.mockup_mode) # Add session to sessions list self.sessions[session.pid] = session diff --git a/rwa/support/sessionservice/session.py b/rwa/support/sessionservice/session.py index e603568..81584ea 100644 --- a/rwa/support/sessionservice/session.py +++ b/rwa/support/sessionservice/session.py @@ -35,20 +35,10 @@ import port_for import psutil import requests -from .config import settings from .lock import TEMP_DIR_PATH from .log import logging from .vnc import run_vnc, save_password -API_SERVER = settings.get("api_url", "http://127.0.0.1") -BASE_URL = API_SERVER + "/app/rwasupport/api/" -REGISTER_URL = BASE_URL + "register/" -STOP_URL = BASE_URL + "stop/" -STATUS_URL = BASE_URL + "status/" -MARK_JOB_AS_DONE_URL = BASE_URL + "jobs/mark_as_done/" - -logging.info(f"Load API config: {API_SERVER}") - def random_digits(length: int): return "".join(secrets.choice(string.digits) for _ in range(length)) @@ -67,7 +57,15 @@ class Session: #: Remote has joined the session STATUS_JOINED = "active" - def __init__(self, trigger_port: int, mockup_session: bool = False): + def __init__(self, host: str, trigger_port: int, mockup_session: bool = False): + self.host = host + self.BASE_URL = self.host + "/app/rwasupport/api/" + self.REGISTER_URL = self.BASE_URL + "register/" + self.STOP_URL = self.BASE_URL + "stop/" + self.STATUS_URL = self.BASE_URL + "status/" + self.MARK_JOB_AS_DONE_URL = self.BASE_URL + "jobs/mark_as_done/" + logging.info(f"Load API config: {self.host}") + self.trigger_token = secrets.token_urlsafe(20) self.trigger_port = trigger_port self.done_jobs = [] @@ -136,7 +134,7 @@ class Session: if not self.mockup_session: try: r = requests.post( - REGISTER_URL, + self.REGISTER_URL, json={ "port": self.ws_port, "pid": self.vnc_pid, @@ -185,7 +183,7 @@ class Session: if not self.mockup_session: try: r = requests.get( - STATUS_URL, params={"id": self.session_id}, headers=self._api_headers + self.STATUS_URL, params={"id": self.session_id}, headers=self._api_headers ) logging.info( @@ -222,7 +220,7 @@ class Session: self.done_jobs.append(job["job_id"]) try: r = requests.post( - MARK_JOB_AS_DONE_URL, params={"id": job["job_id"]}, headers=self._api_headers, + self.MARK_JOB_AS_DONE_URL, params={"id": job["job_id"]}, headers=self._api_headers, ) logging.info( f"The session has marked the job {job} as done in RWA.Support.WebApp " @@ -266,7 +264,7 @@ class Session: if not triggered: try: r = requests.post( - STOP_URL, params={"id": self.session_id}, headers=self._api_headers + self.STOP_URL, params={"id": self.session_id}, headers=self._api_headers ) logging.info( "The stop action has been registered in RWA.Support.WebApp " diff --git a/test_client.py b/test_client.py index 850e8d3..0e78784 100755 --- a/test_client.py +++ b/test_client.py @@ -29,7 +29,9 @@ import dbus bus = dbus.SessionBus() -time = bus.get_object("org.ArcticaProject.RWASupportSessionService", "/RWASupportSessionService") +api = bus.get_object("org.ArcticaProject.RWASupportSessionService", "/RWASupportSessionService") -curr = time.start() +hosts = api.get_web_app_hosts() +print(hosts) +curr = api.start(0) print("Your VNC session is", curr) -- cgit v1.2.3 From f4cf05cd8dd5d59713fad8be967fc2f87167e213 Mon Sep 17 00:00:00 2001 From: Jonathan Weth Date: Mon, 28 Jun 2021 12:59:11 +0200 Subject: Drop dynaconf support --- poetry.lock | 23 +---------------------- pyproject.toml | 1 - rwa/support/sessionservice/config.py | 5 ----- rwa/support/sessionservice/service.py | 2 +- test_client.py | 1 + 5 files changed, 3 insertions(+), 29 deletions(-) diff --git a/poetry.lock b/poetry.lock index 0c0a1a8..0111965 100644 --- a/poetry.lock +++ b/poetry.lock @@ -292,23 +292,6 @@ toml = "*" [package.extras] pipenv = ["pipenv"] -[[package]] -name = "dynaconf" -version = "3.1.4" -description = "The dynamic configurator for your Python Project" -category = "main" -optional = false -python-versions = "*" - -[package.extras] -all = ["redis", "ruamel.yaml", "configobj", "hvac"] -configobj = ["configobj"] -ini = ["configobj"] -redis = ["redis"] -toml = ["toml"] -vault = ["hvac"] -yaml = ["ruamel.yaml"] - [[package]] name = "flake8" version = "3.9.2" @@ -1266,7 +1249,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pyt [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "e94d233aff281e3b0cdf43eab46ee628f6772a88780ca76396f008ae41fb4548" +content-hash = "368a8ee38bb0c8659c6ef4c58e51052b6186ac516234b60488abee1aaa09f5c9" [metadata.files] alabaster = [ @@ -1414,10 +1397,6 @@ dparse = [ {file = "dparse-0.5.1-py3-none-any.whl", hash = "sha256:e953a25e44ebb60a5c6efc2add4420c177f1d8404509da88da9729202f306994"}, {file = "dparse-0.5.1.tar.gz", hash = "sha256:a1b5f169102e1c894f9a7d5ccf6f9402a836a5d24be80a986c7ce9eaed78f367"}, ] -dynaconf = [ - {file = "dynaconf-3.1.4-py2.py3-none-any.whl", hash = "sha256:e6f383b84150b70fc439c8b2757581a38a58d07962aa14517292dcce1a77e160"}, - {file = "dynaconf-3.1.4.tar.gz", hash = "sha256:b2f472d83052f809c5925565b8a2ba76a103d5dc1dbb9748b693ed67212781b9"}, -] flake8 = [ {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, diff --git a/pyproject.toml b/pyproject.toml index de0b661..be6732c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,6 @@ websockify = "^0.9.0" psutil = "^5.7.2" flask = "^1.1.2" argparse = "^1.0.10" -dynaconf = "^3.0.0" usersettings = "^1.1.5" click = "^8.0.1" diff --git a/rwa/support/sessionservice/config.py b/rwa/support/sessionservice/config.py index 4f39a4e..de5518d 100644 --- a/rwa/support/sessionservice/config.py +++ b/rwa/support/sessionservice/config.py @@ -24,11 +24,6 @@ # along with this program. If not, see . import usersettings -from dynaconf import Dynaconf - -settings = Dynaconf( - envvar_prefix="RWA", settings_files=["/etc/rwa/support/sessionservice/settings.toml"] -) user_settings = usersettings.Settings("org.ArcticaProject.RWASupportSessionService") user_settings.add_setting("web_app_hosts", list, ["http://127.0.0.1:8000"]) diff --git a/rwa/support/sessionservice/service.py b/rwa/support/sessionservice/service.py index e3ca5a1..52bf627 100755 --- a/rwa/support/sessionservice/service.py +++ b/rwa/support/sessionservice/service.py @@ -321,7 +321,7 @@ class RWASupportSessionService(dbus.service.Object): return False def _stop_all(self): - """Stop all sessions""" + """Stop all sessions.""" logging.info("Stop all sessions.") for session in list(self.sessions.values()): session.stop() diff --git a/test_client.py b/test_client.py index 5176ad2..deb5252 100755 --- a/test_client.py +++ b/test_client.py @@ -73,5 +73,6 @@ def refresh_status(pid: int): response = req.refresh_status(pid) click.echo(f"Your response is: {response}") + if __name__ == "__main__": cli() -- cgit v1.2.3 From ad5ebc3197b7fbd6ffffda969d5a81d939057bc7 Mon Sep 17 00:00:00 2001 From: Jonathan Weth Date: Tue, 29 Jun 2021 16:29:59 +0200 Subject: Fix click implementation in test client --- test_client.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test_client.py b/test_client.py index deb5252..ee49bae 100755 --- a/test_client.py +++ b/test_client.py @@ -39,7 +39,7 @@ def cli(): @cli.command() -@click.argument("host") +@click.argument("host", type=int) def start(host: int): """Start a session on the RWA.Support.WebApp host with index HOST.""" click.echo(f"Sending D-Bus request 'start': {host}") @@ -48,7 +48,7 @@ def start(host: int): @cli.command() -@click.argument("pid") +@click.argument("pid", type=int) def stop(pid: int): """Stop the session with the pid PID.""" click.echo(f"Sending D-Bus request 'stop' with PID {pid}") @@ -57,7 +57,7 @@ def stop(pid: int): @cli.command() -@click.argument("pid") +@click.argument("pid", type=int) def status(pid: int): """Get the status of the session with the pid PID.""" click.echo(f"Sending D-Bus request 'status' with PID {pid}") @@ -66,7 +66,7 @@ def status(pid: int): @cli.command() -@click.argument("pid") +@click.argument("pid", type=int) def refresh_status(pid: int): """Refresh and get the status of the session with the pid PID.""" click.echo(f"Sending D-Bus request 'refresh_status' with PID {pid}") -- cgit v1.2.3