예제 #1
0
    def __safe_call__(self):
        box = CTK.Box()
        box += CTK.RawHTML('<h2>%s</h2>' % (_("Nagios start up")))

        system_info = SystemInfo.get_info()
        OS = system_info.get('system', '').lower()

        root = CTK.cfg.get_val('%s!root' % (PRE))
        startup = CTK.cfg.get_val('%s!nagiosstartup' % (PRE))
        plist = os.path.join(root, 'nrpe.plist')

        # Register service: init.d, launchd, etc.
        ret = services.register_service('nagios', macos_plist=plist)
        if ret['retcode'] == 0:
            # Launch
            if startup:
                if OS == 'darwin':
                    services.launch_service('org.nagios.nrpe')
                else:
                    services.launch_service('nagios')

            box += CTK.RawHTML(
                js=CTK.DruidContent__JS_to_goto(box.id, URL_SERVER_CONFIG))
            return box.Render().toStr()

        # Error handling
        notice = CTK.Notice()
        notice += CTK.RawHTML('<p>%s</p>' % (_(
            'The installer could not successfully execute the following command:'
        )))
        notice += CTK.RawHTML('<pre>%s</pre>' % (ret['command']))
        notice += CTK.RawHTML('<p>%s</p>' % (_('The reported error was:')))
        notice += CTK.RawHTML('<pre>%s</pre>' % (ret['stderr']))

        box += CTK.RawHTML('<p>%s</p>' % (ret['error']))
        box += notice
        box += CTK.RawHTML('<p>%s</p>' % (_(
            'You can either manually fix the problem and retry, or you can skip the step knowing that the Nagios system service will not be launched at boot time.'
        )))

        buttons = CTK.DruidButtonsPanel()
        buttons += CTK.DruidButton_Close(_('Cancel'))
        buttons += CTK.DruidButton_Goto(_('Retry'),
                                        URL_LAUNCH_SERVICE,
                                        do_submit=True)
        buttons += CTK.DruidButton_Goto(_('Skip'),
                                        URL_SERVER_CONFIG,
                                        do_submit=True)
        box += buttons

        return box.Render().toStr()
    def __safe_call__(self):
        box = CTK.Box()
        box += CTK.RawHTML('<h2>%s</h2>' % (_("Checking Dependencies")))

        error_cc = tools.check_cc()
        error_py = python.detect_python("2.5.0", or_greater=True)
        error_xml = tools.check_xml2config()

        if error_cc:
            note, inst = error_cc
        elif error_py:
            note, inst = error_py
        elif error_xml:
            note, inst = error_xml
        else:
            box += CTK.RawHTML(
                js=CTK.DruidContent__JS_to_goto(box.id, URL_TARGET))
            return box.Render().toStr()

        box += market.Util.InstructionBox(_(note), inst)
        buttons = CTK.DruidButtonsPanel()
        buttons += CTK.DruidButton_Close(_('Cancel'))
        buttons += CTK.DruidButton_Goto(_('Retry'),
                                        URL_PRECONDITION,
                                        do_submit=True)
        return box.Render().toStr()
예제 #3
0
    def __safe_call__(self):
        box = CTK.Box()
        box += CTK.RawHTML('<h2>%s</h2>' % (_("Checking Requirements")))

        buttons = CTK.DruidButtonsPanel()
        buttons += CTK.DruidButton_Close(_('Cancel'))
        buttons += CTK.DruidButton_Goto(_('Retry'),
                                        URL_PRECONDITION,
                                        do_submit=True)

        # CC
        if not cc.detect_cc():
            box += InstructionBox(_(cc.NOTE), cc.CC_INSTRUCTIONS)
            box += buttons
            return box.Render().toStr()

        # Database
        supported_dbs = database.get_supported_dbs(DB_SUPPORTED)
        if not supported_dbs:
            box += database.PreconditionError(DB_SUPPORTED)
            box += buttons
            return box.Render().toStr()

        box += CTK.RawHTML(js=CTK.DruidContent__JS_to_goto(box.id, URL_TARGET))
        return box.Render().toStr()
    def __safe_call__(self):
        box = CTK.Box()
        box += CTK.RawHTML('<h2>%s</h2>' % (_('Access details')))
        box += CTK.RawHTML('<p>%s</p>' % (_(
            'Nuxeo-DAM has been installed, and Cherokee is configured to automatically launch it whenever the resource is accessed if it is not already available. A one-time pre-launch has been issued to save time.'
        )))
        box += CTK.RawHTML('<p>%s</p>' % (_(
            'Note that launching Nuxeo-DAM can take up a couple of  minutes on modern servers, so please be patient the first time you access it.'
        )))
        box += CTK.RawHTML('<p>%s</p>' % (_(
            'It is probably a good idea to pre-launch it instead of having the web-server do so on demand.'
        )))
        box += CTK.RawHTML('<p>%s</p>' %
                           (_('These are the default access details:')))

        notice = CTK.Notice()
        notice += CTK.RawHTML('<b>%s:</b>' % (_('Username')))
        notice += CTK.Indenter(CTK.RawHTML('Administrator'))
        notice += CTK.RawHTML('<b>%s:</b>' % (_('Password')))
        notice += CTK.Indenter(CTK.RawHTML('Administrator'))
        box += notice

        buttons = CTK.DruidButtonsPanel()
        buttons += CTK.DruidButton_Goto(_('Next'),
                                        market.Install.URL_INSTALL_DONE,
                                        do_submit=True)
        box += buttons

        return box.Render().toStr()
