else
set_text(text);
}
+
+ public void set_markup_or_na(string? text = null) {
+ if (text == null || text == "")
+ set_markup("<i>n/a</i>");
+ else
+ set_markup(text);
+ }
}
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;
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;
private ComboBox unit_type_combo_box;
public MainWindow() throws DBus.Error {
- title = "systemdadm";
+ title = session ? "systemd Session Manager" : "systemd System Manager";
position = WindowPosition.CENTER;
set_default_size(1000, 700);
set_border_width(12);
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;
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));
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();
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);
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, 6, 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, 6, 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, 6, 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(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);
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,
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),
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();
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 += " <a href=\"" + i + "\">" + i + "</a>";
+ }
+
+ 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);
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();
try {
u.start("replace");
} catch (DBus.Error e) {
- message("%s", e.message);
+ show_error(e.message);
}
}
try {
u.stop("replace");
} catch (DBus.Error e) {
- message("%s", e.message);
+ show_error(e.message);
}
}
try {
u.reload("replace");
} catch (DBus.Error e) {
- message("%s", e.message);
+ show_error(e.message);
}
}
try {
u.restart("replace");
} catch (DBus.Error e) {
- message("%s", e.message);
+ show_error(e.message);
}
}
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;
t = j.job_type;
}
- TreeIter iter;
- unit_model.append(out iter);
unit_model.set(iter,
0, id,
1, u.description,
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,
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)))
} 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;
return true;
case 1:
- return active_state != "inactive";
+ return active_state != "inactive" || job != "";
case 2:
return id.has_suffix(".service");
try {
manager.reload();
} catch (DBus.Error e) {
- message("%s", e.message);
+ show_error(e.message);
}
}
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();
+
+ show_unit(u);
+ } 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[] = {
{ 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 {
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);
}
return 0;