コード例 #1
0
ファイル: main.py プロジェクト: pandel/opsiPackageBuilder
    def package_import(self, pack: str):
        """
        Import opsi package file into development folder and open it, if successful

        :param pack: package file path
        """
        self.logger.debug("Importing package")

        if self._active_project:
            if not self.project_close():
                return

            self.reset_state()

        # extract product id from package path
        file = Helper.get_file_from_path(pack)
        product = file[:file.rfind("_")]  # remove everything behind product name (version, file extension, etc.)
        project = Helper.concat_path_native(ConfigHandler.cfg.dev_dir, product)

        # import
        try:
            self.startup.hide_me()
            self.do_import(pack)
        except:
            self.logger.error("Package import unsuccessful!")
        else:
            # open
            try:
                self.project_load(project)
            except:
                self.logger.err("Imported package could not be opened!")
コード例 #2
0
ファイル: runner.py プロジェクト: kochd/opsiPackageBuilder
    def check_online_status(self):
        # check if server is generally available
        # use SSH port for connection test
        ret = Helper.test_port(confighandler.ConfigHandler.cfg.opsi_server, confighandler.ConfigHandler.cfg.sshport, 0.5)
        if type(ret) != tuple:
            # check network access and mount network drive if on linux
            if sys.platform == 'win32':
                self.logger.info("System platform: "+ sys.platform)
                if confighandler.ConfigHandler.cfg.usenetdrive == "False":

                    drives = Helper.get_available_drive_letters()
                    if not drives:
                        self.logger.error("No free drive letter found")
                    else:
                        self.logger.info("Free drive letter found: " + repr(drives))
                        self.logger.info("Using drive letter: " + drives[::-1][0])
                        path = "\\\\" + confighandler.ConfigHandler.cfg.opsi_server + "\\" + "opsi_workbench"
                        self.logger.info("Trying to mount path: " + path)
                        ret = MapDrive.mapDrive(drives[::-1][0] + ":", path, confighandler.ConfigHandler.cfg.opsi_user, confighandler.ConfigHandler.cfg.opsi_pass)
                        if ret[0] != 0:
                            self.logger.error("Error mounting path: " + str(ret))
                        else:
                            self.logger.info("Network drive successfully mounted")
                            oPB.NETDRV = drives[::-1][0] + ":"
            else:
                self.logger.info("System platform: "+ sys.platform)
                self.logger.warning("This is not a windows based system. No network drive will be associated")
                self.logger.warning("Please take care, if the specified development base path is correct.")
        else:
            self.logger.warning("opsi server not available. Offline mode activated.")
            self.logger.warning("Return value from connection test: " + str(ret))
            oPB.NETMODE = "offline"
コード例 #3
0
ファイル: main.py プロジェクト: boagoa/opsiPackageBuilder
    def package_import(self, pack: str):
        """
        Import opsi package file into development folder and open it, if successful

        :param pack: package file path
        """
        self.logger.debug("Importing package")

        if self._active_project:
            if not self.project_close():
                return

            self.reset_state()

        # extract product id from package path
        file = Helper.get_file_from_path(pack)
        product = file[:file.rfind(
            "_"
        )]  # remove everything behind product name (version, file extension, etc.)
        project = Helper.concat_path_native(ConfigHandler.cfg.dev_dir, product)

        # import
        try:
            self.startup.hide_me()
            self.do_import(pack)
        except:
            self.logger.error("Package import unsuccessful!")
        else:
            # open
            try:
                self.project_load(project)
            except:
                self.logger.err("Imported package could not be opened!")
コード例 #4
0
ファイル: main.py プロジェクト: boagoa/opsiPackageBuilder
    def update_backend_data(self):
        """Write data from model into backend"""
        self.logger.debug("Updateing backend data from model")

        self.controlData.id = self.model_fields.item(0, 1).text()
        self.controlData.name = self.model_fields.item(0, 2).text()
        self.controlData.description = self.model_fields.item(0, 3).text()
        self.controlData.advice = self.model_fields.item(0, 4).text()
        self.controlData.type = self.model_fields.item(0, 5).text()
        self.controlData.productversion = self.model_fields.item(0, 6).text()
        self.controlData.packageversion = self.model_fields.item(0, 7).text()
        self.controlData.priority = int(self.model_fields.item(0, 8).text())
        self.controlData.licenseRequired = self.model_fields.item(0, 9).text()
        self.controlData.setupScript = self.model_fields.item(0, 10).text()
        self.controlData.uninstallScript = self.model_fields.item(0, 11).text()
        self.controlData.updateScript = self.model_fields.item(0, 12).text()
        self.controlData.alwaysScript = self.model_fields.item(0, 13).text()
        self.controlData.onceScript = self.model_fields.item(0, 14).text()
        self.controlData.customScript = self.model_fields.item(0, 15).text()
        self.controlData.userLoginScript = self.model_fields.item(0, 16).text()

        rows = self.model_dependencies.rowCount()
        self.controlData.dependencies = []
        if self.model_dependencies.item(
                0, 0) is not None:  # empty dependency list
            for i in range(0, rows, 1):
                #self.logger.debug("Reading dependency: " + str(i))
                dep = ProductDependency()
                dep.dependencyForAction = self.model_dependencies.item(
                    i, 0).text()
                dep.requiredProductId = self.model_dependencies.item(i,
                                                                     1).text()
                dep.requiredAction = self.model_dependencies.item(i, 2).text()
                dep.requiredInstallationStatus = self.model_dependencies.item(
                    i, 3).text()
                dep.requirementType = self.model_dependencies.item(i, 4).text()
                self.controlData.dependencies_append(dep)

        rows = self.model_properties.rowCount()
        self.controlData.properties = []
        if self.model_properties.item(0, 0) is not None:  # empty property list
            for i in range(0, rows, 1):
                #self.logger.debug("Reading property: " + str(i))
                prop = ProductProperty()
                prop.name = self.model_properties.item(i, 0).text()
                prop.type = self.model_properties.item(i, 1).text()
                prop.multivalue = self.model_properties.item(i, 2).text()
                prop.editable = self.model_properties.item(i, 3).text()
                prop.description = self.model_properties.item(i, 4).text()
                if prop.type == "bool":
                    prop.values = ""
                    prop.default = self.model_properties.item(i, 6).text()
                else:
                    prop.values = Helper.paramlist2list(
                        self.model_properties.item(i, 5).text())
                    prop.default = Helper.paramlist2list(
                        self.model_properties.item(i, 6).text())
                self.controlData.properties_append(prop)
コード例 #5
0
ファイル: main.py プロジェクト: kochd/opsiPackageBuilder
    def update_backend_data(self):
        """
        Write data from model into backend

        :return:
        """
        self.controlData.id = self.model_fields.item(0, 1).text()
        self.controlData.name = self.model_fields.item(0, 2).text()
        self.controlData.description = self.model_fields.item(0, 3).text()
        self.controlData.advice = self.model_fields.item(0, 4).text()
        self.controlData.type = self.model_fields.item(0, 5).text()
        self.controlData.productversion = self.model_fields.item(0, 6).text()
        self.controlData.packageversion = self.model_fields.item(0, 7).text()
        self.controlData.priority = int(self.model_fields.item(0, 8).text())
        self.controlData.licenseRequired = self.model_fields.item(0, 9).text()
        self.controlData.setupScript = self.model_fields.item(0, 10).text()
        self.controlData.uninstallScript = self.model_fields.item(0, 11).text()
        self.controlData.updateScript = self.model_fields.item(0, 12).text()
        self.controlData.alwaysScript = self.model_fields.item(0, 13).text()
        self.controlData.onceScript = self.model_fields.item(0, 14).text()
        self.controlData.customScript = self.model_fields.item(0, 15).text()
        self.controlData.userLoginScript = self.model_fields.item(0, 16).text()

        rows = self.model_dependencies.rowCount()
        self.controlData.dependencies = []
        if type(self.model_dependencies.item(0, 0)) is not None:  # empty dependency list
            for i in range(0, rows, 1):
                dep = ProductDependency()
                dep.dependencyForAction = self.model_dependencies.item(i, 0).text()
                dep.requiredProductId = self.model_dependencies.item(i, 1).text()
                dep.requiredAction = self.model_dependencies.item(i, 2).text()
                dep.requiredInstallationStatus = self.model_dependencies.item(i, 3).text()
                dep.requirementType = self.model_dependencies.item(i, 4).text()
                self.controlData.dependencies_append(dep)

        rows = self.model_properties.rowCount()
        self.controlData.properties = []
        if type(self.model_properties.item(0, 0)) is not None:  # empty property list
            for i in range(0, rows, 1):
                prop = ProductProperty()
                prop.name = self.model_properties.item(i, 0).text()
                prop.type = self.model_properties.item(i, 1).text()
                prop.multivalue = self.model_properties.item(i, 2).text()
                prop.editable = self.model_properties.item(i, 3).text()
                prop.description = self.model_properties.item(i, 4).text()
                if prop.type == "bool":
                    prop.values = ""
                    prop.default = self.model_properties.item(i, 6).text()
                else:
                    prop.values = Helper.paramlist2list(self.model_properties.item(i, 5).text())
                    prop.default = Helper.paramlist2list(self.model_properties.item(i, 6).text())
                self.controlData.properties_append(prop)
コード例 #6
0
 def validate(self, p_str, p_int):
     if p_str == "":
         return ScriptFileValidator.Intermediate, p_str, p_int
     if os.path.exists(Helper.concat_path_and_file(self._parent.lblPacketFolder.text().replace('\\','/') + "/CLIENT_DATA/", p_str)):
         return ScriptFileValidator.Acceptable, p_str, p_int
     else:
         return ScriptFileValidator.Invalid, p_str, p_int
コード例 #7
0
ファイル: base.py プロジェクト: pandel/opsiPackageBuilder
    def msgbox(self, msgtext = "", typ = oPB.MsgEnum.MS_STAT, parent = None):
        """
        Message box function (virtual)

        **HAS TO BE RE-IMPLEMENTED**

        Valid values for ``typ``:

            * oPB.MsgEnum.MS_ERR -> Error message (status bar/ popup)
            * oPB.MsgEnum.MS_WARN -> Warning (status bar/ popup)
            * oPB.MsgEnum.MS_INFO -> Information (status bar/ popup)
            * oPB.MsgEnum.MS_STAT -> Information (only status bar)
            * oPB.MsgEnum.MS_ALWAYS -> Display this message ALWAYS, regardless of which message ``typ`` is deactivated via settings
            * oPB.MsgEnum.MS_PARSE -> just parse message text and return it
            * oPB.MsgEnum.MS_QUEST_YESNO -> return True / False
            * oPB.MsgEnum.MS_QUEST_CTC -> build question: cancel (return 0)/ rebuild return(1)/ add return (2)
            * oPB.MsgEnum.MS_QUEST_OKCANCEL -> return True / False
            * oPB.MsgEnum.MS_QUEST_PHRASE -> return text from input box

        :param msgtext: Message text
        :param typ: type of message window, see oPB.core enums
        :return variant: see descriptions for ``typ``

        """

        if parent is None:
            parent = self.ui

        # first parse text
        msgtext = Helper.parse_text(msgtext)
        pass