예제 #5
0
    def __safe_call__(self):
        box = CTK.Box()
        box += CTK.RawHTML('<h2>%s</h2>' % (_("Checking Dependencies")))

        buttons = CTK.DruidButtonsPanel()
        buttons += CTK.DruidButton_Close(_('Cancel'))
        buttons += CTK.DruidButton_Goto(_('Retry'),
                                        URL_PRECONDITION,
                                        do_submit=True)

        # Check PHP
        php_cgi_bin = php.figure_phpcgi_binary()

        if not php_cgi_bin:
            box += php.PHP_Interpreter_Not_Found_Widget()
            box += buttons
            return box.Render().toStr()

        # Database
        supported_dbs = database.get_supported_dbs(DB_SUPPORTED)
        if not supported_dbs:
            box += database.PreconditionError(DB_SUPPORTED)
            box += buttons
            return box.Render().toStr()

        # PHP modules
        error = tools.check_requirements()
        if error:
            box += InstructionBox(error[0], error[1])
            box += buttons
            return box.Render().toStr()

        box += CTK.RawHTML(js=CTK.DruidContent__JS_to_goto(box.id, URL_TARGET))
        return box.Render().toStr()
예제 #6
0
    def __safe_call__ (self):
        box = CTK.Box()
        box += CTK.RawHTML ('<h2>%s</h2>' %(_("Checking Requirements")))

        buttons = CTK.DruidButtonsPanel()
        buttons += CTK.DruidButton_Close(_('Cancel'))
        buttons += CTK.DruidButton_Goto (_('Retry'), URL_PRECONDITION, do_submit=True)

        # Check PHP
        php_cgi_bin = php.figure_phpcgi_binary()

        if not php_cgi_bin:
            box += php.PHP_Interpreter_Not_Found_Widget()
            box += buttons
            return box.Render().toStr()

        # Check at least one php DB module is available
        db_errors = tools.check_php_database_support()
        if db_errors:
            note, instruction_list = db_errors

            box += market.Util.InstructionBox (note, instruction_list, bin_path=php_cgi_bin)
            box += buttons
            return box.Render().toStr()

        # Database
        supported_dbs = database.get_supported_dbs (DB_SUPPORTED)
        if not supported_dbs:
            box += database.PreconditionError (DB_SUPPORTED)
            box += buttons
            return box.Render().toStr()

        box += CTK.RawHTML (js = CTK.DruidContent__JS_to_goto (box.id, URL_TARGET))
        return box.Render().toStr()
예제 #7
0
    def __safe_call__(self):
        nagiosuser = CTK.cfg.get_val('%s!nagiosuser' % (PRE))
        nagiosgroup = CTK.cfg.get_val('%s!nagiosgroup' % (PRE))
        nagioscmd = CTK.cfg.get_val('%s!nagioscmd' % (PRE))
        root = CTK.cfg.get_val('%s!root' % (PRE))

        box = CTK.Box()
        box += CTK.RawHTML('<h2>%s</h2>' % (_("Checking System Users")))

        # Installation
        ret = tools.create_credentials(nagiosuser, nagiosgroup, nagioscmd,
                                       root)

        if ret.get('ret') == True:
            box += CTK.RawHTML(
                js=CTK.DruidContent__JS_to_goto(box.id, URL_SERVER_BUILD))
            return box.Render().toStr()

        box += CTK.RawHTML('<p>%s</p>' % (ret['error']))
        box += CTK.Notice(content=CTK.RawHTML('<p>%s</p><pre>%s</pre>' % (_(
            'The installer could not successfully execute the following command:'
        ), ret['command'])))
        box += CTK.RawHTML('<p>%s</p><pre>%s</pre>' %
                           (_('The reported error was:'), ret['stderr']))

        buttons = CTK.DruidButtonsPanel()
        buttons += CTK.DruidButton_Close(_('Cancel'))
        buttons += CTK.DruidButton_Goto(_('Retry'),
                                        URL_USER_CREATION,
                                        do_submit=True)
        box += buttons

        return box.Render().toStr()
