예제 #1
0
class CreateDatabaseStep(BaseWizardStep):
    gladefile = 'CreateDatabaseStep'

    def post_init(self):
        self.n_patches = 0
        self.process_view = ProcessView()
        self.process_view.listen_stderr = True
        self.process_view.connect('read-line', self._on_processview__readline)
        self.process_view.connect('finished', self._on_processview__finished)
        self.expander.add(self.process_view)
        self.expander.grab_focus()
        self._maybe_create_database()

    def next_step(self):
        return LinkStep(self.wizard, self)

    def _maybe_create_database(self):
        logger.info('_maybe_create_database (db_is_local=%s, enable_production=%s)'
                    % (self.wizard.db_is_local, self.wizard.enable_production))
        if self.wizard.db_is_local:
            self._launch_stoqdbadmin()
            return
        elif self.wizard.enable_production:
            self._launch_stoqdbadmin()
            return

        self.wizard.write_pgpass()
        settings = self.wizard.settings
        self.wizard.config.load_settings(settings)

        store = settings.create_super_store()
        version = get_database_version(store)

        if version < (9, 1):
            store.close()
            error(_("Stoq requires PostgresSQL 9.1 or later, but %s found") % (
                ".".join(map(str, version))))

        try:
            check_extensions(store=store)
        except ValueError:
            store.close()
            error(_("Missing PostgreSQL extension on the server, "
                    "please install postgresql-contrib on it"))

        store.close()

        # Secondly, ask the user if he really wants to create the database,
        dbname = settings.dbname
        if yesno(_(u"The specified database '%s' does not exist.\n"
                   u"Do you want to create it?") % dbname,
                 gtk.RESPONSE_YES, _(u"Create database"), _(u"Don't create")):
            self.process_view.feed("** Creating database\r\n")
            self._launch_stoqdbadmin()
        else:
            self.process_view.feed("** Not creating database\r\n")
            self.wizard.disable_next()

    def _launch_stoqdbadmin(self):
        logger.info('_launch_stoqdbadmin')
        self.wizard.disable_back()
        self.wizard.disable_next()

        if sys.argv[0].endswith('.egg'):
            args = [sys.executable, sys.argv[0]]
        elif platform.system() == 'Windows':
            if library.uninstalled:
                args = ['stoq.bat']
            else:
                args = ['stoq.exe']
        else:
            args = ['stoq']

        args.extend([
            'dbadmin', 'init',
            '--no-load-config', '--no-register-station', '-v'])

        if self.wizard.create_examples:
            args.append('--demo')
        elif self.wizard.enable_production:
            args.append('--force')

        if self.wizard.plugins:
            args.append('--enable-plugins')
            args.append(','.join(self.wizard.plugins))
        if self.wizard.db_is_local:
            args.append('--create-dbuser')

        dbargs = self.wizard.settings.get_command_line_arguments()
        args.extend(dbargs)
        self.label.set_label(
            _("Creating a new database for Stoq, depending on the speed of "
              "your computer and the server it may take a couple of "
              "minutes to finish."))
        self.progressbar.set_text(_("Creating database..."))
        self.progressbar.set_fraction(0.05)
        logger.info(' '.join(args))
        self.process_view.execute_command(args)
        self.done_label.set_markup(
            _("Please wait while the database is being created."))

    def _parse_process_line(self, line):
        LOG_CATEGORY = 'stoqlib.database.create'
        log_pos = line.find(LOG_CATEGORY)
        if log_pos == -1:
            return
        line = line[log_pos + len(LOG_CATEGORY) + 1:]
        if line == 'SCHEMA':
            value = 0.1
            text = _("Creating base schema...")
        elif line.startswith('PATCHES:'):
            value = 0.35
            self.n_patches = int(line.split(':', 1)[1])
            text = _("Creating schema, applying patches...")
        elif line.startswith('PATCH:'):
            # 0.4 - 0.7 patches
            patch = float(line.split(':', 1)[1])
            value = 0.4 + (patch / self.n_patches) * 0.3
            text = _("Creating schema, applying patch %d ...") % (patch + 1, )
        elif line == 'INIT START':
            text = _("Creating additional database objects ...")
            value = 0.8
        elif line == 'INIT DONE' and self.wizard.create_examples:
            text = _("Creating examples ...")
            value = 0.85
        elif line.startswith('PLUGIN'):
            text = _("Activating plugins ...")
            if 'nfe' in self.wizard.plugins:
                text += ' ' + _('This may take some time.')
            value = 0.95
        else:
            return
        self.progressbar.set_fraction(value)
        self.progressbar.set_text(text)

    def _finish(self, returncode):
        logger.info('CreateDatabaseStep._finish (returncode=%s)' % returncode)
        if returncode:
            self.wizard.enable_back()
            # Failed to execute/create database
            if returncode == 30:
                # This probably happened because the user either;
                # - pressed cancel in the authentication popup
                # - user erred the password 3 times
                # Allow him to try again
                if yesno(_("Something went wrong while trying to create "
                           "the database. Try again?"),
                         gtk.RESPONSE_NO, _("Change settings"), _("Try again")):
                    return
                self._launch_stoqdbadmin()
                return
            elif returncode == 31:
                # Missing postgresql-contrib package
                self.expander.set_expanded(True)
                warning(_("Your database is missing the postgresql-contrib "
                          "package. Install it and try again"))
            else:
                # Unknown error, just inform user that something went wrong.
                self.expander.set_expanded(True)
                warning(_("Something went wrong while trying to create "
                          "the Stoq database"))
            return
        self.label.set_text("")
        self.wizard.load_config_and_call_setup()
        create_default_profile_settings()
        self.progressbar.set_text(_("Done."))
        self.progressbar.set_fraction(1.0)
        self.wizard.enable_next()
        self.done_label.set_markup(
            _("Installation successful, click <b>Forward</b> to continue."))

    # Callbacks

    def _on_processview__readline(self, view, line):
        self._parse_process_line(line)

    def _on_processview__finished(self, view, returncode):
        self._finish(returncode)
