From 563fae93598326cac01bac07e125d595f39a6600 Mon Sep 17 00:00:00 2001 From: avollkopf <43980694+avollkopf@users.noreply.github.com> Date: Sun, 19 Dec 2021 18:00:15 +0100 Subject: [PATCH 1/2] Add cbpi service logfile download via journalctl --- cbpi/__init__.py | 2 +- cbpi/controller/satellite_controller.py | 2 +- cbpi/controller/system_controller.py | 18 +++++++++++++ cbpi/http_endpoints/http_system.py | 36 ++++++++++++++++++++++++- 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/cbpi/__init__.py b/cbpi/__init__.py index 75aa62c..357bfeb 100644 --- a/cbpi/__init__.py +++ b/cbpi/__init__.py @@ -1 +1 @@ -__version__ = "4.0.0.57" +__version__ = "4.0.0.58" diff --git a/cbpi/controller/satellite_controller.py b/cbpi/controller/satellite_controller.py index e12223c..4629ac8 100644 --- a/cbpi/controller/satellite_controller.py +++ b/cbpi/controller/satellite_controller.py @@ -109,7 +109,7 @@ class SatelliteController: async with AsyncExitStack() as stack: self.tasks = set() stack.push_async_callback(cancel_tasks, self.tasks) - self.client = Client(self.host, port=self.port, username=self.username, password=self.password, will=Will(topic="cbpi/diconnect", payload="CBPi Server Disconnected")) + self.client = Client(self.host, port=self.port, username=self.username, password=self.password, will=Will(topic="cbpi/disconnect", payload="CBPi Server Disconnected")) await stack.enter_async_context(self.client) diff --git a/cbpi/controller/system_controller.py b/cbpi/controller/system_controller.py index 718edfa..d165447 100644 --- a/cbpi/controller/system_controller.py +++ b/cbpi/controller/system_controller.py @@ -40,6 +40,24 @@ class SystemController: dir_name = pathlib.Path(os.path.join(".", 'config')) shutil.make_archive(output_filename, 'zip', dir_name) + async def downloadlog(self, logtime): + filename = "cbpi4.log" + fullname = pathlib.Path(os.path.join(".",filename)) + output_filename="cbpi4_log.zip" + if logtime == "b": + os.system('journalctl -b -u craftbeerpi.service > {}'.format(fullname)) + else: + os.system('journalctl --since \"{} hours ago\" -u craftbeerpi.service > {}'.format(logtime, fullname)) + + zipObj=zipfile.ZipFile(output_filename , 'w', zipfile.ZIP_DEFLATED) + zipObj.write(fullname) + zipObj.close() + os.remove(fullname) + + + + + def allowed_file(self, filename, extension): return '.' in filename and filename.rsplit('.', 1)[1] in set([extension]) diff --git a/cbpi/http_endpoints/http_system.py b/cbpi/http_endpoints/http_system.py index 468d57a..aa3121b 100644 --- a/cbpi/http_endpoints/http_system.py +++ b/cbpi/http_endpoints/http_system.py @@ -146,6 +146,40 @@ class SystemHttpEndpoints: await response.write_eof() return response + + @request_mapping("/log/{logtime}/", method="GET", name="BackupConfig", auth_required=False) + async def downloadlog(self, request): + """ + --- + description: Zip and download craftbeerpi.service log + tags: + - System + responses: + "200": + description: successful operation + content: # Response body + application/zip: # Media type + """ + logtime = request.match_info['logtime'] + await self.controller.downloadlog(logtime) + filename = "cbpi4_log.zip" + file_name = pathlib.Path(os.path.join(".", filename)) + + response = web.StreamResponse( + status=200, + reason='OK', + headers={'Content-Type': 'application/zip'}, + ) + await response.prepare(request) + with open(file_name, 'rb') as file: + for line in file.readlines(): + await response.write(line) + + await response.write_eof() + os.remove(file_name) + return response + + @request_mapping("/restore", method="POST", name="RestoreConfig", auth_required=False) async def restore(self, request): """ @@ -192,4 +226,4 @@ class SystemHttpEndpoints: data = await request.post() logging.info("Data received") await self.controller.uploadSVG(data) - return web.Response(status=200) \ No newline at end of file + return web.Response(status=200) From bee645ff96a555774ad0483fce08dc2b908a1a1b Mon Sep 17 00:00:00 2001 From: avollkopf <43980694+avollkopf@users.noreply.github.com> Date: Mon, 27 Dec 2021 18:11:40 +0100 Subject: [PATCH 2/2] activate chromium desktop via cli - added option to activate chromium desktop on startup via cli - save also actor, sensor, kettle and plugin information when log is downloaded --- cbpi/__init__.py | 2 +- cbpi/cli.py | 37 ++++++++++++++++++++-- cbpi/controller/system_controller.py | 46 +++++++++++++++++++++++++--- cbpi/controller/upload_controller.py | 2 +- 4 files changed, 79 insertions(+), 8 deletions(-) diff --git a/cbpi/__init__.py b/cbpi/__init__.py index 357bfeb..829fd1d 100644 --- a/cbpi/__init__.py +++ b/cbpi/__init__.py @@ -1 +1 @@ -__version__ = "4.0.0.58" +__version__ = "4.0.0.59" diff --git a/cbpi/cli.py b/cbpi/cli.py index 7552600..89e3e5d 100644 --- a/cbpi/cli.py +++ b/cbpi/cli.py @@ -61,6 +61,12 @@ def create_config_file(): srcfile = os.path.join(os.path.dirname(__file__), "config", "craftbeerpi.service") destfile = os.path.join(".", 'config') shutil.copy(srcfile, destfile) + + if os.path.exists(os.path.join(".", 'config', "chromium.desktop")) is False: + srcfile = os.path.join(os.path.dirname(__file__), "config", "chromium.desktop") + destfile = os.path.join(".", 'config') + shutil.copy(srcfile, destfile) + print("Config Folder created") @@ -184,6 +190,21 @@ def plugins_add(package_name): return return + if package_name == 'chromium': + print("Add chromium.desktop to /etc/xdg/autostart/") + try: + if os.path.exists(os.path.join("/etc/xdg/autostart/","chromium.desktop")) is False: + srcfile = os.path.join(".", "config", "chromium.desktop") + destfile = os.path.join("/etc/xdg/autostart/") + shutil.copy(srcfile, destfile) + print("Copied chromium.desktop to /etc/xdg/autostart/") + else: + print("chromium.desktop is already located in /etc/xdg/autostart/") + except Exception as e: + print(e) + return + return + try: with open(os.path.join(".", 'config', "config.yaml"), 'rt') as f: data = yaml.load(f, Loader=yaml.FullLoader) @@ -230,6 +251,18 @@ def plugin_remove(package_name): return return + if package_name == 'chromium': + print("Remove chromium.desktop from /etc/xdg/autostart/") + try: + if os.path.exists(os.path.join("/etc/xdg/autostart/","chromium.desktop")) is True: + os.remove(os.path.join("/etc/xdg/autostart/","chromium.desktop")) + print("Deleted chromium.desktop from /etc/xdg/autostart/") + else: + print("chromium.desktop is not located in /etc/xdg/autostart/") + except Exception as e: + print(e) + return + return try: @@ -366,14 +399,14 @@ def plugins(): @click.command() @click.argument('name') def add(name): - '''Activate Plugin''' + '''Activate Plugin, autostart or chromium ''' plugins_add(name) @click.command() @click.argument('name') def remove(name): - '''Deactivate Plugin''' + '''Deactivate Plugin, autostart or chromium''' plugin_remove(name) diff --git a/cbpi/controller/system_controller.py b/cbpi/controller/system_controller.py index d165447..33bf050 100644 --- a/cbpi/controller/system_controller.py +++ b/cbpi/controller/system_controller.py @@ -3,6 +3,7 @@ import os import shutil import psutil import pathlib +import json import aiohttp from voluptuous.schema_builder import message from cbpi.api.dataclasses import NotificationAction, NotificationType @@ -43,19 +44,56 @@ class SystemController: async def downloadlog(self, logtime): filename = "cbpi4.log" fullname = pathlib.Path(os.path.join(".",filename)) + pluginname = "cbpi4_plugins.txt" + fullpluginname = pathlib.Path(os.path.join(".",pluginname)) + actorname = "cbpi4_actors.txt" + fullactorname = pathlib.Path(os.path.join(".",actorname)) + sensorname = "cbpi4_sensors.txt" + fullsensorname = pathlib.Path(os.path.join(".",sensorname)) + kettlename = "cbpi4_kettles.txt" + fullkettlename = pathlib.Path(os.path.join(".",kettlename)) + output_filename="cbpi4_log.zip" + if logtime == "b": os.system('journalctl -b -u craftbeerpi.service > {}'.format(fullname)) else: os.system('journalctl --since \"{} hours ago\" -u craftbeerpi.service > {}'.format(logtime, fullname)) - zipObj=zipfile.ZipFile(output_filename , 'w', zipfile.ZIP_DEFLATED) - zipObj.write(fullname) - zipObj.close() - os.remove(fullname) + os.system('cbpi plugins > {}'.format(fullpluginname)) + try: + actors = self.cbpi.actor.get_state() + json.dump(actors['data'],open(fullactorname,'w'),indent=4, sort_keys=True) + sensors = self.cbpi.sensor.get_state() + json.dump(sensors['data'],open(fullsensorname,'w'),indent=4, sort_keys=True) + kettles = self.cbpi.kettle.get_state() + json.dump(kettles['data'],open(fullkettlename,'w'),indent=4, sort_keys=True) + except Exception as e: + logging.info(e) + self.cbpi.notify("Error", "Creation of files failed: {}".format(e), NotificationType.ERROR) + try: + zipObj=zipfile.ZipFile(output_filename , 'w', zipfile.ZIP_DEFLATED) + zipObj.write(fullname) + zipObj.write(fullpluginname) + zipObj.write(fullactorname) + zipObj.write(fullsensorname) + zipObj.write(fullkettlename) + zipObj.close() + except Exception as e: + logging.info(e) + self.cbpi.notify("Error", "Zip creation failed: {}".format(e), NotificationType.ERROR) + try: + os.remove(fullname) + os.remove(fullpluginname) + os.remove(fullactorname) + os.remove(fullsensorname) + os.remove(fullkettlename) + except Exception as e: + logging.info(e) + self.cbpi.notify("Error", "Removal of original files failed: {}".format(e), NotificationType.ERROR) def allowed_file(self, filename, extension): diff --git a/cbpi/controller/upload_controller.py b/cbpi/controller/upload_controller.py index dcfcba8..c0702ad 100644 --- a/cbpi/controller/upload_controller.py +++ b/cbpi/controller/upload_controller.py @@ -7,7 +7,7 @@ from cbpi.api import * import xml.etree.ElementTree import sqlite3 from voluptuous.schema_builder import message -from cbpi.api.dataclasses import NotificationAction, NotificationType +from cbpi.api.dataclasses import NotificationAction, NotificationType, Actor, Sensor, Kettle from cbpi.controller.kettle_controller import KettleController from cbpi.api.base import CBPiBase from cbpi.api.config import ConfigType