예제 #8
0
def content():
    box = CTK.Box()

    # Submit 1
    submit = CTK.Submitter ('/submit_ok')
    submit += CTK.TextField ({'name': '1', 'value': '1'})
    box += CTK.RawHTML("<h2>Submit 1</h2>")
    box += submit

    # Submit 2
    submit = CTK.Submitter ('/submit_ok')
    submit += CTK.TextField ({'name': '2', 'value': '2'})
    box += CTK.RawHTML("<h2>Submit 2</h2>")
    box += submit

    # Submit 3
    submit = CTK.Submitter ('/submit_fail')
    submit += CTK.TextField ({'name': '3', 'value': '3'})
    box += CTK.RawHTML("<h2>Submit 3</h2>")
    box += submit

    buttons = CTK.DruidButtonsPanel()
    buttons += CTK.DruidButton_Goto (_('Next'), '/fin', do_submit=True)
    box += buttons

    return box.Render().toStr()
예제 #9
0
    def __safe_call__(self):
        box = CTK.Box()
        box += CTK.RawHTML('<h2>%s</h2>' % (_("Checking Requirements")))

        buttons = CTK.DruidButtonsPanel()
        buttons += CTK.DruidButton_Close(_('Cancel'))
        buttons += CTK.DruidButton_Goto(_('Retry'),
                                        URL_PRECONDITION,
                                        do_submit=True)

        # Check PHP
        php_cgi_bin = php.figure_phpcgi_binary()

        if not php_cgi_bin:
            box += php.PHP_Interpreter_Not_Found_Widget()
            box += buttons
            return box.Render().toStr()

        # Database
        supported_dbs = database.get_supported_dbs(DB_SUPPORTED)
        if not supported_dbs:
            box += database.PreconditionError(DB_SUPPORTED)
            box += buttons
            return box.Render().toStr()

        # Check PHP modules
        error = tools.check_modules()
        if error:
            note, instructions = error
            box += market.Util.InstructionBox(note,
                                              instructions,
                                              bin_path=php_cgi_bin)
            box += buttons
            return box.Render().toStr()

        # Check PHP settings
        setting_errors = tools.check_settings()
        if setting_errors:
            box += CTK.RawHTML('<p>%s</p>' % (_(
                "Some of your PHP settings do not meet Vanilla's requirements. Please edit your PHP configuration files and try again."
            )))
            table = CTK.Table({'class': 'infosection'})
            table.set_header(1)
            table += [
                CTK.RawHTML(x)
                for x in ('%s ' % _('Setting'), '%s ' % _('Expected value'),
                          _('Current value'))
            ]
            for setting_test in setting_errors:
                table += [CTK.RawHTML(str(x)) for x in setting_test]

            box += CTK.Indenter(table)
            box += buttons
            return box.Render().toStr()

        box += CTK.RawHTML(js=CTK.DruidContent__JS_to_goto(box.id, URL_TARGET))
        return box.Render().toStr()
예제 #10
0
    def __init__ (self):
        CTK.Box.__init__ (self)

        self += CTK.RawHTML ('<h1>%s</h1>' %(_("Could not find the PHP interpreter")))
        self += PHP_Interpreter_Not_Found_Widget()

        buttons = CTK.DruidButtonsPanel()
        buttons += CTK.DruidButton_Goto (_('Check Again'), URL_PHP_CONFIG, do_submit=False)
        self += buttons