예제 #2
0
class CreateDatabaseStep(BaseWizardStep):
    gladefile = 'CreateDatabaseStep'

    def post_init(self):
        self.n_patches = 0
        self.process_view = ProcessView()
        self.process_view.listen_stderr = True
        self.process_view.connect('read-line', self._on_processview__readline)
        self.process_view.connect('finished', self._on_processview__finished)
        self.expander.add(self.process_view)
        self.expander.grab_focus()
        self._maybe_create_database()

    def next_step(self):
        return FinishInstallationStep(self.wizard)

    def _maybe_create_database(self):
        logger.info('_maybe_create_database (db_is_local=%s, remove_demo=%s)' %
                    (self.wizard.db_is_local, self.wizard.remove_demo))
        if self.wizard.db_is_local:
            self._launch_stoqdbadmin()
            return
        elif self.wizard.remove_demo:
            self._launch_stoqdbadmin()
            return

        self.wizard.write_pgpass()
        settings = self.wizard.settings
        self.wizard.config.load_settings(settings)

        # store = settings.get_super_store()
        # version = store.dbVersion()
        # if version < (8, 1):
        #     info(_("Stoq requires PostgresSQL 8.1 or later, but %s found") %
        #          ".".join(map(str, version)))
        #     store.close()
        #     return False

        # Secondly, ask the user if he really wants to create the database,
        dbname = settings.dbname
        if yesno(
                _(u"The specified database '%s' does not exist.\n"
                  u"Do you want to create it?") % dbname, gtk.RESPONSE_YES,
                _(u"Create database"), _(u"Don't create")):
            self.process_view.feed("** Creating database\r\n")
            self._launch_stoqdbadmin()
        else:
            self.process_view.feed("** Not creating database\r\n")
            self.wizard.disable_next()

    def _launch_stoqdbadmin(self):
        logger.info('_launch_stoqdbadmin')
        self.wizard.disable_back()
        self.wizard.disable_next()
        stoqdbadmin = 'stoqdbadmin'
        if platform.system() == 'Windows':
            if library.uninstalled:
                stoqdbadmin += '.bat'
            else:
                stoqdbadmin += '.exe'
            # FIXME: listen to file input for
            #        APPDATA/stoqdbadmin/stderr.log + stdout.log
        args = [
            stoqdbadmin, 'init', '--no-load-config', '--no-register-station',
            '-v'
        ]
        if self.wizard.enable_production and not self.wizard.remove_demo:
            args.append('--demo')
        if self.wizard.plugins:
            args.append('--enable-plugins')
            args.append(','.join(self.wizard.plugins))
        if self.wizard.db_is_local:
            args.append('--create-dbuser')

        dbargs = self.wizard.settings.get_command_line_arguments()
        args.extend(dbargs)
        self.label.set_label(
            _("Creating a new database for Stoq, depending on the speed of "
              "your computer and the server it may take a couple of "
              "minutes to finish."))
        self.progressbar.set_text(_("Creating database..."))
        self.progressbar.set_fraction(0.05)
        logger.info(' '.join(args))
        self.process_view.execute_command(args)
        self.done_label.set_markup(
            _("Please wait while the database is being created."))

    def _parse_process_line(self, line):
        LOG_CATEGORY = 'stoqlib.database.create'
        log_pos = line.find(LOG_CATEGORY)
        if log_pos == -1:
            return
        line = line[log_pos + len(LOG_CATEGORY) + 1:]
        if line == 'SCHEMA':
            value = 0.1
            text = _("Creating base schema...")
        elif line.startswith('PATCHES:'):
            value = 0.35
            self.n_patches = int(line.split(':', 1)[1])
            text = _("Creating schema, applying patches...")
        elif line.startswith('PATCH:'):
            # 0.4 - 0.7 patches
            patch = float(line.split(':', 1)[1])
            value = 0.4 + (patch / self.n_patches) * 0.3
            text = _("Creating schema, applying patch %d ...") % (patch + 1, )
        elif line == 'INIT START':
            text = _("Creating additional database objects ...")
            value = 0.8
        elif line == 'INIT DONE' and self.wizard.enable_production:
            text = _("Creating examples ...")
            value = 0.85
        elif line.startswith('PLUGIN'):
            text = _("Activating plugins ...")
            if 'nfe' in self.wizard.plugins:
                text += ' ' + _('This may take some time.')
            value = 0.95
        else:
            return
        self.progressbar.set_fraction(value)
        self.progressbar.set_text(text)

    def _finish(self, returncode):
        logger.info('CreateDatabaseStep._finish (returncode=%s)' % returncode)
        if returncode:
            self.wizard.enable_back()
            # Failed to execute/create database
            if returncode == 30:
                # This probably happened because the user either;
                # - pressed cancel in the authentication popup
                # - user erred the password 3 times
                # Allow him to try again
                if yesno(
                        _("Something went wrong while trying to create "
                          "the database. Try again?"), gtk.RESPONSE_NO,
                        _("Change settings"), _("Try again")):
                    return
                self._launch_stoqdbadmin()
                return
            else:
                # Unknown error, just inform user that something went wrong.
                self.expander.set_expanded(True)
                warning(
                    _("Something went wrong while trying to create "
                      "the Stoq database"))
            return
        self.label.set_text("")
        self.wizard.load_config_and_call_setup()
        create_default_profile_settings()
        ensure_admin_user(self.wizard.config.get_password())
        self.progressbar.set_text(_("Done."))
        self.progressbar.set_fraction(1.0)
        self.wizard.enable_next()
        self.done_label.set_markup(
            _("Installation successful, click <b>Forward</b> to continue."))

    # Callbacks

    def _on_processview__readline(self, view, line):
        self._parse_process_line(line)

    def _on_processview__finished(self, view, returncode):
        self._finish(returncode)