コード例 #8
0
    def onlinecheck(self):
        self.logger.info("Online check")
        if self._active_side == "left":
            depot = self._ui_box_left.currentText().split()[0]
        else:
            depot = self._ui_box_right.currentText().split()[0]

        msg = "\n\n" + translate("depotmanagerController",
                                 "Selected depot:") + "\n" + depot
        self.logger.debug("Selected depot: " + depot)

        ret = Helper.test_port(depot, ConfigHandler.cfg.sshport, 0.5)
        print(ret)

        if ret is True:
            self._parent.msgbox(translate("depotmanagerController",
                                          "The selected depot is ONLINE.") +
                                msg,
                                oPB.MsgEnum.MS_ALWAYS,
                                parent=self.ui)
        else:
            msg += "\n\n" + str(ret)
            self._parent.msgbox(translate("depotmanagerController",
                                          "The selected depot is OFFLINE.") +
                                msg,
                                oPB.MsgEnum.MS_ALWAYS,
                                parent=self.ui)
コード例 #9
0
ファイル: base.py プロジェクト: azra1l/opsiPackageBuilder
    def msgbox(self, msgtext = "", typ = oPB.MsgEnum.MS_STAT, parent = None):
        """
        Message box function (virtual)

        **HAS TO BE RE-IMPLEMENTED**

        Valid values for ``typ``:

            * oPB.MsgEnum.MS_ERR -> Error message (status bar/ popup)
            * oPB.MsgEnum.MS_WARN -> Warning (status bar/ popup)
            * oPB.MsgEnum.MS_INFO -> Information (status bar/ popup)
            * oPB.MsgEnum.MS_STAT -> Information (only status bar)
            * oPB.MsgEnum.MS_ALWAYS -> Display this message ALWAYS, regardless of which message ``typ`` is deactivated via settings
            * oPB.MsgEnum.MS_PARSE -> just parse message text and return it
            * oPB.MsgEnum.MS_QUEST_YESNO -> return True / False
            * oPB.MsgEnum.MS_QUEST_CTC -> build question: cancel (return 0)/ rebuild return(1)/ add return (2)
            * oPB.MsgEnum.MS_QUEST_OKCANCEL -> return True / False
            * oPB.MsgEnum.MS_QUEST_PHRASE -> return text from input box

        :param msgtext: Message text
        :param typ: type of message window, see oPB.core enums
        :return variant: see descriptions for ``typ``

        """

        if parent is None:
            parent = self.ui

        # first parse text
        msgtext = Helper.parse_text(msgtext)
        pass
コード例 #10
0
ファイル: base.py プロジェクト: pandel/opsiPackageBuilder
 def create_project_paths(self, base):
     for elem in oPB.BASE_FOLDERS:
         try:
             path = Path(Helper.concat_path_native(base, elem))
             if not path.exists():
                 path.mkdir(parents=True)
         except OSError:
             raise
コード例 #11
0
ファイル: base.py プロジェクト: azra1l/opsiPackageBuilder
 def create_project_paths(self, base):
     for elem in oPB.BASE_FOLDERS:
         try:
             path = Path(Helper.concat_path_native(base, elem))
             if not path.exists():
                 path.mkdir(parents=True)
         except OSError:
             raise
コード例 #12
0
ファイル: main.py プロジェクト: boagoa/opsiPackageBuilder
    def set_selected_script(self, script, script_type):
        """
        Receives select signal from window button, writes filename to model
        and emits itemChanged signal

        :param script: full pathname to script
        :param script_type: type of script
        """
        self.logger.debug("Set selected script: (" + script + ") (" +
                          script_type + ")")
        if script_type == "setup":
            self.model_fields.item(0, 10).setText(
                Helper.get_file_from_path(script))
        if script_type == "uninstall":
            self.model_fields.item(0, 11).setText(
                Helper.get_file_from_path(script))
        if script_type == "update":
            self.model_fields.item(0, 12).setText(
                Helper.get_file_from_path(script))
        if script_type == "always":
            self.model_fields.item(0, 13).setText(
                Helper.get_file_from_path(script))
        if script_type == "once":
            self.model_fields.item(0, 14).setText(
                Helper.get_file_from_path(script))
        if script_type == "custom":
            self.model_fields.item(0, 15).setText(
                Helper.get_file_from_path(script))
        if script_type == "userlogin":
            self.model_fields.item(0, 16).setText(
                Helper.get_file_from_path(script))
コード例 #13
0
    def get_msiproductcode(self):
        """Show MSI product code of individual MSI file"""
        self.logger.debug("Show MSI product code " + platform.system())
        if platform.system() in ["Windows"]:

            ext = "MSI Package (*.msi)"

            msi = QFileDialog.getOpenFileName(self, translate("MainWindow", "Choose package file"),
                                                "", ext)

            if not msi == ("", ""):
                self.logger.debug("Selected package: " + msi[0])
                prodcode = Helper.get_msi_property(msi[0])
                self._parent.msgbox(translate("MainWindow", "Selected MSI: " + Helper.get_file_from_path(msi[0]) + "\n\n" + "Product Code: " + " " + prodcode), oPB.MsgEnum.MS_ALWAYS, self)
            else:
                self.logger.debug("Dialog aborted.")
        else:
            self._parent.msgbox(translate("MainWindow", "Function not available at the moment for system:" + " " + platform.system()), oPB.MsgEnum.MS_ALWAYS, self)
コード例 #14
0
ファイル: settings.py プロジェクト: kochd/opsiPackageBuilder
    def select_dev_dir(self):
        self.logger.debug("Select development directory")
        directory = QFileDialog.getExistingDirectory(self, translate("SettingsDialog", "Select development folder"),
                                                     ConfigHandler.cfg.dev_dir, QFileDialog.ShowDirsOnly)

        if not directory == "":
            self.logger.info("Chosen directory: " + directory)
            self.inpDevFolder.setText(Helper.concat_path_and_file(directory, ""))
            self.dataChanged.emit()
        else:
            self.logger.debug("Dialog aborted.")
コード例 #15
0
    def __init__(self, parent=None, applangprefix=""):
        """
        Constructor of Translator class

        :param parent: parent, mostly qApp
        :param applangprefix: application language file prefix
        """

        if Translator.cfg is None:
            Translator.cfg = self

            Translator.cfg._parent = parent

            super().__init__(Translator.cfg._parent)

            Translator.cfg._qt_local_path = None
            Translator.cfg._app_locale_path = None
            Translator.cfg._syslocale = None
            Translator.cfg._current_lang = "en"
            Translator.cfg.applangprefix = applangprefix

            Translator.cfg._combobox = None
            Translator.cfg._dialog = None

            # different translators
            Translator.cfg.translator_qt = None
            Translator.cfg.translator_qtbase = None
            Translator.cfg.translator_qthelp = None
            Translator.cfg.translator_qtmm = None
            Translator.cfg.translator_qtwebengine = None
            Translator.cfg.translator_app = None

            pyqt_path = os.path.dirname(PyQt5.__file__)

            if platform.system() == "Windows":
                Translator.cfg._qt_locale_path = Helper.concat_path_native(
                    pyqt_path, "Qt\\translations")
            else:
                if os.path.isdir("/usr/share/qt5/translations/"):
                    Translator.cfg._qt_locale_path = "/usr/share/qt5/translations/"

                else:
                    # we assume, that library plugin path is sibling to translations path
                    # so let's find the plugins and construct translations path
                    lib_dirs = qApp.libraryPaths()

                    for d in lib_dirs:
                        l = os.path.join(d, "../translations")
                        if os.path.isdir(l):
                            Translator.cfg._qt_locale_path = l
                            break

            Translator.cfg._app_locale_path = ":locale/"
            Translator.cfg._syslocale = QtCore.QLocale().system().name()[:2]
コード例 #16
0
    def __init__(self, parent = None, applangprefix = ""):
        """
        Constructor of Translator class

        :param parent: parent, mostly qApp
        :param applangprefix: application language file prefix
        """

        if Translator.cfg is None:
            Translator.cfg = self

            Translator.cfg._parent = parent

            super().__init__(Translator.cfg._parent)

            Translator.cfg._qt_local_path = None
            Translator.cfg._app_locale_path = None
            Translator.cfg._syslocale = None
            Translator.cfg._current_lang = "en"
            Translator.cfg.applangprefix = applangprefix

            Translator.cfg._combobox = None
            Translator.cfg._dialog = None

            # different translators
            Translator.cfg.translator_qt = None
            Translator.cfg.translator_qtbase = None
            Translator.cfg.translator_qthelp = None
            Translator.cfg.translator_qtmm = None
            Translator.cfg.translator_qtwebengine = None
            Translator.cfg.translator_app = None

            pyqt_path = os.path.dirname(PyQt5.__file__)

            if platform.system() == "Windows":
                Translator.cfg._qt_locale_path = Helper.concat_path_native(pyqt_path, "Qt\\translations")
            else:
                if os.path.isdir("/usr/share/qt5/translations/"):
                    Translator.cfg._qt_locale_path = "/usr/share/qt5/translations/"

                else:
                    # we assume, that library plugin path is sibling to translations path
                    # so let's find the plugins and construct translations path
                    lib_dirs = qApp.libraryPaths()

                    for d in lib_dirs:
                        l = os.path.join(d, "../translations")
                        if os.path.isdir(l):
                            Translator.cfg._qt_locale_path = l
                            break

            Translator.cfg._app_locale_path = ":locale/"
            Translator.cfg._syslocale = QtCore.QLocale().system().name()[:2]
コード例 #17
0
    def check_online_status(self):
        self.logger.debug("Check online status")
        # check if server is generally available
        # use SSH port for connection test
        ret = Helper.test_port(confighandler.ConfigHandler.cfg.opsi_server, confighandler.ConfigHandler.cfg.sshport, 0.5)
        if ret is True:
            # check network access and mount network drive if on linux
            if sys.platform == 'win32':
                self.logger.info("System platform: "+ sys.platform)
                if self.args.nonetdrive is False:
                    if confighandler.ConfigHandler.cfg.usenetdrive == "False":

                        drives = Helper.get_available_drive_letters()
                        if not drives:
                            self.logger.error("No free drive letter found")
                        else:
                            self.logger.info("Free drive letter found: " + repr(drives))
                            self.logger.info("Using drive letter: " + drives[::-1][0])
                            path = "\\\\" + confighandler.ConfigHandler.cfg.opsi_server + "\\" + "opsi_workbench"
                            self.logger.info("Trying to mount path: " + path)
                            ret = MapDrive.mapDrive(drives[::-1][0] + ":", path, confighandler.ConfigHandler.cfg.opsi_user, confighandler.ConfigHandler.cfg.opsi_pass)
                            if ret[0] != 0:
                                self.logger.error("Error mounting path: " + str(ret))
                            else:
                                self.logger.info("Network drive successfully mounted")
                                oPB.NETDRV = drives[::-1][0] + ":"
                    else:
                        self.logger.info("Using existing network drive")
                else:
                    self.logger.info("Mounting of network drive via command line disabled")
            else:
                self.logger.info("System platform: "+ sys.platform)
                self.logger.warning("This is not a windows based system. No network drive will be associated")
                self.logger.warning("Please take care, that the specified development base path is correct.")
        else:
            self.logger.warning("opsi server not available. Offline mode activated.")
            self.logger.warning("Return value from connection test: " + str(ret))
            oPB.NETMODE = "offline"
