2010-02-03 15:03:47 +03:00
/ * * *
This file is part of systemd .
Copyright 2010 Lennart Poettering
systemd 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 ; either version 2 of the License , or
( at your option ) any later version .
systemd 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 systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * * /
2010-02-03 14:39:12 +03:00
using Gtk ;
using GLib ;
using DBus ;
using Pango ;
2010-04-07 18:23:08 +04:00
static bool session = false ;
2010-02-03 14:39:12 +03:00
public class LeftLabel : Label {
public LeftLabel ( string ? text = null ) {
if ( text ! = null )
set_markup ( " <b>%s</b> " . printf ( text ) ) ;
set_alignment ( 1 , 0 ) ;
set_padding ( 6 , 0 ) ;
}
}
public class RightLabel : Label {
public RightLabel ( string ? text = null ) {
set_text_or_na ( text ) ;
set_alignment ( 0 , 1 ) ;
set_ellipsize ( EllipsizeMode . START ) ;
set_selectable ( true ) ;
}
public void set_text_or_na ( string ? text = null ) {
if ( text = = null | | text = = " " )
set_markup ( " <i>n/a</i> " ) ;
else
set_text ( text ) ;
}
}
public class MainWindow : Window {
private TreeView unit_view ;
private TreeView job_view ;
private ListStore unit_model ;
private ListStore job_model ;
private Button start_button ;
private Button stop_button ;
private Button restart_button ;
private Button reload_button ;
private Button cancel_button ;
private Connection bus ;
private Manager manager ;
private RightLabel unit_id_label ;
private RightLabel unit_description_label ;
private RightLabel unit_load_state_label ;
private RightLabel unit_active_state_label ;
2010-02-14 03:01:10 +03:00
private RightLabel unit_fragment_path_label ;
2010-02-03 14:39:12 +03:00
private RightLabel unit_active_enter_timestamp_label ;
private RightLabel unit_active_exit_timestamp_label ;
private RightLabel unit_can_start_label ;
private RightLabel unit_can_reload_label ;
private RightLabel job_id_label ;
private RightLabel job_state_label ;
private RightLabel job_type_label ;
public MainWindow ( ) throws DBus . Error {
title = " systemdadm " ;
position = WindowPosition . CENTER ;
set_default_size ( 1000 , 700 ) ;
set_border_width ( 12 ) ;
2010-02-05 02:38:41 +03:00
destroy + = Gtk . main_quit ;
2010-02-03 14:39:12 +03:00
Notebook notebook = new Notebook ( ) ;
add ( notebook ) ;
Box unit_vbox = new VBox ( false , 6 ) ;
notebook . append_page ( unit_vbox , new Label ( " Units " ) ) ;
unit_vbox . set_border_width ( 12 ) ;
Box job_vbox = new VBox ( false , 6 ) ;
notebook . append_page ( job_vbox , new Label ( " Jobs " ) ) ;
job_vbox . set_border_width ( 12 ) ;
2010-02-05 02:38:41 +03:00
unit_model = new ListStore ( 6 , typeof ( string ) , typeof ( string ) , typeof ( string ) , typeof ( string ) , typeof ( string ) , typeof ( Unit ) ) ;
job_model = new ListStore ( 5 , typeof ( string ) , typeof ( string ) , typeof ( string ) , typeof ( string ) , typeof ( Job ) ) ;
2010-02-03 14:39:12 +03:00
unit_view = new TreeView . with_model ( unit_model ) ;
job_view = new TreeView . with_model ( job_model ) ;
2010-02-05 02:38:41 +03:00
unit_view . cursor_changed + = unit_changed ;
job_view . cursor_changed + = job_changed ;
2010-02-03 14:39:12 +03:00
unit_view . insert_column_with_attributes ( - 1 , " Unit " , new CellRendererText ( ) , " text " , 0 ) ;
unit_view . insert_column_with_attributes ( - 1 , " Description " , new CellRendererText ( ) , " text " , 1 ) ;
unit_view . insert_column_with_attributes ( - 1 , " Load State " , new CellRendererText ( ) , " text " , 2 ) ;
unit_view . insert_column_with_attributes ( - 1 , " Active State " , new CellRendererText ( ) , " text " , 3 ) ;
unit_view . insert_column_with_attributes ( - 1 , " Job " , new CellRendererText ( ) , " text " , 4 ) ;
job_view . insert_column_with_attributes ( - 1 , " Job " , new CellRendererText ( ) , " text " , 0 ) ;
job_view . insert_column_with_attributes ( - 1 , " Unit " , new CellRendererText ( ) , " text " , 1 ) ;
job_view . insert_column_with_attributes ( - 1 , " Type " , new CellRendererText ( ) , " text " , 2 ) ;
job_view . insert_column_with_attributes ( - 1 , " State " , new CellRendererText ( ) , " text " , 3 ) ;
ScrolledWindow scroll = new ScrolledWindow ( null , null ) ;
scroll . set_policy ( PolicyType . AUTOMATIC , PolicyType . AUTOMATIC ) ;
scroll . set_shadow_type ( ShadowType . IN ) ;
scroll . add ( unit_view ) ;
unit_vbox . pack_start ( scroll , true , true , 0 ) ;
scroll = new ScrolledWindow ( null , null ) ;
scroll . set_policy ( PolicyType . AUTOMATIC , PolicyType . AUTOMATIC ) ;
scroll . set_shadow_type ( ShadowType . IN ) ;
scroll . add ( job_view ) ;
job_vbox . pack_start ( scroll , true , true , 0 ) ;
unit_id_label = new RightLabel ( ) ;
unit_description_label = new RightLabel ( ) ;
unit_load_state_label = new RightLabel ( ) ;
unit_active_state_label = new RightLabel ( ) ;
2010-02-14 03:01:10 +03:00
unit_fragment_path_label = new RightLabel ( ) ;
2010-02-03 14:39:12 +03:00
unit_active_enter_timestamp_label = new RightLabel ( ) ;
unit_active_exit_timestamp_label = new RightLabel ( ) ;
unit_can_start_label = new RightLabel ( ) ;
unit_can_reload_label = new RightLabel ( ) ;
job_id_label = new RightLabel ( ) ;
job_state_label = new RightLabel ( ) ;
job_type_label = new RightLabel ( ) ;
Table unit_table = new Table ( 9 , 2 , false ) ;
unit_table . set_row_spacings ( 6 ) ;
unit_table . set_border_width ( 12 ) ;
unit_vbox . pack_start ( unit_table , false , true , 0 ) ;
Table job_table = new Table ( 2 , 2 , false ) ;
job_table . set_row_spacings ( 6 ) ;
job_table . set_border_width ( 12 ) ;
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 , 2 , 0 , 1 , AttachOptions . EXPAND | AttachOptions . FILL , AttachOptions . FILL , 0 , 0 ) ;
unit_table . attach ( new LeftLabel ( " Description: " ) , 0 , 1 , 1 , 2 , AttachOptions . FILL , AttachOptions . FILL , 0 , 0 ) ;
unit_table . attach ( unit_description_label , 1 , 2 , 1 , 2 , AttachOptions . EXPAND | AttachOptions . FILL , AttachOptions . FILL , 0 , 0 ) ;
unit_table . attach ( new LeftLabel ( " Load State: " ) , 0 , 1 , 2 , 3 , AttachOptions . FILL , AttachOptions . FILL , 0 , 0 ) ;
unit_table . attach ( unit_load_state_label , 1 , 2 , 2 , 3 , AttachOptions . EXPAND | AttachOptions . FILL , AttachOptions . FILL , 0 , 0 ) ;
unit_table . attach ( new LeftLabel ( " Active State: " ) , 0 , 1 , 3 , 4 , AttachOptions . FILL , AttachOptions . FILL , 0 , 0 ) ;
unit_table . attach ( unit_active_state_label , 1 , 2 , 3 , 4 , AttachOptions . EXPAND | AttachOptions . FILL , AttachOptions . FILL , 0 , 0 ) ;
2010-02-14 03:01:10 +03:00
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 , 2 , 4 , 5 , AttachOptions . EXPAND | AttachOptions . FILL , AttachOptions . FILL , 0 , 0 ) ;
2010-02-03 14:39:12 +03:00
unit_table . attach ( new LeftLabel ( " Active Enter Timestamp: " ) , 0 , 1 , 5 , 6 , AttachOptions . FILL , AttachOptions . FILL , 0 , 0 ) ;
unit_table . attach ( unit_active_enter_timestamp_label , 1 , 2 , 5 , 6 , AttachOptions . EXPAND | AttachOptions . FILL , AttachOptions . FILL , 0 , 0 ) ;
unit_table . attach ( new LeftLabel ( " Active Exit Timestamp: " ) , 0 , 1 , 6 , 7 , AttachOptions . FILL , AttachOptions . FILL , 0 , 0 ) ;
unit_table . attach ( unit_active_exit_timestamp_label , 1 , 2 , 6 , 7 , AttachOptions . EXPAND | AttachOptions . FILL , AttachOptions . FILL , 0 , 0 ) ;
unit_table . attach ( new LeftLabel ( " Can Start/Stop: " ) , 0 , 1 , 7 , 8 , AttachOptions . FILL , AttachOptions . FILL , 0 , 0 ) ;
unit_table . attach ( unit_can_start_label , 1 , 2 , 7 , 8 , AttachOptions . EXPAND | AttachOptions . FILL , AttachOptions . FILL , 0 , 0 ) ;
unit_table . attach ( new LeftLabel ( " Can Reload: " ) , 0 , 1 , 8 , 9 , AttachOptions . FILL , AttachOptions . FILL , 0 , 0 ) ;
unit_table . attach ( unit_can_reload_label , 1 , 2 , 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 ) ;
job_table . attach ( new LeftLabel ( " State: " ) , 0 , 1 , 1 , 2 , AttachOptions . FILL , AttachOptions . FILL , 0 , 0 ) ;
job_table . attach ( job_state_label , 1 , 2 , 1 , 2 , AttachOptions . EXPAND | AttachOptions . FILL , AttachOptions . FILL , 0 , 0 ) ;
job_table . attach ( new LeftLabel ( " Type: " ) , 0 , 1 , 2 , 3 , AttachOptions . FILL , AttachOptions . FILL , 0 , 0 ) ;
job_table . attach ( job_type_label , 1 , 2 , 2 , 3 , AttachOptions . EXPAND | AttachOptions . FILL , AttachOptions . FILL , 0 , 0 ) ;
ButtonBox bbox = new HButtonBox ( ) ;
bbox . set_layout ( ButtonBoxStyle . START ) ;
bbox . set_spacing ( 6 ) ;
unit_vbox . pack_start ( bbox , false , true , 0 ) ;
start_button = new Button . with_mnemonic ( " _Start " ) ;
stop_button = new Button . with_mnemonic ( " Sto_p " ) ;
reload_button = new Button . with_mnemonic ( " _Reload " ) ;
restart_button = new Button . with_mnemonic ( " Res_tart " ) ;
2010-02-05 02:38:41 +03:00
start_button . clicked + = on_start ;
stop_button . clicked + = on_stop ;
reload_button . clicked + = on_reload ;
restart_button . clicked + = on_restart ;
2010-02-03 14:39:12 +03:00
bbox . pack_start ( start_button , false , true , 0 ) ;
bbox . pack_start ( stop_button , false , true , 0 ) ;
bbox . pack_start ( restart_button , false , true , 0 ) ;
bbox . pack_start ( reload_button , false , true , 0 ) ;
bbox = new HButtonBox ( ) ;
bbox . set_layout ( ButtonBoxStyle . START ) ;
bbox . set_spacing ( 6 ) ;
job_vbox . pack_start ( bbox , false , true , 0 ) ;
cancel_button = new Button . with_mnemonic ( " _Cancel " ) ;
2010-02-05 02:38:41 +03:00
cancel_button . clicked + = on_cancel ;
2010-02-03 14:39:12 +03:00
bbox . pack_start ( cancel_button , false , true , 0 ) ;
2010-04-07 18:23:08 +04:00
bus = Bus . get ( session ? BusType . SESSION : BusType . SYSTEM ) ;
2010-02-03 14:39:12 +03:00
2010-02-05 02:38:41 +03:00
manager = bus . get_object (
2010-02-03 14:39:12 +03:00
" org.freedesktop.systemd1 " ,
" /org/freedesktop/systemd1 " ,
" org.freedesktop.systemd1 " ) as Manager ;
2010-02-05 02:38:41 +03:00
manager . unit_new + = on_unit_new ;
manager . job_new + = on_job_new ;
manager . unit_removed + = on_unit_removed ;
manager . job_removed + = on_job_removed ;
manager . subscribe ( ) ;
2010-02-03 14:39:12 +03:00
clear_unit ( ) ;
populate_unit_model ( ) ;
populate_job_model ( ) ;
}
public void populate_unit_model ( ) throws DBus . Error {
unit_model . clear ( ) ;
var list = manager . list_units ( ) ;
foreach ( var i in list ) {
TreeIter iter ;
2010-02-05 02:38:41 +03:00
Unit u = bus . get_object (
" org.freedesktop.systemd1 " ,
i . unit_path ,
" org.freedesktop.systemd1.Unit " ) as Unit ;
2010-02-03 14:39:12 +03:00
unit_model . append ( out iter ) ;
unit_model . set ( iter ,
0 , i . id ,
1 , i . description ,
2 , i . load_state ,
3 , i . active_state ,
4 , i . job_type ! = " " ? " → %s " . printf ( i . job_type ) : " " ,
2010-02-05 02:38:41 +03:00
5 , u ) ;
2010-02-03 14:39:12 +03:00
}
}
public void populate_job_model ( ) throws DBus . Error {
job_model . clear ( ) ;
var list = manager . list_jobs ( ) ;
foreach ( var i in list ) {
TreeIter iter ;
2010-02-05 02:38:41 +03:00
Job j = bus . get_object (
" org.freedesktop.systemd1 " ,
i . job_path ,
" org.freedesktop.systemd1.Job " ) as Job ;
2010-02-03 14:39:12 +03:00
job_model . append ( out iter ) ;
job_model . set ( iter ,
0 , " %u " . printf ( i . id ) ,
1 , i . name ,
2 , " → %s " . printf ( i . type ) ,
3 , i . state ,
2010-02-05 02:38:41 +03:00
4 , j ) ;
2010-02-03 14:39:12 +03:00
}
}
public Unit ? get_current_unit ( ) {
TreePath p ;
unit_view . get_cursor ( out p , null ) ;
if ( p = = null )
return null ;
TreeIter iter ;
2010-02-05 02:38:41 +03:00
Unit u ;
2010-02-03 14:39:12 +03:00
unit_model . get_iter ( out iter , p ) ;
2010-02-05 02:38:41 +03:00
unit_model . get ( iter , 5 , out u ) ;
2010-02-03 14:39:12 +03:00
2010-02-05 02:38:41 +03:00
return u ;
2010-02-03 14:39:12 +03:00
}
public void unit_changed ( ) {
Unit u = get_current_unit ( ) ;
if ( u = = null )
clear_unit ( ) ;
else
show_unit ( u ) ;
}
public void clear_unit ( ) {
start_button . set_sensitive ( false ) ;
stop_button . set_sensitive ( false ) ;
reload_button . set_sensitive ( false ) ;
restart_button . set_sensitive ( false ) ;
unit_id_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 ( ) ;
2010-02-14 03:01:10 +03:00
unit_fragment_path_label . set_text_or_na ( ) ;
2010-02-03 14:39:12 +03:00
unit_active_enter_timestamp_label . set_text_or_na ( ) ;
unit_active_exit_timestamp_label . set_text_or_na ( ) ;
unit_can_reload_label . set_text_or_na ( ) ;
unit_can_start_label . set_text_or_na ( ) ;
}
public void show_unit ( Unit unit ) {
unit_id_label . set_text_or_na ( unit . id ) ;
unit_description_label . set_text_or_na ( unit . description ) ;
unit_load_state_label . set_text_or_na ( unit . load_state ) ;
unit_active_state_label . set_text_or_na ( unit . active_state ) ;
2010-02-14 03:01:10 +03:00
unit_fragment_path_label . set_text_or_na ( unit . fragment_path ) ;
2010-02-03 14:39:12 +03:00
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 ( ) ) ;
} 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 ( ) ) ;
} else
unit_active_exit_timestamp_label . set_text_or_na ( ) ;
bool b = unit . can_start ;
start_button . set_sensitive ( b ) ;
stop_button . set_sensitive ( b ) ;
restart_button . set_sensitive ( b ) ;
unit_can_start_label . set_text_or_na ( b ? " Yes " : " No " ) ;
b = unit . can_reload ;
reload_button . set_sensitive ( b ) ;
unit_can_reload_label . set_text_or_na ( b ? " Yes " : " No " ) ;
}
public Job ? get_current_job ( ) {
TreePath p ;
job_view . get_cursor ( out p , null ) ;
if ( p = = null )
return null ;
TreeIter iter ;
2010-02-05 02:38:41 +03:00
Job * j ;
2010-02-03 14:39:12 +03:00
job_model . get_iter ( out iter , p ) ;
2010-02-05 02:38:41 +03:00
job_model . get ( iter , 4 , out j ) ;
2010-02-03 14:39:12 +03:00
2010-02-05 02:38:41 +03:00
return j ;
2010-02-03 14:39:12 +03:00
}
public void job_changed ( ) {
Job j = get_current_job ( ) ;
if ( j = = null )
clear_job ( ) ;
else
show_job ( j ) ;
}
public void clear_job ( ) {
job_id_label . set_text_or_na ( ) ;
job_state_label . set_text_or_na ( ) ;
job_type_label . set_text_or_na ( ) ;
}
public void show_job ( Job job ) {
job_id_label . set_text_or_na ( " %u " . printf ( job . id ) ) ;
job_state_label . set_text_or_na ( job . state ) ;
job_type_label . set_text_or_na ( job . job_type ) ;
}
public void on_start ( ) {
Unit u = get_current_unit ( ) ;
if ( u = = null )
return ;
try {
u . start ( " replace " ) ;
} catch ( DBus . Error e ) {
message ( " %s " , e . message ) ;
}
}
public void on_stop ( ) {
Unit u = get_current_unit ( ) ;
if ( u = = null )
return ;
try {
u . stop ( " replace " ) ;
} catch ( DBus . Error e ) {
message ( " %s " , e . message ) ;
}
}
public void on_reload ( ) {
Unit u = get_current_unit ( ) ;
if ( u = = null )
return ;
try {
u . reload ( " replace " ) ;
} catch ( DBus . Error e ) {
message ( " %s " , e . message ) ;
}
}
public void on_restart ( ) {
Unit u = get_current_unit ( ) ;
if ( u = = null )
return ;
try {
u . restart ( " replace " ) ;
} catch ( DBus . Error e ) {
message ( " %s " , e . message ) ;
}
}
public void on_cancel ( ) {
Job j = get_current_job ( ) ;
if ( j = = null )
return ;
try {
j . cancel ( ) ;
} catch ( DBus . Error e ) {
message ( " %s " , e . message ) ;
}
}
2010-02-05 02:38:41 +03:00
public void on_unit_new ( string id , ObjectPath path ) {
stderr . printf ( " new path %s " , path ) ;
Unit u = bus . get_object (
" org.freedesktop.systemd1 " ,
path ,
" org.freedesktop.systemd1.Unit " ) as Unit ;
string t = " " ;
Unit . JobLink jl = u . job ;
if ( jl . id ! = 0 ) {
Job j = bus . get_object (
" org.freedesktop.systemd1 " ,
jl . path ,
" org.freedesktop.systemd1.Job " ) as Job ;
t = j . job_type ;
}
TreeIter iter ;
unit_model . append ( out iter ) ;
unit_model . set ( iter ,
0 , u . id ,
1 , u . description ,
2 , u . load_state ,
3 , u . active_state ,
4 , t ! = " " ? " → %s " . printf ( t ) : " " ,
5 , u ) ;
}
public void on_job_new ( uint32 id , ObjectPath path ) {
stderr . printf ( " new path %s " , path ) ;
Job j = bus . get_object (
" org.freedesktop.systemd1 " ,
path ,
" org.freedesktop.systemd1.Job " ) as Job ;
TreeIter iter ;
job_model . append ( out iter ) ;
job_model . set ( iter ,
0 , " %u " . printf ( j . id ) ,
1 , j . unit . id ,
2 , " → %s " . printf ( j . job_type ) ,
3 , j . state ,
4 , j ) ;
}
public void on_unit_removed ( string id , ObjectPath path ) {
stdout . printf ( " Unit %s removed. \n " , id ) ;
/* FIXME */
}
public void on_job_removed ( uint32 id , ObjectPath path ) {
stdout . printf ( " Job %u removed. \n " , id ) ;
/* FIXME */
}
2010-02-03 14:39:12 +03:00
}
2010-04-07 18:23:08 +04:00
static const OptionEntry entries [ ] = {
{ " session " , 0 , 0 , OptionArg . NONE , out session , " Connect to session bus " , null } ,
{ " system " , 0 , OptionFlags . REVERSE , OptionArg . NONE , out session , " Connect to system bus " , null } ,
{ null }
} ;
2010-02-03 14:39:12 +03:00
int main ( string [ ] args ) {
try {
2010-04-07 18:23:08 +04:00
Gtk . init_with_args ( ref args , " [OPTION...] " , entries , " systemadm " ) ;
2010-02-03 14:39:12 +03:00
MainWindow window = new MainWindow ( ) ;
window . show_all ( ) ;
} catch ( DBus . Error e ) {
message ( " %s " , e . message ) ;
2010-04-07 18:23:08 +04:00
} catch ( GLib . Error e ) {
message ( " %s " , e . message ) ;
2010-02-03 14:39:12 +03:00
}
Gtk . main ( ) ;
return 0 ;
}