예제 #3
0
class UpdateSchemaStep(BaseWizardStep):
    gladefile = 'UpdateSchemaStep'

    #
    # WizardStep
    #

    def post_init(self):
        self._finished = False
        self.process_view = ProcessView()
        self.process_view.listen_stderr = True
        self.process_view.connect('read-line', self._on_processview__readline)
        self.process_view.connect('finished', self._on_processview__finished)
        self.expander.add(self.process_view)
        self._launch_stoqdbadmin()
        glib.timeout_add(50, self._on_timeout_add)

    def has_next_step(self):
        return False

    # Private

    def _parse_process_line(self, line):
        # Errors and other messages thrown by stoqdbadmin are not displayed in
        # this wizard. Using info here instead of error, so that the user can
        # still se the log.
        if line.startswith('ERROR:'):
            msg = line[7:]
            info(msg)

        LOG_CATEGORY = 'stoqlib.database.create'
        log_pos = line.find(LOG_CATEGORY)
        if log_pos == -1:
            return
        line = line[log_pos + len(LOG_CATEGORY) + 1:]
        longer = None
        if line.startswith('PATCH:'):
            patch = line.split(':', 1)[1]
            text = _("Applying patch %s ...") % (patch, )
        elif line.startswith('BACKUP-START:'):
            text = _("Creating a database backup")
            longer = _(
                'Creating a database backup in case anything goes wrong.')
        elif line.startswith('RESTORE-START:'):
            text = _("Restoring database backup")
            longer = _('Stoq update failed.\n\n'
                       'We will try to restore the current database.\n\n'
                       'This may take some time.')
        elif line.startswith('RESTORE-DONE:'):
            msg = line.split(':', 1)[1]
            text = _("Database backup restored")
            longer = _(
                'Stoq database update failed but the database was restored.\n'
                'An automatic crash report was submitted. Please, '
                'enter in contact at <b>[email protected]</b> for '
                'assistance in recovering your database and making it '
                'possible to use Stoq %s again.\n\n'
                'A backup database was created as <b>%s</b>') % (
                    stoq.version,
                    msg,
                )
        else:
            return
        self.progressbar.set_text(text)
        if not longer:
            longer = ''
        self.label.set_markup(longer)

    def _launch_stoqdbadmin(self):
        self.wizard.disable_next()
        if sys.argv[0].endswith('.egg'):
            args = [sys.executable, sys.argv[0]]
        elif platform.system() == 'Windows':
            if library.uninstalled:
                args = ['stoq.bat']
            else:
                args = ['stoq.exe']
        else:
            args = ['stoq']

        args.extend(['dbadmin', 'updateschema', '-v'])
        args.extend(api.db_settings.get_command_line_arguments())
        self.process_view.execute_command(args)
        self.progressbar.set_text(_('Applying database patches...'))

    def _finish(self, returncode):
        self._finished = True
        if returncode:
            self.wizard.cancel_button.set_label(gtk.STOCK_QUIT)
            self.progressbar.set_fraction(0.0)
        else:
            # Migration may have changed some parameters, so clear the cache.
            api.sysparam.clear_cache()
            self.wizard.cancel_button.set_sensitive(True)
            self.progressbar.set_text(_("Done. Click 'Forward' to continue"))
            self.progressbar.set_fraction(1.0)
            self.wizard.enable_next()
            self.wizard.next_button.grab_focus()

    # Callbacks

    def _on_processview__readline(self, view, line):
        self._parse_process_line(line)

    def _on_processview__finished(self, view, returncode):
        self._finish(returncode)

    def _on_timeout_add(self):
        if self._finished:
            return False
        self.progressbar.pulse()
        return True