コード例 #18
0
ファイル: settings.py プロジェクト: kochd/opsiPackageBuilder
    def select_keyfile(self):
        self.logger.debug("Select SSH keyfile dialog")

        ext = "Private key file (" + ("; ").join(["*." + x for x in oPB.KEYFILE_EXT]) + ")"  # generate file extension selection string for dialog

        script = QFileDialog.getOpenFileName(self, translate("SettingsDialog", "Choose keyfile"),
                                            ConfigHandler.cfg.dev_dir, ext)

        if not script == ("", ""):
            self.logger.debug("Selected SSH keyfile: " + script[0])
            self.inpKeyFile.setText(Helper.concat_path_and_file(script[0], ""))
            self.dataChanged.emit()
        else:
            self.logger.debug("Dialog aborted.")
コード例 #19
0
ファイル: settings.py プロジェクト: kochd/opsiPackageBuilder
    def select_externaleditor(self):
        self.logger.debug("Select scripteditor dialog")

        ext = "Program (" + ("; ").join(["*." + x for x in oPB.PRG_EXT]) + ")"  # generate file extension selection string for dialog

        script = QFileDialog.getOpenFileName(self, translate("SettingsDialog", "Choose Scripteditor"),
                                            ConfigHandler.cfg.dev_dir, ext)

        if not script == ("", ""):
            self.logger.debug("Selected Scripeditor: " + script[0])
            self.inpExternalEditor.setText(Helper.concat_path_and_file(script[0], ""))
            self.dataChanged.emit()
        else:
            self.logger.debug("Dialog aborted.")
コード例 #20
0
    def validate(self, p_str, p_int):
        """
        Validator method

        :param p_str: script full pathname to validate
        :param p_int: (not used)

        :return: tuple(QValidator.state, p_str, p_int)
        """
        if p_str == "":
            return ScriptFileValidator.Intermediate, p_str, p_int
        if os.path.exists(Helper.concat_path_native(self._parent.lblPacketFolder.text().replace('\\','/') + "/CLIENT_DATA/", p_str)):
            return ScriptFileValidator.Acceptable, p_str, p_int
        else:
            return ScriptFileValidator.Invalid, p_str, p_int
コード例 #21
0
    def fill_cmbDepProdID(self):
        """Fill combobox with values from opsi_depot share"""
        self.cmbDepProdID.clear()

        if oPB.NETMODE != "offline":
            try:
                self.logger.debug("Retrieve active package list from depot")
                subpath = "\\\\" + ConfigHandler.cfg.opsi_server + "\\" + oPB.DEPOTSHARE_BASE
                subdirs = Helper.get_subdirlist(subpath)
                subdirs.sort()

                for elem in subdirs:
                    self.cmbDepProdID.addItem(elem)
            except:
                pass
コード例 #22
0
ファイル: settings.py プロジェクト: pandel/opsiPackageBuilder
    def select_dev_dir(self):
        """Development directory selector dialog"""
        self.logger.debug("Select development directory")
        directory = QFileDialog.getExistingDirectory(self, translate("SettingsDialog", "Select development folder"),
                                                     ConfigHandler.cfg.dev_dir, QFileDialog.ShowDirsOnly)

        if not directory == "":
            self.logger.info("Chosen directory: " + directory)
            value = Helper.concat_path_native(directory, "")
            if value[-1:] == "/" or value[-1:] == '\\':
                value = value[:-1]
            self.inpDevFolder.setText(value)
            self.inpLocalShareBase.setText(value)
            self.dataChanged.emit()
        else:
            self.logger.debug("Dialog aborted.")
コード例 #23
0
ファイル: base.py プロジェクト: pandel/opsiPackageBuilder
    def run_command_line(self):
        """Process project action via command line"""
        self.logger.info("Project given via command line: " + self.args.path)
        if os.path.isabs(self.args.path):
            project = self.args.path
        else:
            project = Helper.concat_path_native(ConfigHandler.cfg.dev_dir, self.args.path)

        # load project
        self.load_backend(project)

        # stop if something happened
        if oPB.EXITCODE != oPB.RET_OK:
            return

        # first, set rights
        if self.args.setrights is True:
            self.do_setrights()
            # wait a short moment for disk flushing
            sleep(0.5)

        # stop if something happened
        if oPB.EXITCODE != oPB.RET_OK:
            return

        # build project
        if self.args.build_mode is not None:
            self.logger.info("Command line: build")
            self.do_build()
            # wait a short moment for disk flushing
            sleep(0.5)

        # stop if something happened
        if oPB.EXITCODE != oPB.RET_OK:
            return

        # install / install+setup / uninstall
        try:
            self.logger.info("Command line: " + self.args.packetaction[0])
            if self.args.packetaction[0] == "install":
                self.do_install(depot = ConfigHandler.cfg.opsi_server)
            if self.args.packetaction[0] == "instsetup":
                self.do_installsetup(depot = ConfigHandler.cfg.opsi_server)
            if self.args.packetaction[0] == "uninstall":
                self.do_uninstall(depot = ConfigHandler.cfg.opsi_server)
        except:
            pass
コード例 #24
0
ファイル: base.py プロジェクト: azra1l/opsiPackageBuilder
    def run_command_line(self):
        """Process project action via command line"""
        self.logger.info("Project given via command line: " + self.args.path)
        if os.path.isabs(self.args.path):
            project = self.args.path
        else:
            project = Helper.concat_path_native(ConfigHandler.cfg.dev_dir, self.args.path)

        # load project
        self.load_backend(project)

        # stop if something happened
        if oPB.EXITCODE != oPB.RET_OK:
            return

        # first, set rights
        if self.args.setrights is True:
            self.do_setrights()
            # wait a short moment for disk flushing
            sleep(0.5)

        # stop if something happened
        if oPB.EXITCODE != oPB.RET_OK:
            return

        # build project
        if self.args.build_mode is not None:
            self.logger.info("Command line: build")
            self.do_build()
            # wait a short moment for disk flushing
            sleep(0.5)

        # stop if something happened
        if oPB.EXITCODE != oPB.RET_OK:
            return

        # install / install+setup / uninstall
        try:
            self.logger.info("Command line: " + self.args.packetaction[0])
            if self.args.packetaction[0] == "install":
                self.do_install(depot = ConfigHandler.cfg.opsi_server)
            if self.args.packetaction[0] == "instsetup":
                self.do_installsetup(depot = ConfigHandler.cfg.opsi_server)
            if self.args.packetaction[0] == "uninstall":
                self.do_uninstall(depot = ConfigHandler.cfg.opsi_server)
        except:
            pass
コード例 #25
0
    def select_dev_dir(self):
        """Development directory selector dialog"""
        self.logger.debug("Select development directory")
        directory = QFileDialog.getExistingDirectory(
            self, translate("SettingsDialog", "Select development folder"),
            ConfigHandler.cfg.dev_dir, QFileDialog.ShowDirsOnly)

        if not directory == "":
            self.logger.info("Chosen directory: " + directory)
            value = Helper.concat_path_native(directory, "")
            if value[-1:] == "/" or value[-1:] == '\\':
                value = value[:-1]
            self.inpDevFolder.setText(value)
            self.inpLocalShareBase.setText(value)
            self.dataChanged.emit()
        else:
            self.logger.debug("Dialog aborted.")
コード例 #26
0
    def select_keyfile(self):
        """SSH keyfile selector dialog"""
        self.logger.debug("Select SSH keyfile dialog")

        ext = "Private key file (" + (" ").join([
            "*." + x for x in oPB.KEYFILE_EXT
        ]) + ")"  # generate file extension selection string for dialog

        script = QFileDialog.getOpenFileName(
            self, translate("SettingsDialog", "Choose keyfile"),
            ConfigHandler.cfg.dev_dir, ext)

        if not script == ("", ""):
            self.logger.debug("Selected SSH keyfile: " + script[0])
            self.inpKeyFile.setText(Helper.concat_path_native(script[0], ""))
            self.dataChanged.emit()
        else:
            self.logger.debug("Dialog aborted.")
コード例 #27
0
    def validate(self, p_str, p_int):
        """
        Validator method

        :param p_str: script full pathname to validate
        :param p_int: (not used)

        :return: tuple(QValidator.state, p_str, p_int)
        """
        if p_str == "":
            return ScriptFileValidator.Intermediate, p_str, p_int
        if os.path.exists(
                Helper.concat_path_native(
                    self._parent.lblPacketFolder.text().replace('\\', '/') +
                    "/CLIENT_DATA/", p_str)):
            return ScriptFileValidator.Acceptable, p_str, p_int
        else:
            return ScriptFileValidator.Invalid, p_str, p_int
コード例 #28
0
    def onlinecheck(self):
        self.logger.info("Online check")
        if self._active_side == "left":
            depot = self._ui_box_left.currentText().split()[0]
        else:
            depot = self._ui_box_right.currentText().split()[0]

        msg = "\n\n" + translate("depotmanagerController", "Selected depot:") + "\n" + depot
        self.logger.debug("Selected depot: " + depot)

        ret = Helper.test_port(depot, ConfigHandler.cfg.sshport, 0.5)
        print(ret)

        if ret is True:
            self._parent.msgbox(translate("depotmanagerController", "The selected depot is ONLINE.") + msg, oPB.MsgEnum.MS_ALWAYS,
                                    parent = self.ui)
        else:
            msg  += "\n\n" + str(ret)
            self._parent.msgbox(translate("depotmanagerController", "The selected depot is OFFLINE.") + msg, oPB.MsgEnum.MS_ALWAYS,
                                    parent = self.ui)
コード例 #29
0
ファイル: base.py プロジェクト: azra1l/opsiPackageBuilder
    def load_backend(self, project_name):
        """Load project data."""
        # itemChanged signal has to be disconnected temporarily, because
        # if not, dataChanged would be set after loading
        self.logger.info("Load project: " + project_name)

        self._dataLoaded = None

        self.controlData.load_data(Helper.concat_path_native(ConfigHandler.cfg.dev_dir, project_name))

        while self._dataLoaded is None: # _dataLoaded has to be True or False
            pass

        if not self._dataLoaded:
            self.logger.error("Backend data could not be loaded.")
            self.logger.debug("Set exitcode RET_EOPEN")
            oPB.EXITCODE = oPB.RET_EOPEN
            self.msgbox(translate("baseController", "Project could not be loaded!"), oPB.MsgEnum.MS_ERR)
        else:
            self.logger.info("Backend data loaded")
            self.msgbox(translate("mainController", "Project loaded successfully!"), oPB.MsgEnum.MS_STAT)
