X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=systemadm.vala;h=de2fa3ae9c6d1fae988520f5c9bd3cc95c6aef0d;hp=6bcb5f6a8319b705eea649880f1f06964f036c1e;hb=d4e6a6f66b7b3c797a1446816b8512d82c92278f;hpb=77a38d306922b3e980c06a3a377b344ea429edd7 diff --git a/systemadm.vala b/systemadm.vala index 6bcb5f6a8..de2fa3ae9 100644 --- a/systemadm.vala +++ b/systemadm.vala @@ -47,6 +47,13 @@ public class RightLabel : Label { else set_text(text); } + + public void set_markup_or_na(string? text = null) { + if (text == null || text == "") + set_markup("n/a"); + else + set_markup(text); + } } public class MainWindow : Window { @@ -66,6 +73,9 @@ public class MainWindow : Window { private Button reload_button; private Button cancel_button; + private Entry unit_load_entry; + private Button unit_load_button; + private Button server_snapshot_button; private Button server_reload_button; @@ -74,6 +84,7 @@ public class MainWindow : Window { private RightLabel unit_id_label; private RightLabel unit_aliases_label; + private RightLabel unit_dependency_label; private RightLabel unit_description_label; private RightLabel unit_load_state_label; private RightLabel unit_active_state_label; @@ -92,7 +103,7 @@ public class MainWindow : Window { private ComboBox unit_type_combo_box; public MainWindow() throws DBus.Error { - title = "systemdadm"; + title = "systemadm"; position = WindowPosition.CENTER; set_default_size(1000, 700); set_border_width(12); @@ -126,7 +137,19 @@ public class MainWindow : Window { unit_type_combo_box.set_active(1); unit_type_combo_box.changed += unit_type_changed; - server_snapshot_button = new Button.with_mnemonic("Take _Snapshot"); + unit_load_entry = new Entry(); + unit_load_button = new Button.with_mnemonic("_Load"); + unit_load_button.set_sensitive(false); + + unit_load_entry.changed += on_unit_load_entry_changed; + unit_load_entry.activate += on_unit_load; + unit_load_button.clicked += on_unit_load; + + Box unit_load_hbox = new HBox(false, 6); + unit_load_hbox.pack_start(unit_load_entry, false, true, 0); + unit_load_hbox.pack_start(unit_load_button, false, true, 0); + + server_snapshot_button = new Button.with_mnemonic("Take S_napshot"); server_reload_button = new Button.with_mnemonic("Reload _Configuration"); server_snapshot_button.clicked += on_server_snapshot; @@ -134,6 +157,7 @@ public class MainWindow : Window { type_hbox.pack_end(server_snapshot_button, false, true, 0); type_hbox.pack_end(server_reload_button, false, true, 0); + type_hbox.pack_end(unit_load_hbox, false, true, 24); unit_model = new ListStore(7, typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(Unit)); job_model = new ListStore(6, typeof(string), typeof(string), typeof(string), typeof(string), typeof(Job), typeof(uint32)); @@ -173,6 +197,7 @@ public class MainWindow : Window { unit_id_label = new RightLabel(); unit_aliases_label = new RightLabel(); + unit_dependency_label = new RightLabel(); unit_description_label = new RightLabel(); unit_load_state_label = new RightLabel(); unit_active_state_label = new RightLabel(); @@ -188,6 +213,10 @@ public class MainWindow : Window { job_state_label = new RightLabel(); job_type_label = new RightLabel(); + unit_dependency_label.set_track_visited_links(false); + unit_dependency_label.set_selectable(false); + unit_dependency_label.activate_link += on_activate_link; + Table unit_table = new Table(8, 6, false); unit_table.set_row_spacings(6); unit_table.set_border_width(0); @@ -199,32 +228,34 @@ public class MainWindow : Window { job_vbox.pack_start(job_table, false, true, 0); unit_table.attach(new LeftLabel("Id:"), 0, 1, 0, 1, AttachOptions.FILL, AttachOptions.FILL, 0, 0); - unit_table.attach(unit_id_label, 1, 5, 0, 1, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(unit_id_label, 1, 6, 0, 1, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); unit_table.attach(new LeftLabel("Aliases:"), 0, 1, 1, 2, AttachOptions.FILL, AttachOptions.FILL, 0, 0); - unit_table.attach(unit_aliases_label, 1, 5, 1, 2, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(unit_aliases_label, 1, 6, 1, 2, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); unit_table.attach(new LeftLabel("Description:"), 0, 1, 2, 3, AttachOptions.FILL, AttachOptions.FILL, 0, 0); - unit_table.attach(unit_description_label, 1, 5, 2, 3, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); - unit_table.attach(new LeftLabel("Fragment Path:"), 0, 1, 3, 4, AttachOptions.FILL, AttachOptions.FILL, 0, 0); - unit_table.attach(unit_fragment_path_label, 1, 5, 3, 4, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); - unit_table.attach(new LeftLabel("Control Group:"), 0, 1, 4, 5, AttachOptions.FILL, AttachOptions.FILL, 0, 0); - unit_table.attach(unit_cgroup_label, 1, 5, 4, 5, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); - - unit_table.attach(new LeftLabel("Load State:"), 0, 1, 5, 6, AttachOptions.FILL, AttachOptions.FILL, 0, 0); - unit_table.attach(unit_load_state_label, 1, 2, 5, 6, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); - unit_table.attach(new LeftLabel("Active State:"), 0, 1, 6, 7, AttachOptions.FILL, AttachOptions.FILL, 0, 0); - unit_table.attach(unit_active_state_label, 1, 2, 6, 7, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); - unit_table.attach(new LeftLabel("Unit State:"), 0, 1, 7, 8, AttachOptions.FILL, AttachOptions.FILL, 0, 0); - unit_table.attach(unit_sub_state_label, 1, 2, 7, 8, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); - - unit_table.attach(new LeftLabel("Active Enter Timestamp:"), 2, 3, 6, 7, AttachOptions.FILL, AttachOptions.FILL, 0, 0); - unit_table.attach(unit_active_enter_timestamp_label, 3, 4, 6, 7, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); - unit_table.attach(new LeftLabel("Active Exit Timestamp:"), 2, 3, 7, 8, AttachOptions.FILL, AttachOptions.FILL, 0, 0); - unit_table.attach(unit_active_exit_timestamp_label, 3, 4, 7, 8, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); - - unit_table.attach(new LeftLabel("Can Start/Stop:"), 4, 5, 6, 7, AttachOptions.FILL, AttachOptions.FILL, 0, 0); - unit_table.attach(unit_can_start_label, 5, 6, 6, 7, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); - unit_table.attach(new LeftLabel("Can Reload:"), 4, 5, 7, 8, AttachOptions.FILL, AttachOptions.FILL, 0, 0); - unit_table.attach(unit_can_reload_label, 5, 6, 7, 8, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(unit_description_label, 1, 6, 2, 3, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(new LeftLabel("Dependencies:"), 0, 1, 3, 4, AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(unit_dependency_label, 1, 6, 3, 4, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(new LeftLabel("Fragment Path:"), 0, 1, 4, 5, AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(unit_fragment_path_label, 1, 6, 4, 5, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(new LeftLabel("Control Group:"), 0, 1, 5, 6, AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(unit_cgroup_label, 1, 6, 5, 6, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); + + unit_table.attach(new LeftLabel("Load State:"), 0, 1, 6, 7, AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(unit_load_state_label, 1, 2, 6, 7, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(new LeftLabel("Active State:"), 0, 1, 7, 8, AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(unit_active_state_label, 1, 2, 7, 8, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(new LeftLabel("Unit State:"), 0, 1, 8, 9, AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(unit_sub_state_label, 1, 2, 8, 9, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); + + unit_table.attach(new LeftLabel("Active Enter Timestamp:"), 2, 3, 7, 8, AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(unit_active_enter_timestamp_label, 3, 4, 7, 8, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(new LeftLabel("Active Exit Timestamp:"), 2, 3, 8, 9, AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(unit_active_exit_timestamp_label, 3, 4, 8, 9, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); + + unit_table.attach(new LeftLabel("Can Start/Stop:"), 4, 5, 7, 8, AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(unit_can_start_label, 5, 6, 7, 8, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(new LeftLabel("Can Reload:"), 4, 5, 8, 9, AttachOptions.FILL, AttachOptions.FILL, 0, 0); + unit_table.attach(unit_can_reload_label, 5, 6, 8, 9, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); job_table.attach(new LeftLabel("Id:"), 0, 1, 0, 1, AttachOptions.FILL, AttachOptions.FILL, 0, 0); job_table.attach(job_id_label, 1, 2, 0, 1, AttachOptions.EXPAND|AttachOptions.FILL, AttachOptions.FILL, 0, 0); @@ -297,6 +328,8 @@ public class MainWindow : Window { i.unit_path, "org.freedesktop.systemd1.Unit") as Unit; + u.changed += on_unit_changed; + unit_model.append(out iter); unit_model.set(iter, 0, i.id, @@ -322,6 +355,8 @@ public class MainWindow : Window { i.job_path, "org.freedesktop.systemd1.Job") as Job; + j.changed += on_job_changed; + job_model.append(out iter); job_model.set(iter, 0, "%u".printf(i.id), @@ -370,6 +405,7 @@ public class MainWindow : Window { unit_id_label.set_text_or_na(); unit_aliases_label.set_text_or_na(); unit_description_label.set_text_or_na(); + unit_description_label.set_text_or_na(); unit_load_state_label.set_text_or_na(); unit_active_state_label.set_text_or_na(); unit_sub_state_label.set_text_or_na(); @@ -381,11 +417,84 @@ public class MainWindow : Window { unit_cgroup_label.set_text_or_na(); } + public string make_dependency_string(string? prefix, string word, string[] dependencies) { + bool first = true; + string r; + + if (prefix == null) + r = ""; + else + r = prefix; + + foreach (string i in dependencies) { + if (r != "") + r += first ? "\n" : ","; + + if (first) { + r += word; + first = false; + } + + r += " " + i + ""; + } + + return r; + } + public void show_unit(Unit unit) { current_unit_id = unit.id; unit_id_label.set_text_or_na(current_unit_id); - unit_aliases_label.set_text_or_na(string.joinv("\n", unit.names)); + + string a = ""; + foreach (string i in unit.names) { + if (i == current_unit_id) + continue; + + if (a == "") + a = i; + else + a += "\n" + i; + } + + unit_aliases_label.set_text_or_na(a); + + string[] + requires = unit.requires, + requires_overridable = unit.requires_overridable, + requisite = unit.requisite, + requisite_overridable = unit.requisite_overridable, + wants = unit.wants, + required_by = unit.required_by, + required_by_overridable = unit.required_by_overridable, + wanted_by = unit.wanted_by, + conflicts = unit.conflicts, + before = unit.before, + after = unit.after; + + unit_dependency_label.set_markup_or_na( + make_dependency_string( + make_dependency_string( + make_dependency_string( + make_dependency_string( + make_dependency_string( + make_dependency_string( + make_dependency_string( + make_dependency_string( + make_dependency_string( + make_dependency_string( + make_dependency_string(null, + "requires", requires), + "overridable requires", requires_overridable), + "requisite", requisite), + "overridable requisite", requisite_overridable), + "wants", wants), + "conflicts", conflicts), + "required by", required_by), + "overridable required by", required_by_overridable), + "wanted by", wanted_by), + "after", after), + "before", before)); unit_description_label.set_text_or_na(unit.description); unit_load_state_label.set_text_or_na(unit.load_state); @@ -395,15 +504,15 @@ public class MainWindow : Window { uint64 t = unit.active_enter_timestamp; if (t > 0) { - TimeVal tv = { (long) (t / 1000000), (long) (t % 1000000) }; - unit_active_enter_timestamp_label.set_text_or_na(tv.to_iso8601()); + Time timestamp = Time.local((time_t) (t / 1000000)); + unit_active_enter_timestamp_label.set_text_or_na(timestamp.format("%a, %d %b %Y %H:%M:%S %z")); } else unit_active_enter_timestamp_label.set_text_or_na(); t = unit.active_exit_timestamp; if (t > 0) { - TimeVal tv = { (long) (t / 1000000), (long) (t % 1000000) }; - unit_active_exit_timestamp_label.set_text_or_na(tv.to_iso8601()); + Time timestamp = Time.local((time_t) (t / 1000000)); + unit_active_exit_timestamp_label.set_text_or_na(timestamp.format("%a, %d %b %Y %H:%M:%S %z")); } else unit_active_exit_timestamp_label.set_text_or_na(); @@ -475,7 +584,7 @@ public class MainWindow : Window { try { u.start("replace"); } catch (DBus.Error e) { - message("%s", e.message); + show_error(e.message); } } @@ -488,7 +597,7 @@ public class MainWindow : Window { try { u.stop("replace"); } catch (DBus.Error e) { - message("%s", e.message); + show_error(e.message); } } @@ -501,7 +610,7 @@ public class MainWindow : Window { try { u.reload("replace"); } catch (DBus.Error e) { - message("%s", e.message); + show_error(e.message); } } @@ -514,7 +623,7 @@ public class MainWindow : Window { try { u.restart("replace"); } catch (DBus.Error e) { - message("%s", e.message); + show_error(e.message); } } @@ -527,15 +636,11 @@ public class MainWindow : Window { try { j.cancel(); } catch (DBus.Error e) { - message("%s", e.message); + show_error(e.message); } } - public void on_unit_new(string id, ObjectPath path) { - Unit u = bus.get_object( - "org.freedesktop.systemd1", - path, - "org.freedesktop.systemd1.Unit") as Unit; + public void update_unit_iter(TreeIter iter, string id, Unit u) { string t = ""; Unit.JobLink jl = u.job; @@ -549,8 +654,6 @@ public class MainWindow : Window { t = j.job_type; } - TreeIter iter; - unit_model.append(out iter); unit_model.set(iter, 0, id, 1, u.description, @@ -561,16 +664,22 @@ public class MainWindow : Window { 6, u); } - public void on_job_new(uint32 id, ObjectPath path) { - Job j = bus.get_object( + public void on_unit_new(string id, ObjectPath path) { + Unit u = bus.get_object( "org.freedesktop.systemd1", path, - "org.freedesktop.systemd1.Job") as Job; + "org.freedesktop.systemd1.Unit") as Unit; + + u.changed += on_unit_changed; TreeIter iter; - job_model.append(out iter); + unit_model.append(out iter); + update_unit_iter(iter, id, u); + } + + public void update_job_iter(TreeIter iter, uint32 id, Job j) { job_model.set(iter, - 0, "%u".printf(j.id), + 0, "%u".printf(id), 1, j.unit.id, 2, "→ %s".printf(j.job_type), 3, j.state, @@ -578,6 +687,19 @@ public class MainWindow : Window { 5, id); } + public void on_job_new(uint32 id, ObjectPath path) { + Job j = bus.get_object( + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Job") as Job; + + j.changed += on_job_changed; + + TreeIter iter; + job_model.append(out iter); + update_job_iter(iter, id, j); + } + public void on_unit_removed(string id, ObjectPath path) { TreeIter iter; if (!(unit_model.get_iter_first(out iter))) @@ -621,10 +743,62 @@ public class MainWindow : Window { } while (job_model.iter_next(ref iter)); } + public void on_unit_changed(Unit u) { + TreeIter iter; + string id; + + if (!(unit_model.get_iter_first(out iter))) + return; + + id = u.id; + + do { + string name; + + unit_model.get(iter, 0, out name); + + if (id == name) { + update_unit_iter(iter, id, u); + + if (current_unit_id == id) + show_unit(u); + + break; + } + + } while (unit_model.iter_next(ref iter)); + } + + public void on_job_changed(Job j) { + TreeIter iter; + uint32 id; + + if (!(job_model.get_iter_first(out iter))) + return; + + id = j.id; + + do { + uint32 k; + + job_model.get(iter, 5, out k); + + if (id == k) { + update_job_iter(iter, id, j); + + if (current_job_id == id) + show_job(j); + + break; + } + + } while (job_model.iter_next(ref iter)); + } + public bool unit_filter(TreeModel model, TreeIter iter) { - string id, active_state; + string id, active_state, job; - model.get(iter, 0, out id, 3, out active_state); + model.get(iter, 0, out id, 3, out active_state, 5, out job); if (id == null) return false; @@ -635,7 +809,7 @@ public class MainWindow : Window { return true; case 1: - return active_state != "inactive"; + return active_state != "inactive" || job != ""; case 2: return id.has_suffix(".service"); @@ -672,7 +846,7 @@ public class MainWindow : Window { try { manager.reload(); } catch (DBus.Error e) { - message("%s", e.message); + show_error(e.message); } } @@ -684,9 +858,70 @@ public class MainWindow : Window { unit_type_combo_box.set_active(8); } catch (DBus.Error e) { - message("%s", e.message); + show_error(e.message); + } + } + + public void on_unit_load() { + string t = unit_load_entry.get_text(); + + if (t == "") + return; + + try { + var path = manager.load_unit(t); + + Unit u = bus.get_object( + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Unit") as Unit; + + var m = new MessageDialog(this, + DialogFlags.DESTROY_WITH_PARENT, + MessageType.INFO, + ButtonsType.CLOSE, + "Unit available as id %s", u.id); + m.title = "Unit"; + m.run(); + m.destroy(); + + } catch (DBus.Error e) { + show_error(e.message); + } + } + + public void on_unit_load_entry_changed() { + unit_load_button.set_sensitive(unit_load_entry.get_text() != ""); + } + + public bool on_activate_link(string uri) { + + try { + string path = manager.get_unit(uri); + + Unit u = bus.get_object( + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Unit") as Unit; + + show_unit(u); + } catch (DBus.Error e) { + show_error(e.message); } + + return true; + } + + public void show_error(string e) { + var m = new MessageDialog(this, + DialogFlags.DESTROY_WITH_PARENT, + MessageType.ERROR, + ButtonsType.CLOSE, "%s", e); + m.title = "Error"; + m.run(); + m.destroy(); } + } static const OptionEntry entries[] = { @@ -695,6 +930,12 @@ static const OptionEntry entries[] = { { null } }; +void show_error(string e) { + var m = new MessageDialog(null, 0, MessageType.ERROR, ButtonsType.CLOSE, "%s", e); + m.run(); + m.destroy(); +} + int main (string[] args) { try { @@ -702,12 +943,13 @@ int main (string[] args) { MainWindow window = new MainWindow(); window.show_all(); + + Gtk.main(); } catch (DBus.Error e) { - message("%s", e.message); + show_error(e.message); } catch (GLib.Error e) { - message("%s", e.message); + show_error(e.message); } - Gtk.main(); return 0; }