예제 #4
0
파일: update.py 프로젝트: Joaldino/stoq
class UpdateSchemaStep(BaseWizardStep):
    gladefile = 'UpdateSchemaStep'

    #
    # WizardStep
    #

    def post_init(self):
        self._finished = False
        self.process_view = ProcessView()
        self.process_view.listen_stderr = True
        self.process_view.connect('read-line', self._on_processview__readline)
        self.process_view.connect('finished', self._on_processview__finished)
        self.expander.add(self.process_view)
        self._launch_stoqdbadmin()
        glib.timeout_add(50, self._on_timeout_add)

    def has_next_step(self):
        return False

    # Private

    def _parse_process_line(self, line):
        # Errors and other messages thrown by stoqdbadmin are not displayed in
        # this wizard. Using info here instead of error, so that the user can
        # still se the log.
        if line.startswith('ERROR:'):
            msg = line[7:]
            info(msg)

        LOG_CATEGORY = 'stoqlib.database.create'
        log_pos = line.find(LOG_CATEGORY)
        if log_pos == -1:
            return
        line = line[log_pos + len(LOG_CATEGORY) + 1:]
        longer = None
        if line.startswith('PATCH:'):
            patch = line.split(':', 1)[1]
            text = _("Applying patch %s ...") % (patch, )
        elif line.startswith('BACKUP-START:'):
            text = _("Creating a database backup")
            longer = _('Creating a database backup in case anything goes wrong.')
        elif line.startswith('RESTORE-START:'):
            text = _("Restoring database backup")
            longer = _(
                'Stoq update failed.\n\n'
                'We will try to restore the current database.\n\n'
                'This may take some time.')
        elif line.startswith('RESTORE-DONE:'):
            msg = line.split(':', 1)[1]
            text = _("Database backup restored")
            longer = _(
                'Stoq database update failed but the database was restored.\n'
                'An automatic crash report was submitted. Please, '
                'enter in contact at <b>[email protected]</b> for '
                'assistance in recovering your database and making it '
                'possible to use Stoq %s again.\n\n'
                'A backup database was created as <b>%s</b>') % (
                stoq.version, msg, )
        else:
            return
        self.progressbar.set_text(text)
        if not longer:
            longer = ''
        self.label.set_markup(longer)

    def _launch_stoqdbadmin(self):
        self.wizard.disable_next()
        args = ['stoqdbadmin', 'updateschema', '-v']
        args.extend(api.db_settings.get_command_line_arguments())
        self.process_view.execute_command(args)
        self.progressbar.set_text(_('Applying database patches...'))

    def _finish(self, returncode):
        self._finished = True
        if returncode:
            self.wizard.cancel_button.set_label(gtk.STOCK_QUIT)
            self.progressbar.set_fraction(0.0)
        else:
            # Migration may have changed some parameters, so clear the cache.
            api.sysparam.clear_cache()
            self.wizard.cancel_button.set_sensitive(True)
            self.progressbar.set_text(_("Done. Click 'Forward' to continue"))
            self.progressbar.set_fraction(1.0)
            self.wizard.enable_next()
            self.wizard.next_button.grab_focus()

    # Callbacks

    def _on_processview__readline(self, view, line):
        self._parse_process_line(line)

    def _on_processview__finished(self, view, returncode):
        self._finish(returncode)

    def _on_timeout_add(self):
        if self._finished:
            return False
        self.progressbar.pulse()
        return True