コード例 #30
0
ファイル: base.py プロジェクト: pandel/opsiPackageBuilder
    def load_backend(self, project_name):
        """Load project data."""
        # itemChanged signal has to be disconnected temporarily, because
        # if not, dataChanged would be set after loading
        self.logger.info("Load project: " + project_name)

        self._dataLoaded = None

        self.controlData.load_data(Helper.concat_path_native(ConfigHandler.cfg.dev_dir, project_name))

        while self._dataLoaded is None: # _dataLoaded has to be True or False
            pass

        if not self._dataLoaded:
            self.logger.error("Backend data could not be loaded.")
            self.logger.debug("Set exitcode RET_EOPEN")
            oPB.EXITCODE = oPB.RET_EOPEN
            self.msgbox(translate("baseController", "Project could not be loaded!"), oPB.MsgEnum.MS_ERR)
        else:
            self.logger.info("Backend data loaded")
            self.msgbox(translate("baseController", "Project loaded successfully!"), oPB.MsgEnum.MS_STAT)
コード例 #31
0
    def select_externaleditor(self):
        """External editor selector dialog"""
        self.logger.debug("Select scripteditor dialog")

        if platform.system() != "Windows":
            ext = "Program (" + (" ").join([
                "*." + x for x in oPB.PRG_EXT
            ]) + ")"  # generate file extension selection string for dialog
        else:
            ext = "Any (*)"

        script = QFileDialog.getOpenFileName(
            self, translate("SettingsDialog", "Choose Scripteditor"),
            ConfigHandler.cfg.dev_dir, ext)

        if not script == ("", ""):
            self.logger.debug("Selected Scripeditor: " + script[0])
            self.inpExternalEditor.setText(
                Helper.concat_path_native(script[0], ""))
            self.dataChanged.emit()
        else:
            self.logger.debug("Dialog aborted.")
コード例 #32
0
ファイル: settings.py プロジェクト: pandel/opsiPackageBuilder
    def select_logfile(self):
        """Logfile selector dialog"""
        self.logger.debug("Select log file dialog")

        """
        ext = "Log (*.log)"  # generate file extension selection string for dialog

        script = QFileDialog.getOpenFileName(self, translate("SettingsDialog", "Choose folder for logfile"),
                                             ConfigHandler.cfg.log_file, ext)

        if not script == ("", ""):
            self.logger.debug("Selected Logile: " + script[0])
        """

        directory = QFileDialog.getExistingDirectory(self, translate("SettingsDialog", "Select logfile folder"),
                                                     ConfigHandler.cfg.dev_dir, QFileDialog.ShowDirsOnly)

        if not directory == "":
            self.logger.info("Chosen directory: " + directory)
            self.inpLogFile.setText(Helper.concat_path_native(directory, "opb-session.log"))
            self.dataChanged.emit()
        else:
            self.logger.debug("Dialog aborted.")
コード例 #33
0
    def select_script_dialog(self, script_type, setvalue = True):
        """
        Opens a dialog to select a script file / Clear field content

        :param script_type: field type identifier (setup, uninstall, update, always, once, custom, userlogin)
        :param setvalue: set new value = True, empty field only = False
        """
        self.logger.debug("Select script dialog")

        ext = "Scripts (" + "; ".join(["*." + x for x in oPB.SCRIPT_EXT]) + ")"  # generate file extension selection string for dialog

        if setvalue:
            if self.lblPacketFolder.text() == "":
                script = QFileDialog.getOpenFileName(self, translate("MainWindow", "Choose script"),
                                                     ConfigHandler.cfg.dev_dir, ext)
            else:
                script = QFileDialog.getOpenFileName(self, translate("MainWindow", "Choose script"),
                                                     Helper.concat_path_and_file(self.lblPacketFolder.text(), "CLIENT_DATA"), ext)

            if not script == ("", ""):
                self._parent.set_selected_script(script[0], script_type)
        else:
            self._parent.set_selected_script("", script_type)
コード例 #34
0
    def select_logfile(self):
        """Logfile selector dialog"""
        self.logger.debug("Select log file dialog")
        """
        ext = "Log (*.log)"  # generate file extension selection string for dialog

        script = QFileDialog.getOpenFileName(self, translate("SettingsDialog", "Choose folder for logfile"),
                                             ConfigHandler.cfg.log_file, ext)

        if not script == ("", ""):
            self.logger.debug("Selected Logile: " + script[0])
        """

        directory = QFileDialog.getExistingDirectory(
            self, translate("SettingsDialog", "Select logfile folder"),
            ConfigHandler.cfg.dev_dir, QFileDialog.ShowDirsOnly)

        if not directory == "":
            self.logger.info("Chosen directory: " + directory)
            self.inpLogFile.setText(
                Helper.concat_path_native(directory, "opb-session.log"))
            self.dataChanged.emit()
        else:
            self.logger.debug("Dialog aborted.")
コード例 #35
0
ファイル: main.py プロジェクト: kochd/opsiPackageBuilder
    def set_selected_script(self, script, script_type):
        """
        Receives select signal from window button, writes filename to model
        and emits itemChanged signal

        :param script: full pathname to script
        :param script_type: type of script
        """
        self.logger.debug("Set selected script: (" + script + ") (" + script_type + ")")
        if script_type == "setup":
            self.model_fields.item(0, 10).setText(Helper.get_file_from_path(script))
        if script_type == "uninstall":
            self.model_fields.item(0, 11).setText(Helper.get_file_from_path(script))
        if script_type == "update":
            self.model_fields.item(0, 12).setText(Helper.get_file_from_path(script))
        if script_type == "always":
            self.model_fields.item(0, 13).setText(Helper.get_file_from_path(script))
        if script_type == "once":
            self.model_fields.item(0, 14).setText(Helper.get_file_from_path(script))
        if script_type == "custom":
            self.model_fields.item(0, 15).setText(Helper.get_file_from_path(script))
        if script_type == "userlogin":
            self.model_fields.item(0, 16).setText(Helper.get_file_from_path(script))
コード例 #36
0
ファイル: runner.py プロジェクト: kochd/opsiPackageBuilder
    def __init__(self, parent = None):
        """Create a wizard or the mainwindow"""
        super().__init__(parent)

        self.logger = None
        self.args = self.get_args()

        # redirect system exception hook
        sys.excepthook = self.excepthook

        # create new application
        self.app = QApplication(sys.argv)

        # Application name
        self.app.setOrganizationName("opsi Package Builder")
        self.app.setApplicationName("opsi Package Builder " + oPB.PROGRAM_VERSION)

        # save ourselves in main instance property to be easily accessd via qApp
        # i.e.
        # from PyQt5.QtWidgets import qApp
        # main = qApp.property("main")
        self.app.setProperty("main", self)

        # Initialize the logger
        self.logWindow =  oPB.gui.logging.LogDialog(None, self, self.args.log_level.upper())
        self.instantiate_logger(False)

        #self.instantiate_logger_old()

        # instantiate configuration class
        confighandler.ConfigHandler(oPB.CONFIG_INI)

        # log program version and user
        self.logger.info("opsi PackageBuilder (MIT licensed) " + oPB.PROGRAM_VERSION)
        self.logger.info("Current user: "******"Command line arguments given:")
        for key, val in vars(self.args).items():
            self.logger.info("  " + key + ": " + str(val))
        if self.args.log_level.upper() not in ["DEBUG", "INFO", "SSHINFO", "WARNING", "ERROR", "CRITICAL", "SSH"]:
            self.logger.error("  Undefined log level: " + self.args.log_file.upper())
            self.logger.error("  Log level has been set to ERROR")

        for elem in self.app.libraryPaths():
            self.logger.debug("QT5 library path: " + elem)

        self.install_translations()

        self.check_online_status()

        # -----------------------------------------------------------------------------------------
        # main ui dispatching

        # startup gui variant
        if not self.args.nogui:

            # startup program window
            self.mainWindow = main.MainWindowController(self.args)
            self.mainWindow.ui.showLogRequested.connect(self.logWindow.show)
            self.mainWindow.closeAppRequested.connect(self.logWindow.close)

            # run main app loop
            self.app.exec_()

        # only process commandline
        else:
            self.logger.info("No-GUI parameter set")

            # startup program window
            self.console = console.ConsoleController(self.args)

        # -----------------------------------------------------------------------------------------

        # unmount drive after end of program
        if oPB.NETDRV is not None:
            ret = MapDrive.unMapDrive(oPB.NETDRV)
            if ret[0] != 0:
                self.logger.error("Error unmounting path: " + str(ret))
            else:
                self.logger.info("Network drive successfully unmounted")

        # exit and set return code
        self.logger.debug("Exit code: " + str(oPB.EXITCODE))

        sys.exit(oPB.EXITCODE)
