ui/ncurses: Add status log UI
authorJeremy Kerr <jk@ozlabs.org>
Tue, 6 Dec 2016 06:23:28 +0000 (17:23 +1100)
committerSamuel Mendoza-Jonas <sam@mendozajonas.com>
Tue, 20 Dec 2016 04:04:21 +0000 (15:04 +1100)
Currently, status messages from the server are displayed in a single
line at the bottom of the main menu UI, and are lost once a new status
is reported.

This change adds a facility for the UI to collect and display the status
messages from the server, in a dedicated UI screen. This allows a user
to look back through the discovery & boot process.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
ui/ncurses/Makefile.am
ui/ncurses/nc-cui-help.c
ui/ncurses/nc-cui.c
ui/ncurses/nc-cui.h
ui/ncurses/nc-menu.c
ui/ncurses/nc-statuslog.c [new file with mode: 0644]
ui/ncurses/nc-statuslog.h [new file with mode: 0644]

index 265ae6960b8dce15c501b941e9c3cfc3867de844..feec51d3cb92dddb05a764554f78bb6576472362 100644 (file)
@@ -49,7 +49,10 @@ ui_ncurses_libpbnc_la_SOURCES = \
        ui/ncurses/nc-add-url.h \
        ui/ncurses/nc-add-url-help.c \
        ui/ncurses/nc-subset.c \
-       ui/ncurses/nc-subset.h
+       ui/ncurses/nc-subset.h \
+       ui/ncurses/nc-statuslog.c \
+       ui/ncurses/nc-statuslog.h
+
 
 sbin_PROGRAMS += ui/ncurses/petitboot-nc
 
index 0482830138c6f8bdbbc87f4792920ae8167d5cc2..7d97ba5db6779d11bacab2ec960f8c065e9d02ea 100644 (file)
@@ -18,6 +18,8 @@ To make changes to the system configuration, type C (configure).\n\
 \n\
 To set the language for the petitboot interface, type L (language).\n\
 \n\
+To view the log of status messages from the discovery process, type G (log).\n\
+\n\
 To find new or updated boot options on the system, select the 'Rescan devices' \
 option.\n\
 \n\
index a6537cb46b2b9e46a353d383e6c7ec8c5fad4c39..86515bc7f987e1ba1bd9310d6dc7a2d71dffdfce 100644 (file)
@@ -42,6 +42,7 @@
 #include "nc-sysinfo.h"
 #include "nc-lang.h"
 #include "nc-helpscreen.h"
+#include "nc-statuslog.h"
 #include "nc-subset.h"
 
 extern const struct help_text main_menu_help_text;
@@ -335,6 +336,19 @@ void cui_show_lang(struct cui *cui)
        cui_set_current(cui, lang_screen_scr(cui->lang_screen));
 }
 