예제 #5
0
파일: update.py 프로젝트: stoq/stoq
class UpdateSchemaStep(BaseWizardStep):
    gladefile = "UpdateSchemaStep"

    #
    # WizardStep
    #

    def post_init(self):
        self._finished = False
        self.process_view = ProcessView()
        self.process_view.listen_stderr = True
        self.process_view.connect("read-line", self._on_processview__readline)
        self.process_view.connect("finished", self._on_processview__finished)
        self.expander.add(self.process_view)
        self._launch_stoqdbadmin()
        glib.timeout_add(50, self._on_timeout_add)

    def has_next_step(self):
        return False

    # Private

    def _parse_process_line(self, line):
        # Errors and other messages thrown by stoqdbadmin are not displayed in
        # this wizard. Using info here instead of error, so that the user can
        # still se the log.
        if line.startswith("ERROR:"):
            msg = line[7:]
            info(msg)

        LOG_CATEGORY = "stoqlib.database.create"
        log_pos = line.find(LOG_CATEGORY)
        if log_pos == -1:
            return
        line = line[log_pos + len(LOG_CATEGORY) + 1 :]
        longer = None
        if line.startswith("PATCH:"):
            patch = line.split(":", 1)[1]
            text = _("Applying patch %s ...") % (patch,)
        elif line.startswith("BACKUP-START:"):
            text = _("Creating a database backup")
            longer = _("Creating a database backup in case anything goes wrong.")
        elif line.startswith("RESTORE-START:"):
            text = _("Restoring database backup")
            longer = _(
                "Stoq update failed.\n\n" "We will try to restore the current database.\n\n" "This may take some time."
            )
        elif line.startswith("RESTORE-DONE:"):
            msg = line.split(":", 1)[1]
            text = _("Database backup restored")
            longer = _(
                "Stoq database update failed but the database was restored.\n"
                "An automatic crash report was submitted. Please, "
                "enter in contact at <b>[email protected]</b> for "
                "assistance in recovering your database and making it "
                "possible to use Stoq %s again.\n\n"
                "A backup database was created as <b>%s</b>"
            ) % (stoq.version, msg)
        else:
            return
        self.progressbar.set_text(text)
        if not longer:
            longer = ""
        self.label.set_markup(longer)

    def _launch_stoqdbadmin(self):
        self.wizard.disable_next()
        if sys.argv[0].endswith(".egg"):
            args = [sys.executable, sys.argv[0]]
        elif platform.system() == "Windows":
            if library.uninstalled:
                args = ["stoq.bat"]
            else:
                # We should use stoq-cmd here, but the output is breaking
                # the process view
                args = ["stoq.exe"]
        else:
            args = ["stoq"]

        args.extend(["dbadmin", "updateschema", "-v"])
        args.extend(api.db_settings.get_command_line_arguments())
        self.process_view.execute_command(args)
        self.progressbar.set_text(_("Applying database patches..."))

    def _finish(self, returncode):
        self._finished = True
        if returncode:
            self.wizard.cancel_button.set_label(gtk.STOCK_QUIT)
            self.progressbar.set_fraction(0.0)
        else:
            # Migration may have changed some parameters, so clear the cache.
            api.sysparam.clear_cache()
            self.wizard.cancel_button.set_sensitive(True)
            self.progressbar.set_text(_("Done. Click 'Forward' to continue"))
            self.progressbar.set_fraction(1.0)
            self.wizard.enable_next()
            self.wizard.next_button.grab_focus()

    # Callbacks

    def _on_processview__readline(self, view, line):
        self._parse_process_line(line)

    def _on_processview__finished(self, view, returncode):
        self._finish(returncode)

    def _on_timeout_add(self):
        if self._finished:
            return False
        self.progressbar.pulse()
        return True