コード例 #37
0
ファイル: main.py プロジェクト: pandel/opsiPackageBuilder
    def msgbox(self, msgtext = "", typ = oPB.MsgEnum.MS_STAT, parent = None, preload = ""):
        """ Messagebox function

        Valid values for typ:
            * oPB.MsgEnum.MS_ERR -> Error message (status bar/ popup)
            * oPB.MsgEnum.MS_WARN -> Warning (status bar/ popup)
            * oPB.MsgEnum.MS_INFO -> Information (status bar/ popup)
            * oPB.MsgEnum.MS_STAT -> Information (only status bar)
            * oPB.MsgEnum.MS_ALWAYS -> Display this message ALWAYS, regardless of which message **typ** is deactivated via settings
            * oPB.MsgEnum.MS_PARSE -> just parse message text and return it
            * oPB.MsgEnum.MS_QUEST_YESNO
            * oPB.MsgEnum.MS_QUEST_CTC
            * oPB.MsgEnum.MS_QUEST_OKCANCEL
            * oPB.MsgEnum.MS_QUEST_PHRASE
            * oPB.MsgEnum.MS_QUEST_PASS
            * oPB.MsgEnum.MS_QUEST_DEPOT

        :param msgtext: Message text
        :param typ: type of message window, see oPB.core enums
        :param parent: parent ui of message box
        :param preload: pre-fill input boxes with this text
        """
        if parent is None:
            parent = self.ui

        # first parse text, is argument is str
        if type(msgtext) is str:
            msgtext = Helper.parse_text(msgtext)

        if typ == oPB.MsgEnum.MS_ERR:
            self.msgSend.emit(msgtext)
            if ConfigHandler.cfg.no_error_msg == "False":
                QMessageBox.critical(parent, translate("mainController", "Error"), msgtext, QMessageBox.Ok)

        elif typ == oPB.MsgEnum.MS_WARN:
            self.msgSend.emit(msgtext)
            if ConfigHandler.cfg.no_warning_msg == "False":
                QMessageBox.warning(parent, translate("mainController", "Warning"), msgtext, QMessageBox.Ok)

        elif typ == oPB.MsgEnum.MS_INFO:
            self.msgSend.emit(msgtext)
            if ConfigHandler.cfg.no_info_msg == "False":
                QMessageBox.information(parent, translate("mainController", "Message"), msgtext, QMessageBox.Ok)

        elif typ == oPB.MsgEnum.MS_STAT:
            self.msgSend.emit(msgtext)

        elif typ == oPB.MsgEnum.MS_ALWAYS:
            QMessageBox.information(parent, translate("mainController", "Message"), msgtext, QMessageBox.Ok)

        elif typ == oPB.MsgEnum.MS_PARSE:
            return msgtext

        elif typ == oPB.MsgEnum.MS_QUEST_YESNO:
            retval = QMessageBox.question(parent, translate("mainController", "Question"), msgtext, QMessageBox.Yes, QMessageBox.No)
            if retval == QMessageBox.No:
                return False
            else:
                return True

        elif typ == oPB.MsgEnum.MS_QUEST_CTC:
            msgBox = QMessageBox(parent)
            msgBox.setWindowTitle(translate("mainController", "Question"))
            msgBox.setText(msgtext)
            msgBox.setIcon(QMessageBox.Question)
            cancelBtn = QPushButton(translate("mainController", "Cancel"))
            rebuildBtn = QPushButton(translate("mainController", "Rebuild"))
            addBtn = QPushButton(translate("mainController", "Add version"))
            msgBox.addButton(cancelBtn, QMessageBox.RejectRole)
            msgBox.addButton(rebuildBtn, QMessageBox.AcceptRole)
            msgBox.addButton(addBtn, QMessageBox.AcceptRole)
            msgBox.exec_()
            if msgBox.clickedButton() == cancelBtn:
                return 0
            elif msgBox.clickedButton() == rebuildBtn:
                return 1
            else:
                return 2

        elif typ == oPB.MsgEnum.MS_QUEST_OKCANCEL:
            retval = QMessageBox.question(parent, translate("mainController", "Question"), msgtext, QMessageBox.Ok, QMessageBox.Cancel)
            if retval == QMessageBox.Cancel:
                return False
            else:
                return True

        elif typ == oPB.MsgEnum.MS_QUEST_PHRASE:
            text = QInputDialog.getText(parent, translate("mainController", "Additional information"),
                                          msgtext, QLineEdit.Normal, preload)
            return text

        elif typ == oPB.MsgEnum.MS_QUEST_PASS:
            text = QInputDialog.getText(parent, translate("mainController", "Additional information"),
                                          msgtext, QLineEdit.Password, preload)
            return text

        elif typ == oPB.MsgEnum.MS_QUEST_DEPOT:
            preselectlist = [i for i, j in enumerate(msgtext) if ConfigHandler.cfg.opsi_server in j]
            if preselectlist:
                preselect = preselectlist[0]
            else:
                preselect = -1
            item = QInputDialog.getItem(parent, translate("mainController", "Question"),
                                        translate("mainController", "Select which depot to use:"),
                                        msgtext, preselect, False)
            return item

        elif typ == oPB.MsgEnum.MS_ABOUTQT:
            QMessageBox.aboutQt(parent, translate("mainController", "About Qt"))
コード例 #38
0
ファイル: bundle.py プロジェクト: cbka/opsiPackageBuilder
    def create_bundle(self, prods=[]):
        self.logger.debug("Create bundle from selection")

        if prods:
            msg = "\n\n" + translate(
                "bundleController", "Chosen products:") + "\n\n" + ("\n").join(
                    [p for p in prods])
            reply = self._parent.msgbox(
                translate("bundleController", "Create product bundle now?") +
                msg, oPB.MsgEnum.MS_QUEST_YESNO)
            if reply is True:
                self.logger.debug("Selected product(s): " + str(prods))

                ok = False
                while not ok:
                    comment = "meta-"
                    accept = False
                    while comment == "" or accept == False:
                        (
                            comment, accept
                        ) = self._parent.msgbox(translate(
                            "bundleController",
                            "Please enter package name (allowed characters: a-z, A-Z, 0-9, ._-):"
                        ),
                                                oPB.MsgEnum.MS_QUEST_PHRASE,
                                                parent=self.ui,
                                                preload=comment)

                        # first test if cancel button was pressed
                        if not accept:
                            self._parent.msgbox(translate(
                                "bundleController",
                                "Package creation canceled!"),
                                                oPB.MsgEnum.MS_ALWAYS,
                                                parent=self.ui)
                            self.logger.debug(
                                "Package bundle creation canceled by the user."
                            )
                            self._parent.startup.show_()
                            return None

                        if ConfigHandler.cfg.age == "True":
                            test = re.match(oPB.OPB_PRODUCT_ID_REGEX_NEW,
                                            comment)
                        else:
                            test = re.match(oPB.OPB_PRODUCT_ID_REGEX_OLD,
                                            comment)

                        if not test:
                            self._parent.msgbox(translate(
                                "bundleController",
                                "Package name is no valid product id!"),
                                                oPB.MsgEnum.MS_ALWAYS,
                                                parent=self.ui)
                            accept = False

                    directory = Helper.concat_path_native(
                        ConfigHandler.cfg.dev_dir, comment)
                    self.logger.info("Chosen directory for new project: " +
                                     directory)
                    if os.path.exists(directory):
                        self._parent.msgbox(translate(
                            "bundleController",
                            "Package name already exists. Please choose another package name!"
                        ),
                                            oPB.MsgEnum.MS_ALWAYS,
                                            parent=self.ui)
                    else:
                        self._parent.project_create(directory)
                        for p in prods:
                            self._parent.add_setup_before_dependency(p)
                        self._parent.controlData.priority = -100
                        self._parent.controlData.setupScript = "dummy.opsiscript"
                        self._parent.controlData.create_script_stub(
                            self._parent.controlData.setupScript)
                        self._parent.save_backend()
                        ok = True
                        self.logger.debug("Package bundle creation finished.")
        else:
            self.logger.debug("Nothing selected.")
コード例 #39
0
ファイル: main.py プロジェクト: pandel/opsiPackageBuilder
    def project_copy(self, project_folder):
        """
        Copies current project data to new project destination

        :param destination: destination for copied project
        """

        dest_data = ""
        val = 0

        def sizeof_fmt(num, suffix='B'):
            for unit in ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']:
                if abs(num) < 1024.0:
                    return "%3.1f%s%s" % (num, unit, suffix)
                num /= 1024.0
            return "%.1f%s%s" % (num, 'Yi', suffix)

        def copy2_(src, dst):
            self.logger.debug("Copying to destination file: " + str(dst))
            self.msgbox("CLIENT_DATA: " + str(dst).replace(dest_data, ""), oPB.MsgEnum.MS_STAT)
            self.progressChanged.emit(val)
            shutil.copy2(src,dst)

        def countFiles(directory):
            files = []
            total_size = 0
            if os.path.isdir(directory):
                for path, dirs, filenames in os.walk(directory):
                    files.extend(filenames)
                    for f in filenames:
                        fp = os.path.join(path, f)
                        total_size += os.path.getsize(fp)

            return len(files), total_size

        def copyDirectory(src, dest):
            self.logger.info("Copying files")
            self.logger.debug("Source: " + src)
            self.logger.debug("Destination:" + dest)
            if os.path.exists(dest):
                shutil.rmtree(dest)
            try:
                shutil.copytree(src, dest, copy_function=copy2_)
            # Directories are the same
            except shutil.Error as e:
                self.logger.error('Directory not copied. Error: %s' % e)
            # Any error saying that the directory doesn't exist
            except OSError as e:
                self.logger.error('Directory not copied. Error: %s' % e)

        self.logger.info("Create new project from current: " + project_folder)

        # create new control object as copy

        if os.path.exists(Helper.concat_path_native(project_folder, "CLIENT_DATA")):
            self.logger.error("CLIENT_DATA subdirectory in destination folder detected. This is not allowed for security reason!")
            self.msgbox(translate("mainController", "CLIENT_DATA subdirectory in destination folder detected. This is not allowed for security reason!"),
                        oPB.MsgEnum.MS_ERR)
            return

        newControl = deepcopy(self.controlData)
        self.create_project_paths(project_folder)
        project_name = PurePath(project_folder).name.replace(" ","_")
        newControl.id = project_name
        newControl.projectfolder = project_folder

        # add changelog entry for this copy process
        text = "Project copied from: " + self.controlData.packagename
        newentry = ChangelogEntry(newControl.id)
        newentry.version = "(" + newControl.productversion + "-" + newControl.packageversion + ")"
        newentry.status = oPB.CHLOG_STATI[0]
        newentry.urgency = oPB.CHLOG_BLOCKMARKER + oPB.CHLOG_URGENCIES[0]
        newentry.text = "\n" + text + changelog_footer()
        newControl.changelog_append(newentry)

        try:
            self.processingStarted.emit()

            newControl.save_data()
            self.logger.debug("New control data saved.")

            dest_data = Helper.concat_path_native(newControl.projectfolder, "CLIENT_DATA")
            total, total_size = countFiles(Helper.concat_path_native(self.controlData.projectfolder, "CLIENT_DATA"))
            val = 100 / total

            reply = self.msgbox(translate("mainController", "Copy files now? This can't be canceled.") + "\n\nTotal: " +  str(total) + "\n" + sizeof_fmt(total_size),
                                oPB.MsgEnum.MS_QUEST_YESNO)
            if reply is True:
                copyDirectory(Helper.concat_path_native(self.controlData.projectfolder, "CLIENT_DATA"),
                              Helper.concat_path_native(newControl.projectfolder, "CLIENT_DATA")
                              )
                self.logger.debug("Files copied.")

            self.processingEnded.emit(True)

            # close current project an re-open clone
            if not self.project_close():
                return

            self.project_load(project_name)
        except:
            self.logger.error("Project could not be copied and re-opened.")
