File indexing completed on 2024-05-19 05:35:37

0001 # SPDX-License-Identifier: GPL-3.0-or-later
0002 # SPDX-FileCopyrightText: 2021 Anupam Basak <anupam.basak27@gmail.com>
0003 
0004 import os
0005 from queue import SimpleQueue
0006 
0007 import PySide2
0008 from PySide2.QtCore import QUrl, Slot, Signal, Property, QTimer, QProcess
0009 from PySide2.QtQml import qmlRegisterType
0010 from PySide2.QtWidgets import QApplication
0011 
0012 from PicoWizard.module import Module
0013 from PicoWizard.utils.constants import SCRIPTS_DIR
0014 from PicoWizard.utils.logger import Logger
0015 
0016 
0017 class Finish(Module):
0018     log = Logger.getLogger(__name__)
0019 
0020     _isComplete = False
0021     _runningScriptIndex = -1
0022     _totalScriptsCount = -1
0023 
0024     def __init__(self, parent=None):
0025         super().__init__(__file__, parent)
0026         self._scriptsQueue = SimpleQueue()
0027 
0028     @staticmethod
0029     def registerTypes() -> None:
0030         qmlRegisterType(Finish, 'PicoWizard', 1, 0, 'FinishModule')
0031 
0032     @staticmethod
0033     def qmlPath() -> QUrl:
0034         return QUrl(os.path.join(os.path.dirname(os.path.realpath(__file__)), "Finish.qml"))
0035 
0036     def _getIsComplete(self):
0037         return self._isComplete
0038 
0039     def _getRunningScriptIndex(self):
0040         return self._runningScriptIndex
0041 
0042     def _getTotalScriptsCount(self):
0043         return self._totalScriptsCount
0044 
0045     def _processScripts(self):
0046         if self._scriptsQueue.empty():
0047             self._isComplete = True
0048             self.isCompleteChanged.emit()
0049         else:
0050             script = self._scriptsQueue.get()
0051             self._runningScriptIndex += 1
0052             self.runningScriptIndexChanged.emit()
0053 
0054             self.log.info(f'Running Script : {script.arguments()[2]}')
0055 
0056             script.finished.connect(lambda exitCode: self._scriptFinishedHandler(script, exitCode))
0057             script.errorOccurred.connect(lambda error: self._scriptErroredHandler(script, error))
0058             script.readyReadStandardOutput.connect(lambda: self.log.info(f'Output: {script.readAllStandardOutput()}'))
0059 
0060             script.start()
0061 
0062     def _scriptFinishedHandler(self, script, exitCode):
0063         self.log.info(f'Script [{script.arguments()[2]}] Finished: Exit code ({exitCode})')
0064         self._processScripts()
0065 
0066     def _scriptErroredHandler(self, script, error):
0067         self.log.info(f'Script [{script.arguments()[2]}] Errored: {error}')
0068         self._processScripts()
0069 
0070     @Slot(None, result=str)
0071     def moduleName(self) -> str:
0072         return "Finish"
0073 
0074     @Slot(None)
0075     def runScripts(self):
0076         if os.path.exists(SCRIPTS_DIR):
0077             with open("/tmp/pico-wizard.env", "w") as env:
0078                 for key in Module.__ENV__.keys():
0079                     env.writelines(f'export {key}="{Module.__ENV__.value(key)}"\n')
0080 
0081             scripts = os.listdir(SCRIPTS_DIR)
0082             scripts.sort()
0083 
0084             self._totalScriptsCount = len(scripts)
0085             self.totalScriptsCountChanged.emit()
0086 
0087             self.log.debug(Module.__ENV__.toStringList())
0088 
0089             for script in scripts:
0090                 if ".hook" not in script:
0091                     args = [
0092                         "/usr/bin/pico-wizard-script-runner",
0093                         "/tmp/pico-wizard.env",
0094                         os.path.join(SCRIPTS_DIR, script)
0095                     ]
0096 
0097                     process = QProcess(self)
0098                     process.setProgram('/usr/bin/pkexec')
0099                     process.setArguments(args)
0100 
0101                     self._scriptsQueue.put(process)
0102 
0103         self._processScripts()
0104 
0105     @Slot(None)
0106     def runCompleteHook(self):
0107         process = QProcess(self)
0108         args = None
0109 
0110         if os.path.isfile("/etc/pico-wizard/scripts.d/finish.hook"):
0111             self.log.info("Executing finish hook")
0112             args = [
0113                 "/usr/bin/pico-wizard-script-runner",
0114                 "/tmp/pico-wizard.env",
0115                 os.path.join(SCRIPTS_DIR, 'finish.hook')
0116             ]
0117         else:
0118             self.log.info("Rebooting")
0119             args = [
0120                 "/bin/shutdown",
0121                 "-r",
0122                 "now"
0123             ]
0124 
0125         process.start('/usr/bin/pkexec', args)
0126 
0127     @Signal
0128     def isCompleteChanged(self):
0129         pass
0130 
0131     @Signal
0132     def runningScriptIndexChanged(self):
0133         pass
0134 
0135     @Signal
0136     def totalScriptsCountChanged(self):
0137         pass
0138 
0139     isComplete = Property(bool, _getIsComplete, notify=isCompleteChanged)
0140     runningScriptIndex = Property(int, _getRunningScriptIndex, notify=runningScriptIndexChanged)
0141     totalScriptsCount = Property(int, _getTotalScriptsCount, notify=totalScriptsCountChanged)