예제 #6
0
class ProgressbarDialog(BasicDialog):
    """Dialogs showing progress of a ProcessView should inherit from this.
    """
    #: Default size for this dialog.
    size = (400, 300)

    #: Title for the window.
    title = None

    #: Default process and arguments to run.
    args = []

    #: Default output of the process running.
    log_category = None

    #: Message that will appear on the progressbar before the process is
    #: started.
    start_msg = _(u'Running task...')

    #: Message that will appear when process succeeds.
    success_msg = _(u'Task ran successfully!')

    #: Message that will appear then the process fails.
    failure_msg = _(u'Task failed!')

    def __init__(self,
                 title=None,
                 args=None,
                 log_category=None,
                 start_msg=None,
                 success_msg=None,
                 failure_msg=None):
        """:param title: The title of the window.
        :param args: Default process and arguments to run.
        :param log_category: Default process and arguments to run.
        :param start_msg: Message that will appear on the progressbar before
        the process is started.
        :param success_msg: Message that will appear when process succeeds.
        :param failure_msg: Message that will appear then the process fails.
        """
        self.title = title or self.title
        if not self.title:
            raise ValueError('You must define a title for the window.')

        self.args = args or self.args
        if not self.args:
            raise ValueError('You must define the process and arguments for '
                             'the process.')

        self.log_category = log_category or self.log_category
        if not self.log_category:
            raise ValueError('You must define a log category to read the '
                             'output of the process from.')

        self.start_msg = start_msg or self.start_msg
        self.success_msg = success_msg or self.success_msg
        self.failure_msg = failure_msg or self.failure_msg

        BasicDialog.__init__(self, size=self.size, title=self.title)

        self._build_ui()
        self._execute()

    def _build_ui(self):
        self.main_label.set_text(self.start_msg)
        self.set_ok_label(_("Done"))

        self.progressbar = gtk.ProgressBar()
        self.vbox.pack_start(self.progressbar, False, False)
        self.progressbar.show()

        self.expander = gtk.Expander(label=_("Details..."))
        self.expander.set_expanded(False)
        self.vbox.pack_start(self.expander, True, True)
        self.expander.show()
        self.vbox.set_child_packing(self.main, False, False, 0, 0)

        self.process_view = ProcessView()
        self.process_view.listen_stdout = False
        self.process_view.listen_stderr = True
        self.expander.add(self.process_view)
        self.process_view.show()

        self.disable_ok()

    def _execute(self):
        self.args.extend(api.db_settings.get_command_line_arguments())
        self.process_view.execute_command(self.args)

    def _parse_process_line(self, line):
        log_pos = line.find(self.log_category)
        if log_pos == -1:
            return
        line = line[log_pos + len(self.log_category) + 1:]

        value, text = self.process_line(line)

        if value and text:
            self.progressbar.set_fraction(value)
            self.progressbar.set_text(text)

    def _finish(self, returncode):
        if returncode:
            self.expander.set_expanded(True)
            warning(self.failure_msg)
            return
        self.progressbar.set_text(self.success_msg)
        self.progressbar.set_fraction(1)
        self.enable_ok()

    #
    #   Public API
    #

    def process_line(self, line):
        """This method will be called once for each line of the process output,
        and must return a tuple containing the percentage and message that will
        be displayed in the progress bar.

        :param line: The line that must be processed.
        :returns: A tuple, in which in the first value is the percentage that
          will be displayed in the progressbar (0 <= value <= 1) and the text
          that will be displayed in it.
        """
        raise NotImplementedError("Can't define how to parse the output. You "
                                  "must implement process_line.")

    #
    #   Callbacks
    #

    def on_process_view__read_line(self, view, line):
        self._parse_process_line(line)

    def on_process_view__finished(self, view, returncode):
        self._finish(returncode)