コード例 #40
0
ファイル: scripttree.py プロジェクト: cbka/opsiPackageBuilder
    def open_scripteditor(self):
        """Open script editor after double click on tree view item"""

        self.logger.debug("Start scripteditor")

        idx = self.treeView.currentIndex()
        if idx.isValid():
            sibling = idx.sibling(idx.row(), idx.column() + 1)
            item = self.model.itemFromIndex(sibling)
            script = item.text()

        if "(External)" in script:
            self._parent.msgbox(
                translate(
                    "MainWindow",
                    "Sorry! You cannot edit a script outside the project folder!"
                ), oPB.MsgEnum.MS_ERR, self)
            return

        if ConfigHandler.cfg.editor_intern == "True":
            self._parent.msgbox(
                translate(
                    "MainWindow",
                    "Internal editor not available at the moment. Use external editor instead!"
                ), oPB.MsgEnum.MS_ALWAYS, self)
            self._parentUi.actionSettings.trigger()
            return

        if os.path.exists(ConfigHandler.cfg.scripteditor):
            path = Helper.concat_path_native(
                self._parentUi.lblPacketFolder.text(), "CLIENT_DATA")

            path = Helper.concat_path_native(path, script)

            self.logger.debug("Opening script: " + path)
            cmd = [ConfigHandler.cfg.scripteditor]
            if (ConfigHandler.cfg.editor_options).strip() != "":
                for part in (ConfigHandler.cfg.editor_options).split():
                    cmd.append(part)
                if ConfigHandler.cfg.editor_attachdirect == "True":
                    cmd[-1] = cmd[-1] + path
                else:
                    cmd.append(path)
            else:
                cmd.append(path)

            self.logger.debug("Executing subprocess: " + str(cmd))
            proc = subprocess.Popen(cmd,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE,
                                    universal_newlines=True)
            outs, errs = proc.communicate()
            self.logger.info(outs)
            self.logger.error(errs)
            if proc.returncode != 0:
                self._parent.msgbox(
                    translate(
                        "MainWindow",
                        "Editor startup did not cleanup correctly.\n\nThe following message(s) returned:"
                    ) + "\n\nStandard Out:\n" + outs + "\n\nStandard Err:\n" +
                    errs, oPB.MsgEnum.MS_WARN, self)

        else:
            self._parent.msgbox(
                translate(
                    "MainWindow", "Editor not found:" + " " +
                    ConfigHandler.cfg.scripteditor), oPB.MsgEnum.MS_ERR, self)
コード例 #41
0
    def __init__(self, parent = None):
        """Create a wizard or the mainwindow"""
        self._parent = parent

        super().__init__(self._parent)

        print("runner/Main parent: ", self._parent, " -> self: ", self) if oPB.PRINTHIER else None

        self.logger = None
        self.args = self.get_args()
        self._log_level = None
        self._log_file = None
        self.translator = None

        # make it really quiet, part 1
        if self.args.quiet:
            self.args.nogui = True

        # instantiate configuration class
        confighandler.ConfigHandler(oPB.CONFIG_INI)

        # redirect system exception hook
        if not self.args.noexcepthook:
            sys.excepthook = self.excepthook

        # pre-instantiating the application, avoid some nasty OpenGL messages
        QApplication.setAttribute(QtCore.Qt.AA_UseOpenGLES)
        # create new application and install stylesheet
        self.app = QApplication(sys.argv)
        self.install_stylesheet()

        # Create and display the splash screen, if in ui mode
        if not self.args.nogui:
            splash_pix = QPixmap(':/images/splash.png')
            self.splash = QSplashScreen(splash_pix, QtCore.Qt.WindowStaysOnTopHint)
            self.splash.setMask(splash_pix.mask())
            # splash.showMessage("opsi Package Builder " + oPB.PROGRAM_VERSION + " " + translate("Main", "is loading..."), QtCore.Qt.AlignCenter, QtCore.Qt.white)
            self.splash.show()
            self.app.processEvents()

        # Application name
        self.app.setOrganizationName("opsi Package Builder")
        self.app.setApplicationName("opsi Package Builder " + oPB.PROGRAM_VERSION)

        # save ourselves in main instance property to be easily accessd via qApp
        # i.e.
        # from PyQt5.QtWidgets import qApp
        # main = qApp.property("main")
        self.app.setProperty("main", self)

        if confighandler.ConfigHandler.cfg.log_always == "True":
            if self.args.log_file is not None:
                self._log_file = self.args.log_file
            else:
                self._log_file = confighandler.ConfigHandler.cfg.log_file

            if self.args.log_level.upper() != "NOTSET":
                self._log_level = self.args.log_level.upper()
            else:
                self._log_level = confighandler.ConfigHandler.cfg.log_level
        else:
            self._log_file = self.args.log_file
            if self.args.log_level.upper() == "NOTSET":
                self._log_level = "CRITICAL"
            else:
                self._log_level = self.args.log_level.upper()

        if self._log_file is not None:
            if not pathlib.Path(self._log_file).is_absolute():
                if platform.system() == "Windows":
                    self._log_file = str(pathlib.PurePath(oPB.WIN_TMP_PATH, self._log_file))
                if platform.system() in ["Darwin", "Linux"]:
                    self._log_file = str(pathlib.PurePath(oPB.UNIX_TMP_PATH, self._log_file))

        # overwrite development directory from config with command line arg
        if self.args.dev_dir is not None:
                confighandler.ConfigHandler.cfg.dev_dir = self.args.dev_dir

        # Initialize the logger and reroute QtCore messages to it
        self.logWindow =  oPB.gui.logging.LogDialog(None, self, self._log_level)
        self.instantiate_logger(False)
        QtCore.qInstallMessageHandler(self.qt_message_handler)

        # log program version and user
        self.logger.info(80 * "-")
        self.logger.info("opsi PackageBuilder (MIT licensed) " + oPB.PROGRAM_VERSION)
        self.logger.info("Current user: "******"Command line arguments given:")
        for key, val in vars(self.args).items():
            self.logger.info("  " + key + ": " + str(val))
        if self._log_level not in ["DEBUG", "INFO", "SSHINFO", "WARNING", "ERROR", "CRITICAL", "SSH"]:
            self.logger.error("  Undefined log level: " + self._log_level)
            self.logger.error("  Log level has been set to ERROR")

        for elem in self.app.libraryPaths():
            self.logger.debug("QT5 library path: " + elem)

        # write config to log, if necessary
        confighandler.ConfigHandler.cfg.log_config()


        self.check_online_status()

        # -----------------------------------------------------------------------------------------
        # main ui dispatching

        # startup gui variant
        if not self.args.nogui:

            # hide console window, but only under Windows and only if app is frozen
            if sys.platform.lower().startswith('win'):
                if getattr(sys, 'frozen', False):
                    hideConsole()

            # installing translators
            self.translator = Translator(self.app, "opsipackagebuilder")
            self.translator.install_translations(confighandler.ConfigHandler.cfg.language)

            # retranslate logWindow, as it is loaded before the translations
            self.logWindow.retranslateUi(self.logWindow)

            # create app icon
            app_icon = QtGui.QIcon()
            app_icon.addFile(':images/prog_icons/opb/package_16x16.png', QtCore.QSize(16, 16))
            app_icon.addFile(':images/prog_icons/opb/package_24x24.png', QtCore.QSize(24, 24))
            app_icon.addFile(':images/prog_icons/opb/package_32x32.png', QtCore.QSize(32, 32))
            app_icon.addFile(':images/prog_icons/opb/package_48x48.png', QtCore.QSize(48, 48))
            app_icon.addFile(':images/prog_icons/opb/package_64x64.png', QtCore.QSize(64, 64))
            app_icon.addFile(':images/prog_icons/opb/package_92x92.png', QtCore.QSize(92, 92))
            app_icon.addFile(':images/prog_icons/opb/package_128x128.png', QtCore.QSize(128, 128))
            app_icon.addFile(':images/prog_icons/opb/package_256x256.png', QtCore.QSize(256, 256))
            self.app.setProperty("prog_icon",app_icon)

            # startup program window
            self.mainWindow = main.MainWindowController(self.args)
            self.mainWindow.ui.showLogRequested.connect(self.logWindow.show)
            self.mainWindow.closeAppRequested.connect(self.logWindow.close)

            self.splash.finish(self.mainWindow.ui)

            # check for updates if configured
            if confighandler.ConfigHandler.cfg.updatecheck == "True":
                self.mainWindow.update_check()

            # run main app loop
            self.app.exec_()

        # only process commandline
        else:
            self.logger.info("No-GUI parameter set")

            # startup program window
            self.console = console.ConsoleController(self.args)

        # -----------------------------------------------------------------------------------------

        # unmount drive (if exist) after end of program
        if (oPB.NETDRV is not None) and oPB.NETDRV != "offline":
            ret = MapDrive.unMapDrive(oPB.NETDRV)
            if ret[0] != 0:
                self.logger.error("Error unmounting path: " + str(ret))
            else:
                self.logger.info("Network drive successfully unmounted")

        # exit and set return code
        self.logger.info("Exit code: " + str(oPB.EXITCODE))

        # show console window
        if not self.args.nogui:
            if sys.platform.lower().startswith('win'):
                if getattr(sys, 'frozen', False):
                    showConsole()

        sys.exit(oPB.EXITCODE)
コード例 #42
0
 def userLoginScript(self, value):
     if not Helper.extCheck(value):
         raise ValueError(translate("ControlFileData", "userLogin script has invalid file extension"))
     self._userLoginScript = value
コード例 #43
0
 def customScript(self, value):
     if not Helper.extCheck(value):
         raise ValueError(translate("ControlFileData", "custom script has invalid file extension"))
     self._customScript = value
コード例 #44
0
    def open_scripteditor(self):
        """
        Open configured script editor.

        Method reaction depends on calling widget (self.sender())
        """
        self.logger.debug("Start scripteditor")

        if ConfigHandler.cfg.editor_intern == "True":
            self._parent.msgbox(translate("MainWindow", "Internal editor not available at the moment. Use external editor instead!"), oPB.MsgEnum.MS_ALWAYS, self)
            self.actionSettings.trigger()
            return

        if os.path.exists(ConfigHandler.cfg.scripteditor):
            path = Helper.concat_path_native(self.lblPacketFolder.text(), "CLIENT_DATA")
            if self.sender() == self.btnScrSetupEdit:
                if self.inpScrSetup.text().strip() == "":
                    script = "setup.opsiscript"
                else:
                    script = self.inpScrSetup.text()
            elif self.sender() == self.btnScrUninstallEdit:
                if self.inpScrUninstall.text().strip() == "":
                    script = "uninstall.opsiscript"
                else:
                    script = self.inpScrUninstall.text()
            elif self.sender() == self.btnScrUpdateEdit:
                if self.inpScrUpdate.text().strip() == "":
                    script = "update.opsiscript"
                else:
                    script = self.inpScrUpdate.text()
            elif self.sender() == self.btnScrAlwaysEdit:
                if self.inpScrAlways.text().strip() == "":
                    script = "always.opsiscript"
                else:
                    script = self.inpScrAlways.text()
            elif self.sender() == self.btnScrOnceEdit:
                if self.inpScrOnce.text().strip() == "":
                    script = "once.opsiscript"
                else:
                    script = self.inpScrOnce.text()
            elif self.sender() == self.btnScrCustomEdit:
                if self.inpScrCustom.text().strip() == "":
                    script = "custom.opsiscript"
                else:
                    script = self.inpScrCustom.text()
            elif self.sender() == self.btnScrUserLoginEdit:
                if self.inpScrUserLogin.text().strip() == "":
                    script = "userlogin.opsiscript"
                else:
                    script = self.inpScrUserLogin.text()
            elif self.sender() == self.actionScriptEditor:
                script = "new.opsiscript"

            # script editor from menu
            if path != "" and script != "":
                path = Helper.concat_path_native(path, script)

            self.logger.debug("Opening script: " + path)
            # construct calling array
            # first add basic scripteditor executable
            cmd = [ConfigHandler.cfg.scripteditor]
            # if there are options, split and append them
            if (ConfigHandler.cfg.editor_options).strip() != "":
                for part in (ConfigHandler.cfg.editor_options).split():
                    cmd.append(part)
                # if attach direct is true, combine last option with script file path
                if ConfigHandler.cfg.editor_attachdirect == "True":
                    cmd[-1] = cmd[-1] + path
                # or else, append as separate value to list
                else:
                    cmd.append(path)
            else:
                cmd.append(path)

            self.logger.debug("Executing subprocess: " + str(cmd))
            proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
            outs, errs = proc.communicate()
            self.logger.info(outs)
            self.logger.error(errs)
            if proc.returncode != 0 and proc.returncode != 555:
                self._parent.msgbox(translate("MainWindow", "Editor did not exit as expected.\n\nThe following message(s) returned:") +
                                    "\n\nStandard Out:\n" + outs +
                                    "\nStandard Err:\n" + errs +
                                    "\n\nReturn code: " + str(proc.returncode),
                                    oPB.MsgEnum.MS_WARN, self)
        else:
            self._parent.msgbox(translate("MainWindow", "Editor not found:" + " " + ConfigHandler.cfg.scripteditor), oPB.MsgEnum.MS_ERR, self)
