[03/29] ui/ncurses: Add status log UI
diff mbox

Message ID 20161219041915.30497-4-sam@mendozajonas.com
State Accepted
Headers show

Commit Message

Samuel Mendoza-Jonas Dec. 19, 2016, 4:18 a.m. UTC
From: Jeremy Kerr <jk@ozlabs.org>

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    |   5 +-
 ui/ncurses/nc-cui-help.c  |   2 +
 ui/ncurses/nc-cui.c       |  39 +++++++++++++---
 ui/ncurses/nc-cui.h       |   3 ++
 ui/ncurses/nc-menu.c      |   3 ++
 ui/ncurses/nc-statuslog.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++
 ui/ncurses/nc-statuslog.h |  35 ++++++++++++++
 7 files changed, 193 insertions(+), 7 deletions(-)
 create mode 100644 ui/ncurses/nc-statuslog.c
 create mode 100644 ui/ncurses/nc-statuslog.h

Patch
diff mbox

diff --git a/ui/ncurses/Makefile.am b/ui/ncurses/Makefile.am
index 265ae69..feec51d 100644
--- a/ui/ncurses/Makefile.am
+++ b/ui/ncurses/Makefile.am
@@ -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
 
diff --git a/ui/ncurses/nc-cui-help.c b/ui/ncurses/nc-cui-help.c
index 0482830..7d97ba5 100644
--- a/ui/ncurses/nc-cui-help.c
+++ b/ui/ncurses/nc-cui-help.c
@@ -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\
diff --git a/ui/ncurses/nc-cui.c b/ui/ncurses/nc-cui.c
index a6537cb..86515bc 100644
--- a/ui/ncurses/nc-cui.c
+++ b/ui/ncurses/nc-cui.c
@@ -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);
 
diff --git a/ui/ncurses/nc-cui.h b/ui/ncurses/nc-cui.h
index b00d251..418df71 100644
--- a/ui/ncurses/nc-cui.h
+++ b/ui/ncurses/nc-cui.h
@@ -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,
diff --git a/ui/ncurses/nc-menu.c b/ui/ncurses/nc-menu.c
index 723d348..90a2c0a 100644
--- a/ui/ncurses/nc-menu.c
+++ b/ui/ncurses/nc-menu.c
@@ -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
index 0000000..1943f39
--- /dev/null
+++ b/ui/ncurses/nc-statuslog.c
@@ -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
index 0000000..e29980e
--- /dev/null
+++ b/ui/ncurses/nc-statuslog.h
@@ -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 */