예제 #7
0
파일: config.py 프로젝트: 5l1v3r1/stoq-1
class CreateDatabaseStep(BaseWizardStep):
    gladefile = 'CreateDatabaseStep'

    def post_init(self):
        self.n_patches = 0
        self.process_view = ProcessView()
        self.process_view.listen_stderr = True
        self.process_view.connect('read-line', self._on_processview__readline)
        self.process_view.connect('finished', self._on_processview__finished)
        self.expander.add(self.process_view)
        self.expander.grab_focus()
        self._maybe_create_database()

    def next_step(self):
        return LinkStep(self.wizard, self)

    def _maybe_create_database(self):
        logger.info(
            '_maybe_create_database (db_is_local=%s, enable_production=%s)' %
            (self.wizard.db_is_local, self.wizard.enable_production))
        if self.wizard.db_is_local:
            self._launch_stoqdbadmin()
            return
        elif self.wizard.enable_production:
            self._launch_stoqdbadmin()
            return

        self.wizard.write_pgpass()
        settings = self.wizard.settings
        self.wizard.config.load_settings(settings)

        store = settings.create_super_store()
        version = get_database_version(store)

        if version < (9, 1):
            store.close()
            error(
                _("Stoq requires PostgresSQL 9.1 or later, but %s found") %
                (".".join(map(str, version))))

        try:
            check_extensions(store=store)
        except ValueError:
            store.close()
            error(
                _("Missing PostgreSQL extension on the server, "
                  "please install postgresql-contrib on it"))

        store.close()
        self.process_view.feed("** Creating database\r\n")
        self._launch_stoqdbadmin()

    def _launch_stoqdbadmin(self):
        logger.info('_launch_stoqdbadmin')
        self.wizard.disable_back()
        self.wizard.disable_next()

        if sys.argv[0].endswith('.egg'):
            args = [sys.executable, sys.argv[0]]
        elif platform.system() == 'Windows':
            if library.uninstalled:
                args = ['stoq.bat']
            else:
                args = ['stoq-cmd.exe']
        else:
            args = ['stoq']

        args.extend([
            'dbadmin', 'init', '--no-load-config', '--no-register-station',
            '-v'
        ])

        if self.wizard.create_examples:
            args.append('--demo')
        elif self.wizard.enable_production:
            args.append('--force')

        if self.wizard.db_is_local:
            args.append('--create-dbuser')

        dbargs = self.wizard.settings.get_command_line_arguments()
        args.extend(dbargs)
        self.label.set_label(
            _("Creating a new database for Stoq, depending on the speed of "
              "your computer and the server it may take a couple of "
              "minutes to finish."))
        self.progressbar.set_text(_("Creating database..."))
        self.progressbar.set_fraction(0.05)
        logger.info(' '.join(args))
        self.process_view.execute_command(args)
        self.done_label.set_markup(
            _("Please wait while the database is being created."))

    def _parse_process_line(self, line):
        LOG_CATEGORY = 'stoqlib.database.create'
        log_pos = line.find(LOG_CATEGORY)
        if log_pos == -1:
            return
        line = line[log_pos + len(LOG_CATEGORY) + 1:]
        if line == 'SCHEMA':
            value = 0.1
            text = _("Creating base schema...")
        elif line.startswith('PATCHES:'):
            value = 0.35
            self.n_patches = int(line.split(':', 1)[1])
            text = _("Creating schema, applying patches...")
        elif line.startswith('PATCH:'):
            # 0.4 - 0.7 patches
            patch = float(line.split(':', 1)[1])
            value = 0.4 + (patch / self.n_patches) * 0.3
            text = _("Creating schema, applying patch %d ...") % (patch + 1, )
        elif line == 'INIT START':
            text = _("Creating additional database objects ...")
            value = 0.8
        elif line == 'INIT DONE' and self.wizard.create_examples:
            text = _("Creating examples ...")
            value = 0.85
        elif line.startswith('PLUGIN'):
            text = _("Activating plugins ...")
            if 'nfe' in self.wizard.plugins:
                text += ' ' + _('This may take some time.')
            value = 0.95
        else:
            return
        self.progressbar.set_fraction(value)
        self.progressbar.set_text(text)

    def _finish(self, returncode):
        logger.info('CreateDatabaseStep._finish (returncode=%s)' % returncode)
        if returncode:
            self.wizard.enable_back()
            # Failed to execute/create database
            if returncode == 30:
                # This probably happened because the user either;
                # - pressed cancel in the authentication popup
                # - user erred the password 3 times
                # Allow him to try again
                if yesno(
                        _("Something went wrong while trying to create "
                          "the database. Try again?"), Gtk.ResponseType.NO,
                        _("Change settings"), _("Try again")):
                    return
                self._launch_stoqdbadmin()
                return
            elif returncode == 31:
                # Missing postgresql-contrib package
                self.expander.set_expanded(True)
                warning(
                    _("Your database is missing the postgresql-contrib "
                      "package. Install it and try again"))
            else:
                # Unknown error, just inform user that something went wrong.
                self.expander.set_expanded(True)
                warning(
                    _("Something went wrong while trying to create "
                      "the Stoq database"))
            return
        self.label.set_text("")
        self.wizard.load_config_and_call_setup()
        create_default_profile_settings()
        self.progressbar.set_text(_("Done."))
        self.progressbar.set_fraction(1.0)
        self.wizard.enable_next()
        self.done_label.set_markup(
            _("Installation successful, click <b>Forward</b> to continue."))

    # Callbacks

    def _on_processview__readline(self, view, line):
        self._parse_process_line(line)

    def _on_processview__finished(self, view, returncode):
        self._finish(returncode)