コード例 #45
0
ファイル: main.py プロジェクト: kochd/opsiPackageBuilder
    def msgbox(self, msgtext = "", typ = oPB.MsgEnum.MS_STAT, parent = None):
        """ Messagebox function

        Valid values for typ:
            * oPB.MsgEnum.MS_ERR -> Error message (status bar/ popup)
            * oPB.MsgEnum.MS_WARN -> Warning (status bar/ popup)
            * oPB.MsgEnum.MS_INFO -> Information (status bar/ popup)
            * oPB.MsgEnum.MS_STAT -> Information (only status bar)
            * oPB.MsgEnum.MS_ALWAYS -> Display this message ALWAYS, regardless of which message **typ** is deactivated via settings
            * oPB.MsgEnum.MS_PARSE -> just parse message text and return it
            * oPB.MsgEnum.MS_QUEST_YESNO
            * oPB.MsgEnum.MS_QUEST_CTC
            * oPB.MsgEnum.MS_QUEST_OKCANCEL

        :param msgtext: Message text
        :param typ: type of message window, see oPB.core enums
        """
        if parent is None:
            parent = self.ui

        # first parse text
        msgtext = Helper.parse_text(msgtext)

        if typ == oPB.MsgEnum.MS_ERR:
            self.msgSend.emit(msgtext)
            if ConfigHandler.cfg.no_error_msg == "False":
                QMessageBox.critical(parent, translate("mainController", "Error"), msgtext, QMessageBox.Ok)

        elif typ == oPB.MsgEnum.MS_WARN:
            self.msgSend.emit(msgtext)
            if ConfigHandler.cfg.no_warning_msg == "False":
                QMessageBox.warning(parent, translate("mainController", "Warning"), msgtext, QMessageBox.Ok)

        elif typ == oPB.MsgEnum.MS_INFO:
            self.msgSend.emit(msgtext)
            if ConfigHandler.cfg.no_info_msg == "False":
                QMessageBox.information(parent, translate("mainController", "Message"), msgtext, QMessageBox.Ok)

        elif typ == oPB.MsgEnum.MS_STAT:
            self.msgSend.emit(msgtext)

        elif typ == oPB.MsgEnum.MS_ALWAYS:
            QMessageBox.information(parent, translate("mainController", "Message"), msgtext, QMessageBox.Ok)

        elif typ == oPB.MsgEnum.MS_PARSE:
            return msgtext

        elif typ == oPB.MsgEnum.MS_QUEST_YESNO:
            retval = QMessageBox.question(parent, translate("mainController", "Question"), msgtext, QMessageBox.Yes, QMessageBox.No)
            if retval == QMessageBox.No:
                return False
            else:
                return True

        elif typ == oPB.MsgEnum.MS_QUEST_CTC:
            msgBox = QMessageBox(parent)
            msgBox.setWindowTitle(translate("mainController", "Question"))
            msgBox.setText(msgtext)
            msgBox.setIcon(QMessageBox.Question)
            cancelBtn = QPushButton(translate("mainController", "Cancel"))
            rebuildBtn = QPushButton(translate("mainController", "Rebuild"))
            addBtn = QPushButton(translate("mainController", "Add version"))
            msgBox.addButton(cancelBtn, QMessageBox.RejectRole)
            msgBox.addButton(rebuildBtn, QMessageBox.AcceptRole)
            msgBox.addButton(addBtn, QMessageBox.AcceptRole)
            msgBox.exec_()
            if msgBox.clickedButton() == cancelBtn:
                return 0
            elif msgBox.clickedButton() == rebuildBtn:
                return 1
            else:
                return 2

        elif typ == oPB.MsgEnum.MS_QUEST_OKCANCEL:
            retval = QMessageBox.question(parent, translate("mainController", "Question"), msgtext, QMessageBox.Ok, QMessageBox.Cancel)
            if retval == QMessageBox.Cancel:
                return False
            else:
                return True

        elif typ == oPB.MsgEnum.MS_QUEST_PHRASE:
            text = QInputDialog.getText(parent, translate("mainController", "Additional information"),
                                          msgtext, QLineEdit.Normal,"")
            return text
コード例 #46
0
def changelog_footer() ->str:
    """
    Generate footer for standard changelog entries.

    :return: footer sring
    """
    return "\n\n" + " -- " + ConfigHandler.cfg.packagemaintainer + " <" + ConfigHandler.cfg.mailaddress + ">  " + Helper.timestamp_changelog() + "\n"
コード例 #47
0
    def save_data(self):
        """Save control file data of current project"""
        controlfile = self._projectfolder + "/OPSI/control"

        if Path(controlfile).exists():
            try:
                shutil.move(controlfile, controlfile + "-" + Helper.timestamp() + ".bak")

            except IOError:
                self.logger.error("Existing control file could not be renamed")
                self.logger.debug("Emit dataLoaded(False)")
                self.dataSaved.emit(False)
                return

        try:
            with open(self._projectfolder + "/OPSI/control", "x", encoding="utf-8", newline="\n") as file:
                self.logger.debug("Control file opened: " + self._projectfolder + "/OPSI/control")

                file.write("[Package]\n")
                file.write("version: " + self.packageversion + "\n")
                file.write("depends: " + self.depends + "\n")
                file.write("incremental: " + self.incremental + "\n\n")
                file.write("[Product]\n")
                file.write("type: " + self.type + "\n")
                file.write("id: " + self.id + "\n")
                file.write("name: " + self.name + "\n")
                file.write("description: " + self.description.strip() + "\n")
                file.write("advice: " + self.advice + "\n")
                file.write("version: " + self.productversion + "\n")
                file.write("priority: " + str(self.priority) + "\n")
                file.write("licenseRequired: " + self.licenseRequired + "\n")
                file.write("productClasses: " + self.productClasses + "\n")
                file.write("setupScript: " + self.setupScript + "\n")
                file.write("uninstallScript: " + self.uninstallScript + "\n")
                file.write("updateScript: " + self.updateScript + "\n")
                file.write("alwaysScript: " + self.alwaysScript + "\n")
                file.write("onceScript: " + self.onceScript + "\n")
                file.write("customScript: " + self.customScript + "\n")
                file.write("userLoginScript: " + self.userLoginScript + "\n")

                if self.dependencies:
                    for elem in self.dependencies:
                        file.write("\n")
                        file.write("[ProductDependency]\n")
                        file.write("action: " + elem[0] + "\n")
                        file.write("requiredProduct: " + elem[1] + "\n")
                        if elem[2] not in ["", "none"]:
                            file.write("requiredAction: " + elem[2] + "\n")
                        else:
                            file.write("requiredStatus: " + elem[3] + "\n")
                        file.write("requirementType: " + elem[4] + "\n")

                if self.properties:
                    for elem in self.properties:
                        file.write("\n")
                        file.write("[ProductProperty]\n")
                        file.write("type: " + elem[1] + "\n")
                        file.write("name: " + elem[0] + "\n")
                        if elem[1] == "unicode":
                            file.write("multivalue: " + elem[2] + "\n")
                            file.write("editable: " + elem[3] + "\n")
                        file.write("description: " + elem[4] + "\n")
                        if elem[1] == "unicode":
                            v = json.dumps(elem[5], ensure_ascii=False)
                            d = json.dumps(elem[6], ensure_ascii=False)
                            if v == '""':  # empty string returned by json.dumps
                                file.write("values: \n")
                            else:
                                file.write("values: " + v + "\n")
                            if d == '""':  # empty string returned by json.dumps
                                file.write("default: \n")
                            else:
                                file.write("default: " + d + "\n")
                        else:
                            file.write("default: " + elem[6] + "\n")

                file.write("\n")
                file.write("[Changelog]\n")
                file.write(self.changelog)

                file.close()
                self.logger.debug("Emit dataSaved(True)")
                self.dataSaved.emit(True)  # on success

        except:
            self.logger.error("Error writing control file")
            self.logger.exception("Error writing control file")
            self.logger.debug("Emit dataSaved(False)")
            self.dataSaved.emit(False)