예제 #11
0
    def __safe_call__(self):
        box = CTK.Box()
        target_wid = target.TargetSelection()
        target_wid.bind(
            'goto_next_stage',
            CTK.DruidContent__JS_to_goto(box.id, php.URL_PHP_CONFIG_INTRO))
        box += target_wid

        buttons = CTK.DruidButtonsPanel()
        buttons += CTK.DruidButton_Close(_('Cancel'))
        buttons += CTK.DruidButton_Goto(_('Next'),
                                        php.URL_PHP_CONFIG_INTRO,
                                        do_submit=True)
        box += buttons

        return box.Render().toStr()
예제 #12
0
    def __safe_call__(self):
        box = CTK.Box()
        box += CTK.RawHTML('<h2>%s</h2>' % (_("Checking Dependencies")))

        if tools.check_cc():
            box += CTK.RawHTML(
                js=CTK.DruidContent__JS_to_goto(box.id, URL_TARGET))
            return box.Render().toStr()

        box += InstructionBox(_(tools.DEP_NOTE), tools.DEP_INSTRUCTIONS)
        buttons = CTK.DruidButtonsPanel()
        buttons += CTK.DruidButton_Close(_('Cancel'))
        buttons += CTK.DruidButton_Goto(_('Retry'),
                                        URL_PRECONDITION,
                                        do_submit=True)
        return box.Render().toStr()
    def __safe_call__(self):
        box = CTK.Box()
        box += CTK.RawHTML('<h1>%s</h1>' %
                           (_("Checking for installation requirements")))

        if java.detect_java('1.6'):
            box += CTK.RawHTML(
                js=CTK.DruidContent__JS_to_goto(box.id, URL_TARGET))
            return box.Render().toStr()

        box += InstructionBox(_(java.JAVA6_NOTE), java.JAVA6_INSTRUCTIONS)
        buttons = CTK.DruidButtonsPanel()
        buttons += CTK.DruidButton_Close(_('Cancel'))
        buttons += CTK.DruidButton_Goto(
            _('Retry'),
            market.Install.URL_INSTALL_SETUP_EXTERNAL,
            do_submit=True)
        return box.Render().toStr()
예제 #14
0
    def __safe_call__(self):
        box = CTK.Box()
        box += CTK.RawHTML('<h2>%s</h2>' % (_("Checking Requirements")))

        buttons = CTK.DruidButtonsPanel()
        buttons += CTK.DruidButton_Close(_('Cancel'))
        buttons += CTK.DruidButton_Goto(
            _('Retry'),
            market.Install.URL_INSTALL_SETUP_EXTERNAL,
            do_submit=True)

        # Ruby
        ruby_bin = ruby.detect_ruby('1.8')
        gem_bin = ruby.detect_gem()

        if not ruby_bin or not gem_bin:
            box += InstructionBox(_(ruby.RUBY18_NOTE),
                                  ruby.RUBY18_INSTRUCTIONS)
            box += buttons
            return box.Render().toStr()

        # CC
        cc_bin = cc.detect_cc(cache=False)
        if not cc_bin:
            box += InstructionBox(_(cc.CC_NOTE), cc.CC_INSTRUCTIONS)
            box += buttons
            return box.Render().toStr()

        # C++
        cpp_bin = cpp.detect_cpp(cache=False)
        if not cpp_bin:
            box += InstructionBox(_(cpp.CPP_NOTE), cpp.CPP_INSTRUCTIONS)
            box += buttons
            return box.Render().toStr()

        # Database
        supported_dbs = database.get_supported_dbs(DB_SUPPORTED)
        if not supported_dbs:
            box += database.PreconditionError(DB_SUPPORTED)
            box += buttons
            return box.Render().toStr()

        box += CTK.RawHTML(js=CTK.DruidContent__JS_to_goto(box.id, URL_TARGET))
        return box.Render().toStr()
예제 #15
0
    def __safe_call__(self):
        notice = CTK.Notice()
        notice += CTK.RawHTML('<p><b>%s:</b> %s</p>' %
                              (_('Username'), 'admin'))
        notice += CTK.RawHTML('<p><b>%s:</b> %s</p>' %
                              (_('Password'), 'admin'))

        buttons = CTK.DruidButtonsPanel()
        buttons += CTK.DruidButton_Close(_('Cancel'))
        buttons += CTK.DruidButton_Goto(_('Next'),
                                        market.Install.URL_INSTALL_DONE,
                                        do_submit=True)

        box = CTK.Box()
        box += CTK.RawHTML('<h2>%s</h2>' % (_(ACCESS_H2)))
        box += CTK.RawHTML('<p>%s</p>' % (_(ACCESS_P1)))
        box += notice
        box += buttons
        return box.Render().toStr()