예제 #8
0
class ProgressbarDialog(BasicDialog):
    """Dialogs showing progress of a ProcessView should inherit from this.
    """
    #: Default size for this dialog.
    size = (400, 300)

    #: Title for the window.
    title = None

    #: Default process and arguments to run.
    args = []

    #: Default output of the process running.
    log_category = None

    #: Message that will appear on the progressbar before the process is
    #: started.
    start_msg = _(u'Running task...')

    #: Message that will appear when process succeeds.
    success_msg = _(u'Task ran successfully!')

    #: Message that will appear then the process fails.
    failure_msg = _(u'Task failed!')

    def __init__(self, title=None, args=None, log_category=None,
                 start_msg=None, success_msg=None, failure_msg=None):
        """:param title: The title of the window.
        :param args: Default process and arguments to run.
        :param log_category: Default process and arguments to run.
        :param start_msg: Message that will appear on the progressbar before
        the process is started.
        :param success_msg: Message that will appear when process succeeds.
        :param failure_msg: Message that will appear then the process fails.
        """
        self.title = title or self.title
        if not self.title:
            raise ValueError('You must define a title for the window.')

        self.args = args or self.args
        if not self.args:
            raise ValueError('You must define the process and arguments for '
                             'the process.')

        self.log_category = log_category or self.log_category
        if not self.log_category:
            raise ValueError('You must define a log category to read the '
                             'output of the process from.')

        self.start_msg = start_msg or self.start_msg
        self.success_msg = success_msg or self.success_msg
        self.failure_msg = failure_msg or self.failure_msg

        BasicDialog.__init__(self, size=self.size, title=self.title)

        self._build_ui()
        self._execute()

    def _build_ui(self):
        self.main_label.set_text(self.start_msg)
        self.set_ok_label(_("Done"))

        self.progressbar = gtk.ProgressBar()
        self.vbox.pack_start(self.progressbar, False, False)
        self.progressbar.show()

        self.expander = gtk.Expander(label=_("Details..."))
        self.expander.set_expanded(False)
        self.vbox.pack_start(self.expander, True, True)
        self.expander.show()
        self.vbox.set_child_packing(self.main, False, False, 0, 0)

        self.process_view = ProcessView()
        self.process_view.listen_stdout = False
        self.process_view.listen_stderr = True
        self.expander.add(self.process_view)
        self.process_view.show()

        self.disable_ok()

    def _execute(self):
        self.args.extend(api.db_settings.get_command_line_arguments())
        self.process_view.execute_command(self.args)

    def _parse_process_line(self, line):
        log_pos = line.find(self.log_category)
        if log_pos == -1:
            return
        line = line[log_pos + len(self.log_category) + 1:]

        value, text = self.process_line(line)

        if value and text:
            self.progressbar.set_fraction(value)
            self.progressbar.set_text(text)

    def _finish(self, returncode):
        if returncode:
            self.expander.set_expanded(True)
            warning(self.failure_msg)
            return
        self.progressbar.set_text(self.success_msg)
        self.progressbar.set_fraction(1)
        self.enable_ok()

    #
    #   Public API
    #

    def process_line(self, line):
        """This method will be called once for each line of the process output,
        and must return a tuple containing the percentage and message that will
        be displayed in the progress bar.

        :param line: The line that must be processed.
        :returns: A tuple, in which in the first value is the percentage that
          will be displayed in the progressbar (0 <= value <= 1) and the text
          that will be displayed in it.
        """
        raise NotImplementedError("Can't define how to parse the output. You "
                                  "must implement process_line.")

    #
    #   Callbacks
    #

    def on_process_view__read_line(self, view, line):
        self._parse_process_line(line)

    def on_process_view__finished(self, view, returncode):
        self._finish(returncode)