コード例 #48
0
ファイル: main.py プロジェクト: boagoa/opsiPackageBuilder
    def project_copy(self, project_folder):
        """
        Copies current project data to new project destination

        :param destination: destination for copied project
        """

        dest_data = ""
        val = 0

        def sizeof_fmt(num, suffix='B'):
            for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']:
                if abs(num) < 1024.0:
                    return "%3.1f%s%s" % (num, unit, suffix)
                num /= 1024.0
            return "%.1f%s%s" % (num, 'Yi', suffix)

        def copy2_(src, dst):
            self.logger.debug("Copying to destination file: " + str(dst))
            self.msgbox("CLIENT_DATA: " + str(dst).replace(dest_data, ""),
                        oPB.MsgEnum.MS_STAT)
            self.progressChanged.emit(val)
            shutil.copy2(src, dst)

        def countFiles(directory):
            files = []
            total_size = 0
            if os.path.isdir(directory):
                for path, dirs, filenames in os.walk(directory):
                    files.extend(filenames)
                    for f in filenames:
                        fp = os.path.join(path, f)
                        total_size += os.path.getsize(fp)

            return len(files), total_size

        def copyDirectory(src, dest):
            self.logger.info("Copying files")
            self.logger.debug("Source: " + src)
            self.logger.debug("Destination:" + dest)
            if os.path.exists(dest):
                shutil.rmtree(dest)
            try:
                shutil.copytree(src, dest, copy_function=copy2_)
            # Directories are the same
            except shutil.Error as e:
                self.logger.error('Directory not copied. Error: %s' % e)
            # Any error saying that the directory doesn't exist
            except OSError as e:
                self.logger.error('Directory not copied. Error: %s' % e)

        self.logger.info("Create new project from current: " + project_folder)

        # create new control object as copy

        if os.path.exists(
                Helper.concat_path_native(project_folder, "CLIENT_DATA")):
            self.logger.error(
                "CLIENT_DATA subdirectory in destination folder detected. This is not allowed for security reason!"
            )
            self.msgbox(
                translate(
                    "mainController",
                    "CLIENT_DATA subdirectory in destination folder detected. This is not allowed for security reason!"
                ), oPB.MsgEnum.MS_ERR)
            return

        newControl = deepcopy(self.controlData)
        self.create_project_paths(project_folder)
        project_name = PurePath(project_folder).name.replace(" ", "_")
        newControl.id = project_name
        newControl.projectfolder = project_folder

        # add changelog entry for this copy process
        text = "Project copied from: " + self.controlData.packagename
        newentry = ChangelogEntry(newControl.id)
        newentry.version = "(" + newControl.productversion + "-" + newControl.packageversion + ")"
        newentry.status = oPB.CHLOG_STATI[0]
        newentry.urgency = oPB.CHLOG_BLOCKMARKER + oPB.CHLOG_URGENCIES[0]
        newentry.text = "\n" + text + changelog_footer()
        newControl.changelog_append(newentry)

        try:
            self.processingStarted.emit()

            newControl.save_data()
            self.logger.debug("New control data saved.")

            dest_data = Helper.concat_path_native(newControl.projectfolder,
                                                  "CLIENT_DATA")
            total, total_size = countFiles(
                Helper.concat_path_native(self.controlData.projectfolder,
                                          "CLIENT_DATA"))
            val = 100 / total

            reply = self.msgbox(
                translate("mainController",
                          "Copy files now? This can't be canceled.") +
                "\n\nTotal: " + str(total) + "\n" + sizeof_fmt(total_size),
                oPB.MsgEnum.MS_QUEST_YESNO)
            if reply is True:
                copyDirectory(
                    Helper.concat_path_native(self.controlData.projectfolder,
                                              "CLIENT_DATA"),
                    Helper.concat_path_native(newControl.projectfolder,
                                              "CLIENT_DATA"))
                self.logger.debug("Files copied.")

            self.processingEnded.emit(True)

            # close current project an re-open clone
            if not self.project_close():
                return

            self.project_load(project_name)
        except:
            self.logger.error("Project could not be copied and re-opened.")
コード例 #49
0
ファイル: main.py プロジェクト: boagoa/opsiPackageBuilder
    def msgbox(self,
               msgtext="",
               typ=oPB.MsgEnum.MS_STAT,
               parent=None,
               preload=""):
        """ Messagebox function

        Valid values for typ:
            * oPB.MsgEnum.MS_ERR -> Error message (status bar/ popup)
            * oPB.MsgEnum.MS_WARN -> Warning (status bar/ popup)
            * oPB.MsgEnum.MS_INFO -> Information (status bar/ popup)
            * oPB.MsgEnum.MS_STAT -> Information (only status bar)
            * oPB.MsgEnum.MS_ALWAYS -> Display this message ALWAYS, regardless of which message **typ** is deactivated via settings
            * oPB.MsgEnum.MS_PARSE -> just parse message text and return it
            * oPB.MsgEnum.MS_QUEST_YESNO
            * oPB.MsgEnum.MS_QUEST_CTC
            * oPB.MsgEnum.MS_QUEST_OKCANCEL
            * oPB.MsgEnum.MS_QUEST_PHRASE
            * oPB.MsgEnum.MS_QUEST_PASS
            * oPB.MsgEnum.MS_QUEST_DEPOT

        :param msgtext: Message text
        :param typ: type of message window, see oPB.core enums
        :param parent: parent ui of message box
        :param preload: pre-fill input boxes with this text
        """
        if parent is None:
            parent = self.ui

        # first parse text, is argument is str
        if type(msgtext) is str:
            msgtext = Helper.parse_text(msgtext)

        if typ == oPB.MsgEnum.MS_ERR:
            self.msgSend.emit(msgtext)
            if ConfigHandler.cfg.no_error_msg == "False":
                QMessageBox.critical(parent,
                                     translate("mainController", "Error"),
                                     msgtext, QMessageBox.Ok)

        elif typ == oPB.MsgEnum.MS_WARN:
            self.msgSend.emit(msgtext)
            if ConfigHandler.cfg.no_warning_msg == "False":
                QMessageBox.warning(parent,
                                    translate("mainController", "Warning"),
                                    msgtext, QMessageBox.Ok)

        elif typ == oPB.MsgEnum.MS_INFO:
            self.msgSend.emit(msgtext)
            if ConfigHandler.cfg.no_info_msg == "False":
                QMessageBox.information(parent,
                                        translate("mainController", "Message"),
                                        msgtext, QMessageBox.Ok)

        elif typ == oPB.MsgEnum.MS_STAT:
            self.msgSend.emit(msgtext)

        elif typ == oPB.MsgEnum.MS_ALWAYS:
            QMessageBox.information(parent,
                                    translate("mainController", "Message"),
                                    msgtext, QMessageBox.Ok)

        elif typ == oPB.MsgEnum.MS_PARSE:
            return msgtext

        elif typ == oPB.MsgEnum.MS_QUEST_YESNO:
            retval = QMessageBox.question(
                parent, translate("mainController", "Question"), msgtext,
                QMessageBox.Yes, QMessageBox.No)
            if retval == QMessageBox.No:
                return False
            else:
                return True

        elif typ == oPB.MsgEnum.MS_QUEST_CTC:
            msgBox = QMessageBox(parent)
            msgBox.setWindowTitle(translate("mainController", "Question"))
            msgBox.setText(msgtext)
            msgBox.setIcon(QMessageBox.Question)
            cancelBtn = QPushButton(translate("mainController", "Cancel"))
            rebuildBtn = QPushButton(translate("mainController", "Rebuild"))
            addBtn = QPushButton(translate("mainController", "Add version"))
            msgBox.addButton(cancelBtn, QMessageBox.RejectRole)
            msgBox.addButton(rebuildBtn, QMessageBox.AcceptRole)
            msgBox.addButton(addBtn, QMessageBox.AcceptRole)
            msgBox.exec_()
            if msgBox.clickedButton() == cancelBtn:
                return 0
            elif msgBox.clickedButton() == rebuildBtn:
                return 1
            else:
                return 2

        elif typ == oPB.MsgEnum.MS_QUEST_OKCANCEL:
            retval = QMessageBox.question(
                parent, translate("mainController", "Question"), msgtext,
                QMessageBox.Ok, QMessageBox.Cancel)
            if retval == QMessageBox.Cancel:
                return False
            else:
                return True

        elif typ == oPB.MsgEnum.MS_QUEST_PHRASE:
            text = QInputDialog.getText(
                parent, translate("mainController", "Additional information"),
                msgtext, QLineEdit.Normal, preload)
            return text

        elif typ == oPB.MsgEnum.MS_QUEST_PASS:
            text = QInputDialog.getText(
                parent, translate("mainController", "Additional information"),
                msgtext, QLineEdit.Password, preload)
            return text

        elif typ == oPB.MsgEnum.MS_QUEST_DEPOT:
            preselectlist = [
                i for i, j in enumerate(msgtext)
                if ConfigHandler.cfg.opsi_server in j
            ]
            if preselectlist:
                preselect = preselectlist[0]
            else:
                preselect = -1
            item = QInputDialog.getItem(
                parent, translate("mainController", "Question"),
                translate("mainController", "Select which depot to use:"),
                msgtext, preselect, False)
            return item

        elif typ == oPB.MsgEnum.MS_ABOUTQT:
            QMessageBox.aboutQt(parent, translate("mainController",
                                                  "About Qt"))
コード例 #50
0
    def _processAction(self, cmd, action, retval):
        self.logger.sshinfo("Processing action...")
        # ------------------------------------------------------------------------------------------------------------------------
        if self.ret == oPB.RET_OK:

            # hook into stderr for progress analysing
            old_stderr = sys.stderr
            s = AnalyseProgressHook(self, old_stderr)
            # sys.stdout = s

            try:
                with self.shell:
                    try:
                        self.logger.sshinfo("Trying to execute command: " + self._obscurepass(cmd))

                        if action in [oPB.OpEnum.DO_INSTALL, oPB.OpEnum.DO_QUICKINST, oPB.OpEnum.DO_INSTSETUP,
                                      oPB.OpEnum.DO_UPLOAD, oPB.OpEnum.DO_UNINSTALL, oPB.OpEnum.DO_QUICKUNINST]:
                            result = self.shell.run(cmd.split(),
                                cwd = self.control.path_on_server,
                                update_env = self._env,
                                allow_error = True,
                                stderr = s,
                                use_pty = True
                            )
                        else:
                            result = self.shell.run(cmd.split(),
                                cwd = self.control.path_on_server,
                                update_env = self._env,
                                allow_error = True,
                                stderr = s
                            )

                        # Log standard out
                        out = Helper.strip_ansi_codes(result.output.decode(encoding='UTF-8')).splitlines()
                        for line in out:
                            line = self._obscurepass(line)
                            self.logger.ssh(line)


                        # Log standard error
                        out = Helper.strip_ansi_codes(result.stderr_output.decode(encoding='UTF-8')).splitlines()
                        for line in out:
                            line = self._obscurepass(line)
                            self.logger.sshinfo(line)
                            isErr = self.hasErrors(line)
                            if isErr[0]:
                                self.ret = retval
                                self.rettype = oPB.MsgEnum.MS_ERR
                                self.retmsg = isErr[1]

                    except spur.NoSuchCommandError:
                        self.logger.error("Set return code to RET_SSHCMDERR")
                        self.ret = oPB.RET_SSHCMDERR
                        self.rettype = oPB.MsgEnum.MS_ERR
                        self.retmsg = translate("OpsiProcessing", "Command not found. See Log for details.")

            except ConnectionError as error:
                    self.logger.error(repr(error).replace("\\n"," --> "))
                    self.logger.error("Set return code to RET_SSHCONNERR")
                    self.ret = oPB.RET_SSHCONNERR
                    self.rettype = oPB.MsgEnum.MS_ERR
                    self.retmsg = translate("OpsiProcessing", "Error establishing SSH connection. See Log for details.")

            # reset hook state
            #sys.stdout = old_stderr

            return result.output.decode(encoding='UTF-8')
        else:
            return {}