+static void cui_statuslog_exit(struct cui *cui)
+{
+       cui_set_current(cui, &cui->main->scr);
+       talloc_free(cui->statuslog_screen);
+       cui->statuslog_screen = NULL;
+}
+
+void cui_show_statuslog(struct cui *cui)
+{
+       cui->statuslog_screen = statuslog_screen_init(cui, cui_statuslog_exit);
+       cui_set_current(cui, statuslog_screen_scr(cui->statuslog_screen));
+}
+
 static void cui_add_url_exit(struct cui *cui)
 {
        cui_set_current(cui, &cui->main->scr);
@@ -698,6 +712,8 @@ static void cui_update_status(struct status *status, void *arg)
 {
        struct cui *cui = cui_from_arg(arg);
 
+       statuslog_append_steal(cui, cui->statuslog, status);
+
        nc_scr_status_printf(cui->current,
                        "%s: %s",
                        status->type == STATUS_ERROR ?
@@ -825,6 +841,12 @@ static int menu_lang_execute(struct pmenu_item *item)
        return 0;
 }
 
+static int menu_statuslog_execute(struct pmenu_item *item)
+{
+       cui_show_statuslog(cui_from_item(item));
+       return 0;
+}
+
 static int menu_reinit_execute(struct pmenu_item *item)
 {
        if (cui_from_item(item)->client)
@@ -849,7 +871,7 @@ static struct pmenu *main_menu_init(struct cui *cui)
        int result;
        bool lockdown = lockdown_active();
 
-       m = pmenu_init(cui, 7, cui_on_exit);
+       m = pmenu_init(cui, 8, cui_on_exit);
        if (!m) {
                pb_log("%s: failed\n", __func__);
                return NULL;
@@ -861,7 +883,7 @@ static struct pmenu *main_menu_init(struct cui *cui)
                "Petitboot (" PACKAGE_VERSION ")");
        m->scr.frame.rtitle = NULL;
        m->scr.frame.help = talloc_strdup(m,
-               _("Enter=accept, e=edit, n=new, x=exit, l=language, h=help"));
+               _("Enter=accept, e=edit, n=new, x=exit, l=language, g=log, h=help"));
        m->scr.frame.status = talloc_strdup(m, _("Welcome to Petitboot"));
 
        /* add a separator */
@@ -878,25 +900,29 @@ static struct pmenu *main_menu_init(struct cui *cui)
        i->on_execute = menu_config_execute;
        pmenu_item_insert(m, i, 2);
 
+       i = pmenu_item_create(m, _("System status log"));
+       i->on_execute = menu_statuslog_execute;
+       pmenu_item_insert(m, i, 3);
+
        /* this label isn't translated, so we don't want a gettext() here */
        i = pmenu_item_create(m, "Language");
        i->on_execute = menu_lang_execute;
-       pmenu_item_insert(m, i, 3);
+       pmenu_item_insert(m, i, 4);
 
        i = pmenu_item_create(m, _("Rescan devices"));
        i->on_execute = menu_reinit_execute;
-       pmenu_item_insert(m, i, 4);
+       pmenu_item_insert(m, i, 5);
 
        i = pmenu_item_create(m, _("Retrieve config from URL"));
        i->on_execute = menu_add_url_execute;
-       pmenu_item_insert(m, i, 5);
+       pmenu_item_insert(m, i, 6);
 
        if (lockdown)
                i = pmenu_item_create(m, _("Reboot"));
        else
                i = pmenu_item_create(m, _("Exit to shell"));
        i->on_execute = pmenu_exit_cb;
-       pmenu_item_insert(m, i, 6);
+       pmenu_item_insert(m, i, 7);
 
        result = pmenu_setup(m);
 
@@ -1023,6 +1049,7 @@ struct cui *cui_init(void* platform_info,
        cui->c_sig = pb_cui_sig;
        cui->platform_info = platform_info;
        cui->waitset = waitset_create(cui);
+       cui->statuslog = statuslog_init(cui);
 
        process_init(cui, cui->waitset, false);
 
index b00d251e12d0652dee340ab2ecd04e7e227d0b5e..418df711204ea3f95ea176ba4b8f71c6263bc8cd 100644 (file)
@@ -56,6 +56,7 @@ struct cui {
        struct waitset *waitset;
        struct discover_client *client;
        struct system_info *sysinfo;
+       struct statuslog *statuslog;
        struct sysinfo_screen *sysinfo_screen;
        struct config *config;
        struct config_screen *config_screen;
@@ -64,6 +65,7 @@ struct cui {
        struct lang_screen *lang_screen;
        struct help_screen *help_screen;
        struct subset_screen *subset_screen;
+       struct statuslog_screen *statuslog_screen;
        struct pjs *pjs;
        void *platform_info;
        unsigned int default_item;
@@ -80,6 +82,7 @@ void cui_item_new(struct pmenu *menu);
 void cui_show_sysinfo(struct cui *cui);
 void cui_show_config(struct cui *cui);
 void cui_show_lang(struct cui *cui);
+void cui_show_statuslog(struct cui *cui);
 void cui_show_help(struct cui *cui, const char *title,
                const struct help_text *text);
 void cui_show_subset(struct cui *cui, const char *title,
index 723d3489f2a4a521175e3009aee696ebec8b8973..90a2c0a996c6b9704653657f8a291fc1d2709892 100644 (file)
@@ -418,6 +418,9 @@ static void pmenu_process_key(struct nc_scr *scr, int key)
        case 'l':
                cui_show_lang(cui_from_arg(scr->ui_ctx));
                break;
+       case 'g':
+               cui_show_statuslog(cui_from_arg(scr->ui_ctx));
+               break;
        case KEY_F(1):
        case 'h':
                if (menu->help_text)
diff --git a/ui/ncurses/nc-statuslog.c b/ui/ncurses/nc-statuslog.c
new file mode 100644 (file)
index 0000000..1943f39
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ *  Copyright (C) 2016 IBM Corporation
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include <talloc/talloc.h>
+#include <types/types.h>
+#include <log/log.h>
+#include <util/util.h>
+#include <i18n/i18n.h>
+
+#include "nc-cui.h"
+#include "nc-textscreen.h"
+#include "nc-statuslog.h"
+
+static const int max_status_entry = 10000;
+
+struct statuslog_entry {
+       struct status           *status;
+       struct list_item        list;
+};
+
+struct statuslog {
+       struct list             status;
+       int                     n_status;
+       bool                    truncated;
+};
+
+struct statuslog_screen {
+       struct text_screen text_scr;
+};
+
+struct statuslog *statuslog_init(struct cui *cui)
+{
+       struct statuslog *sl;
+
+       sl = talloc(cui, struct statuslog);
+       sl->truncated = false;
+       sl->n_status = 0;
+       list_init(&sl->status);
+
+       return sl;
+}
+
+void statuslog_append_steal(struct cui *cui, struct statuslog *statuslog,
+               struct status *status)
+{
+       struct statuslog_entry *entry;
+
+       entry = talloc(statuslog, struct statuslog_entry);
+       entry->status = status;
+       talloc_steal(statuslog, status);
+
+       list_add_tail(&statuslog->status, &entry->list);
+
+       if (statuslog->n_status >= max_status_entry) {
+               list_remove(&statuslog->status.head);
+               statuslog->truncated = true;
+               statuslog->n_status--;
+       }
+
+       statuslog->n_status++;
+
+       if (cui->statuslog_screen) {
+               text_screen_append_line(&cui->statuslog_screen->text_scr,
+                               "%s", status->message);
+               text_screen_draw(&cui->statuslog_screen->text_scr);
+       }
+}
+
+struct statuslog_screen *statuslog_screen_init(struct cui *cui,
+               void (*on_exit)(struct cui *))
+{
+       struct statuslog_screen *screen;
+       struct statuslog_entry *entry;
+       const char *title;
+
+       screen = talloc_zero(cui, struct statuslog_screen);
+
+       title = _("Petitboot status log");
+
+       text_screen_init(&screen->text_scr, cui, title, on_exit);
+       list_for_each_entry(&cui->statuslog->status, entry, list) {
+               text_screen_append_line(&screen->text_scr, "%s",
+                               entry->status->message);
+       }
+       text_screen_draw(&screen->text_scr);
+
+       return screen;
+}
+
+struct nc_scr *statuslog_screen_scr(struct statuslog_screen *screen)
+{
+       return text_screen_scr(&screen->text_scr);
+}
diff --git a/ui/ncurses/nc-statuslog.h b/ui/ncurses/nc-statuslog.h
new file mode 100644 (file)
index 0000000..e29980e
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  Copyright (C) 2016 IBM Corporation
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _NC_STATUSLOG_H
+#define _NC_STATUSLOG_H
+
+#include "nc-cui.h"
+
+struct statuslog;
+struct statuslog_screen;
+
+struct statuslog *statuslog_init(struct cui *cui);
+void statuslog_append_steal(struct cui *cui, struct statuslog *statuslog,
+               struct status *status);
+
+struct statuslog_screen *statuslog_screen_init(struct cui *cui,
+               void (*on_exit)(struct cui *));
+
+struct nc_scr *statuslog_screen_scr(struct statuslog_screen *screen);
+
+#endif /* defined _NC_STATUSLOG_H */