예제 #16
0
    def __safe_call__(self):
        box = CTK.Box()
        box += CTK.RawHTML('<h2>%s</h2>' % (_("Checking Requirements")))

        buttons = CTK.DruidButtonsPanel()
        buttons += CTK.DruidButton_Close(_('Cancel'))
        buttons += CTK.DruidButton_Goto(
            _('Retry'),
            market.Install.URL_INSTALL_SETUP_EXTERNAL,
            do_submit=True)

        # Check PHP
        php_cgi_bin = php.figure_phpcgi_binary()

        if not php_cgi_bin:
            box += php.PHP_Interpreter_Not_Found_Widget()
            box += buttons
            return box.Render().toStr()

        box += CTK.RawHTML(js=CTK.DruidContent__JS_to_goto(box.id, URL_TARGET))
        return box.Render().toStr()
예제 #17
0
    def __safe_call__(self):
        box = CTK.Box()
        box += CTK.RawHTML('<h2>%s</h2>' % (_("Checking Requirements")))

        buttons = CTK.DruidButtonsPanel()
        buttons += CTK.DruidButton_Close(_('Cancel'))
        buttons += CTK.DruidButton_Goto(
            _('Retry'),
            market.Install.URL_INSTALL_SETUP_EXTERNAL,
            do_submit=True)

        # Check PHP
        php_cgi_bin = php.figure_phpcgi_binary()

        if not php_cgi_bin:
            box += php.PHP_Interpreter_Not_Found_Widget()
            box += buttons
            return box.Render().toStr()

        # Check PHP modules
        error = tools.check_modules()
        if error:
            note, instructions = error
            box += market.Util.InstructionBox(note,
                                              instructions,
                                              bin_path=php_cgi_bin)
            box += buttons
            return box.Render().toStr()

        # Database
        supported_dbs = database.get_supported_dbs(DB_SUPPORTED)
        if not supported_dbs:
            box += database.PreconditionError(DB_SUPPORTED)
            box += buttons
            return box.Render().toStr()

        box += CTK.RawHTML(js=CTK.DruidContent__JS_to_goto(box.id, URL_TARGET))
        return box.Render().toStr()
예제 #18
0
    def __safe_call__(self):
        pre = "tmp!market!install"

        table = CTK.PropsTable()
        table.Add(
            _('Language'),
            CTK.ComboCfg('%s!lang' % (pre), tools.OPTS_LANG, {
                'class': 'noauto',
                'selected': 'en'
            }), _(LANG_NOTE))

        submit = CTK.Submitter(URL_APPLY)
        submit += table

        buttons = CTK.DruidButtonsPanel()
        buttons += CTK.DruidButton_Close(_('Cancel'))
        buttons += CTK.DruidButton_Goto(_('Next'), URL_INSTALL, do_submit=True)

        box = CTK.Box()
        box += CTK.RawHTML('<h2>%s</h2>' % (LANG_H2))
        box += CTK.RawHTML('<p>%s</p>' % (LANG_P1))
        box += submit
        box += buttons
        return box.Render().toStr()
예제 #19
0
    def __safe_call__(self):
        ruby_min = ruby.ruby_version()
        dblist = database.get_supported_dbs(DB_SUPPORTED)
        db_system = [x['db'] for x in dblist]
        db_redmine = DB_SUPPORTED[:]

        box = CTK.Box()
        box += CTK.RawHTML('<h2>%s</h2>' % (_("Database Requirements")))
        message = ''

        if 'mysql' in db_system:
            if version_to_int(ruby_min) < version_to_int('1.8.6'):
                message += '<p>%s</p>' % (_(NOTE_MYSQL1))
                db_redmine.remove('mysql')

            elif not database.mysql_dev_path():  # required by mysql gem:
                message += '<p>%s</p>' % (_(NOTE_MYSQL2))
                db_redmine.remove('mysql')

                box += market.Util.InstructionBox(
                    database.MYSQL_DEV_NOTE, database.MYSQL_DEV_INSTRUCTIONS)

        if 'sqlite3' in db_system:
            if version_to_int(ruby_min) < version_to_int(
                    '1.8.7'):  # required by sqlite3 gem:
                message += '<p>%s</p>' % (_(NOTE_SQLITE))
                db_redmine.remove('sqlite3')

        # No DBS
        if db_redmine == []:
            message += '<p>%s</p>' % (_(NOTE_NODBS))

            buttons = CTK.DruidButtonsPanel()
            buttons += CTK.DruidButton_Close(_('Cancel'))
            buttons += CTK.DruidButton_Goto(_('Retry'),
                                            URL_DATABASE_PRE,
                                            do_submit=True)

            notice = CTK.Notice()
            notice += CTK.RawHTML(message)

            box += notice
            box += buttons

        # Some DBs present on system but not supported for some reason
        elif message:
            buttons = CTK.DruidButtonsPanel()
            buttons += CTK.DruidButton_Close(_('Cancel'))
            buttons += CTK.DruidButton_Goto(_('Next'),
                                            URL_DATABASE,
                                            do_submit=True)

            notice = CTK.Notice()
            notice += CTK.RawHTML(message)

            box += notice
            box += buttons

        # DB list untouched
        else:
            box += CTK.RawHTML(
                js=CTK.DruidContent__JS_to_goto(box.id, URL_DATABASE))

        return box.Render().toStr()
예제 #20
0
    def __call__(self):
        # Check the apps
        orphan = check_orphan_installations()
        unfinished = check_unfinished_installations()

        # Unfinished apps are not even orphans
        for u in unfinished:
            if u in orphan:
                orphan.remove(u)

        # Build list of apps to remove
        remove_apps = {}

        for app in orphan:
            db = app_database_exists(app)
            service = self._figure_app_service(app)

            remove_apps[app] = {}
            remove_apps[app]['type'] = _('Orphan')
            remove_apps[app]['name'] = self._figure_app_name(app)
            remove_apps[app]['date'] = self._figure_app_date(app)
            if db:
                remove_apps[app]['db'] = db
            if service:
                remove_apps[app]['service'] = service

        for app in unfinished:
            if app in remove_apps:
                continue

            db = app_database_exists(app)
            service = self._figure_app_service(app)
            app_fp = os.path.join(CHEROKEE_OWS_ROOT, app)

            remove_apps[app] = {}
            remove_apps[app]['type'] = _('Unfinished')
            remove_apps[app]['name'] = self._figure_app_name(app)
            remove_apps[app]['date'] = self._figure_app_date(app)
            if db:
                remove_apps[app]['db'] = db
            if service:
                remove_apps[app]['service'] = service

            # Even though it's a 'unfinished' app, a virtual server
            # might exist already.
            for v in CTK.cfg['vserver'] or []:
                if CTK.cfg.get_val('vserver!%s!document_root' % (v)) == app_fp:
                    remove_apps[app]['vserver'] = v

        # Store in CTK.cfg
        del (CTK.cfg['tmp!market!maintenance!remove'])
        for app in remove_apps:
            CTK.cfg['tmp!market!maintenance!remove!%s!del' % (app)] = 0
            CTK.cfg['tmp!market!maintenance!remove!%s!name' %
                    (app)] = remove_apps[app]['name']
            CTK.cfg['tmp!market!maintenance!remove!%s!db' %
                    (app)] = remove_apps[app].get('db')
            CTK.cfg['tmp!market!maintenance!remove!%s!service' %
                    (app)] = remove_apps[app].get('service')
            CTK.cfg['tmp!market!maintenance!remove!%s!date' %
                    (app)] = remove_apps[app].get('date')
            CTK.cfg['tmp!market!maintenance!remove!%s!vserver' %
                    (app)] = remove_apps[app].get('vserver')

        # Dialog buttons
        b_next = CTK.DruidButton_Goto(_('Remove'), URL_MAINTENANCE_DB, True)
        b_close = CTK.DruidButton_Close(_('Close'))
        b_cancel = CTK.DruidButton_Close(_('Cancel'))

        buttons = CTK.DruidButtonsPanel()
        buttons += b_close
        buttons += b_cancel
        buttons += b_next

        # App list
        app_list = AppList(remove_apps, b_next, b_cancel, b_close)

        # Content
        cont = CTK.Container()
        cont += CTK.RawHTML('<h2>%s</h2>' %
                            (_("Applications requiring maintenance")))
        cont += CTK.Box({'id': 'maintenance-removal'}, app_list)
        cont += buttons
        cont += CTK.RawHTML(js=b_next.JS_to_hide())
        cont += CTK.RawHTML(js=b_cancel.JS_to_hide())

        submit = CTK.Submitter(URL_MAINTENANCE_LIST_APPLY)
        submit += cont
        return submit.Render().toStr()