2010-08-14 21:59:25 +04:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2010-01-23 03:52:57 +03:00
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
2012-04-12 02:20:58 +04:00
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation ; either version 2.1 of the License , or
2010-02-03 15:03:47 +03:00
( 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
2012-04-12 02:20:58 +04:00
Lesser General Public License for more details .
2010-02-03 15:03:47 +03:00
2012-04-12 02:20:58 +04:00
You should have received a copy of the GNU Lesser General Public License
2010-02-03 15:03:47 +03:00
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
2010-04-18 05:07:42 +04:00
# include <errno.h>
2010-01-26 23:39:06 +03:00
# include "unit.h"
2010-01-23 03:52:57 +03:00
# include "snapshot.h"
2010-04-18 05:07:42 +04:00
# include "unit-name.h"
# include "dbus-snapshot.h"
2014-12-10 21:00:46 +03:00
# include "bus-common-errors.h"
2010-04-18 05:07:42 +04:00
static const UnitActiveState state_translation_table [ _SNAPSHOT_STATE_MAX ] = {
[ SNAPSHOT_DEAD ] = UNIT_INACTIVE ,
[ SNAPSHOT_ACTIVE ] = UNIT_ACTIVE
} ;
2011-05-05 12:58:55 +04:00
static void snapshot_init ( Unit * u ) {
Snapshot * s = SNAPSHOT ( u ) ;
assert ( s ) ;
2012-01-15 15:25:20 +04:00
assert ( UNIT ( s ) - > load_state = = UNIT_STUB ) ;
2011-05-05 12:58:55 +04:00
2012-01-15 15:25:20 +04:00
UNIT ( s ) - > ignore_on_isolate = true ;
UNIT ( s ) - > ignore_on_snapshot = true ;
2013-07-01 02:02:03 +04:00
UNIT ( s ) - > allow_isolate = true ;
2011-05-05 12:58:55 +04:00
}
2010-04-21 05:27:44 +04:00
static void snapshot_set_state ( Snapshot * s , SnapshotState state ) {
SnapshotState old_state ;
assert ( s ) ;
2010-04-18 05:07:42 +04:00
2010-04-21 05:27:44 +04:00
old_state = s - > state ;
s - > state = state ;
2010-04-18 05:07:42 +04:00
2010-04-21 05:27:44 +04:00
if ( state ! = old_state )
2014-11-27 22:20:23 +03:00
log_unit_debug ( UNIT ( s ) - > id ,
2014-06-22 22:20:08 +04:00
" %s changed %s -> %s " ,
UNIT ( s ) - > id ,
snapshot_state_to_string ( old_state ) ,
snapshot_state_to_string ( state ) ) ;
2010-01-23 03:52:57 +03:00
2011-01-20 15:17:22 +03:00
unit_notify ( UNIT ( s ) , state_translation_table [ old_state ] , state_translation_table [ state ] , true ) ;
2010-04-21 05:27:44 +04:00
}
2010-04-18 05:07:42 +04:00
2010-07-01 05:39:55 +04:00
static int snapshot_load ( Unit * u ) {
Snapshot * s = SNAPSHOT ( u ) ;
assert ( u ) ;
2012-01-15 15:04:08 +04:00
assert ( u - > load_state = = UNIT_STUB ) ;
2010-07-01 05:39:55 +04:00
/* Make sure that only snapshots created via snapshot_create()
* can be loaded */
2013-07-01 02:02:03 +04:00
if ( ! u - > transient & & UNIT ( s ) - > manager - > n_reloading < = 0 )
2010-07-01 05:39:55 +04:00
return - ENOENT ;
2012-01-15 15:04:08 +04:00
u - > load_state = UNIT_LOADED ;
2010-07-01 05:39:55 +04:00
return 0 ;
}
2010-04-21 05:27:44 +04:00
static int snapshot_coldplug ( Unit * u ) {
Snapshot * s = SNAPSHOT ( u ) ;
2010-04-18 05:07:42 +04:00
2010-04-21 05:27:44 +04:00
assert ( s ) ;
assert ( s - > state = = SNAPSHOT_DEAD ) ;
2010-04-18 05:07:42 +04:00
2010-04-21 05:27:44 +04:00
if ( s - > deserialized_state ! = s - > state )
snapshot_set_state ( s , s - > deserialized_state ) ;
2010-04-18 05:07:42 +04:00
return 0 ;
}
static void snapshot_dump ( Unit * u , FILE * f , const char * prefix ) {
2010-01-26 23:39:06 +03:00
Snapshot * s = SNAPSHOT ( u ) ;
2010-01-23 03:52:57 +03:00
assert ( s ) ;
2010-04-18 05:07:42 +04:00
assert ( f ) ;
2010-01-23 03:52:57 +03:00
2010-04-18 05:07:42 +04:00
fprintf ( f ,
" %sSnapshot State: %s \n "
" %sClean Up: %s \n " ,
2010-04-21 05:27:44 +04:00
prefix , snapshot_state_to_string ( s - > state ) ,
2010-04-18 05:07:42 +04:00
prefix , yes_no ( s - > cleanup ) ) ;
}
static int snapshot_start ( Unit * u ) {
Snapshot * s = SNAPSHOT ( u ) ;
assert ( s ) ;
assert ( s - > state = = SNAPSHOT_DEAD ) ;
snapshot_set_state ( s , SNAPSHOT_ACTIVE ) ;
if ( s - > cleanup )
unit_add_to_cleanup_queue ( u ) ;
return 0 ;
}
static int snapshot_stop ( Unit * u ) {
Snapshot * s = SNAPSHOT ( u ) ;
assert ( s ) ;
assert ( s - > state = = SNAPSHOT_ACTIVE ) ;
snapshot_set_state ( s , SNAPSHOT_DEAD ) ;
return 0 ;
2010-01-23 03:52:57 +03:00
}
2010-04-21 05:27:44 +04:00
static int snapshot_serialize ( Unit * u , FILE * f , FDSet * fds ) {
Snapshot * s = SNAPSHOT ( u ) ;
Unit * other ;
Iterator i ;
assert ( s ) ;
assert ( f ) ;
assert ( fds ) ;
unit_serialize_item ( u , f , " state " , snapshot_state_to_string ( s - > state ) ) ;
unit_serialize_item ( u , f , " cleanup " , yes_no ( s - > cleanup ) ) ;
2012-01-15 15:04:08 +04:00
SET_FOREACH ( other , u - > dependencies [ UNIT_WANTS ] , i )
unit_serialize_item ( u , f , " wants " , other - > id ) ;
2010-04-21 05:27:44 +04:00
return 0 ;
}
static int snapshot_deserialize_item ( Unit * u , const char * key , const char * value , FDSet * fds ) {
Snapshot * s = SNAPSHOT ( u ) ;
int r ;
assert ( u ) ;
assert ( key ) ;
assert ( value ) ;
assert ( fds ) ;
if ( streq ( key , " state " ) ) {
SnapshotState state ;
2013-07-01 02:02:03 +04:00
state = snapshot_state_from_string ( value ) ;
if ( state < 0 )
2014-11-27 22:20:23 +03:00
log_unit_debug ( u - > id , " Failed to parse state value %s " , value ) ;
2010-04-21 05:27:44 +04:00
else
s - > deserialized_state = state ;
} else if ( streq ( key , " cleanup " ) ) {
2013-07-01 02:02:03 +04:00
r = parse_boolean ( value ) ;
if ( r < 0 )
2014-11-27 22:20:23 +03:00
log_unit_debug ( u - > id , " Failed to parse cleanup value %s " , value ) ;
2010-04-21 05:27:44 +04:00
else
s - > cleanup = r ;
2010-07-03 21:51:24 +04:00
} else if ( streq ( key , " wants " ) ) {
2010-04-21 05:27:44 +04:00
2013-07-01 02:02:03 +04:00
r = unit_add_two_dependencies_by_name ( u , UNIT_AFTER , UNIT_WANTS , value , NULL , true ) ;
if ( r < 0 )
2010-04-21 05:27:44 +04:00
return r ;
} else
2014-11-27 22:20:23 +03:00
log_unit_debug ( u - > id , " Unknown serialization key '%s' " , key ) ;
2010-04-21 05:27:44 +04:00
return 0 ;
}
2013-05-03 06:51:50 +04:00
_pure_ static UnitActiveState snapshot_active_state ( Unit * u ) {
2010-04-18 05:07:42 +04:00
assert ( u ) ;
return state_translation_table [ SNAPSHOT ( u ) - > state ] ;
}
2013-05-03 06:51:50 +04:00
_pure_ static const char * snapshot_sub_state_to_string ( Unit * u ) {
2010-04-18 05:07:42 +04:00
assert ( u ) ;
2010-04-21 05:27:44 +04:00
return snapshot_state_to_string ( SNAPSHOT ( u ) - > state ) ;
2010-04-18 05:07:42 +04:00
}
2013-11-20 00:12:59 +04:00
int snapshot_create ( Manager * m , const char * name , bool cleanup , sd_bus_error * e , Snapshot * * _s ) {
2013-07-01 02:02:03 +04:00
_cleanup_free_ char * n = NULL ;
2010-04-21 05:27:44 +04:00
Unit * other , * u = NULL ;
2013-07-01 02:02:03 +04:00
Iterator i ;
2010-04-18 05:07:42 +04:00
int r ;
2010-04-21 05:27:44 +04:00
const char * k ;
2010-04-18 05:07:42 +04:00
assert ( m ) ;
assert ( _s ) ;
if ( name ) {
2013-12-27 00:30:22 +04:00
if ( ! unit_name_is_valid ( name , TEMPLATE_INVALID ) )
2013-11-20 00:12:59 +04:00
return sd_bus_error_setf ( e , SD_BUS_ERROR_INVALID_ARGS , " Unit name %s is not valid. " , name ) ;
2010-04-18 05:07:42 +04:00
2013-11-20 00:12:59 +04:00
if ( unit_name_to_type ( name ) ! = UNIT_SNAPSHOT )
return sd_bus_error_setf ( e , SD_BUS_ERROR_INVALID_ARGS , " Unit name %s lacks snapshot suffix. " , name ) ;
2010-04-18 05:07:42 +04:00
2013-11-20 00:12:59 +04:00
if ( manager_get_unit ( m , name ) )
2014-10-28 19:36:17 +03:00
return sd_bus_error_setf ( e , BUS_ERROR_UNIT_EXISTS , " Snapshot %s exists already. " , name ) ;
2010-04-18 05:07:42 +04:00
} else {
for ( ; ; ) {
if ( asprintf ( & n , " snapshot-%u.snapshot " , + + m - > n_snapshots ) < 0 )
return - ENOMEM ;
2013-08-07 05:30:34 +04:00
if ( ! manager_get_unit ( m , n ) ) {
name = n ;
2010-04-18 05:07:42 +04:00
break ;
2013-08-07 05:30:34 +04:00
}
2010-04-18 05:07:42 +04:00
free ( n ) ;
2013-07-01 02:02:03 +04:00
n = NULL ;
2010-04-18 05:07:42 +04:00
}
}
2010-07-08 04:43:18 +04:00
r = manager_load_unit_prepare ( m , name , NULL , e , & u ) ;
2010-04-18 05:07:42 +04:00
if ( r < 0 )
2010-04-21 05:27:44 +04:00
goto fail ;
2013-07-01 02:02:03 +04:00
u - > transient = true ;
2010-07-01 05:39:55 +04:00
manager_dispatch_load_queue ( m ) ;
2012-01-15 15:04:08 +04:00
assert ( u - > load_state = = UNIT_LOADED ) ;
2010-07-01 05:39:55 +04:00
2010-04-21 05:27:44 +04:00
HASHMAP_FOREACH_KEY ( other , k , m - > units , i ) {
2013-07-01 02:02:03 +04:00
if ( other - > ignore_on_snapshot | |
other - > transient )
2010-04-21 05:27:44 +04:00
continue ;
2012-01-15 15:04:08 +04:00
if ( k ! = other - > id )
2010-04-21 05:27:44 +04:00
continue ;
2010-04-21 08:01:13 +04:00
if ( UNIT_VTABLE ( other ) - > check_snapshot )
if ( ! UNIT_VTABLE ( other ) - > check_snapshot ( other ) )
continue ;
2010-04-21 05:27:44 +04:00
if ( ! UNIT_IS_ACTIVE_OR_ACTIVATING ( unit_active_state ( other ) ) )
continue ;
2013-07-01 02:02:03 +04:00
r = unit_add_two_dependencies ( u , UNIT_AFTER , UNIT_WANTS , other , true ) ;
if ( r < 0 )
2010-04-21 05:27:44 +04:00
goto fail ;
}
2010-04-18 05:07:42 +04:00
SNAPSHOT ( u ) - > cleanup = cleanup ;
* _s = SNAPSHOT ( u ) ;
2014-11-27 22:20:23 +03:00
log_unit_info ( u - > id , " Created snapshot %s. " , u - > id ) ;
2014-06-22 22:20:08 +04:00
2010-04-18 05:07:42 +04:00
return 0 ;
2010-04-21 05:27:44 +04:00
fail :
if ( u )
unit_add_to_cleanup_queue ( u ) ;
return r ;
2010-04-18 05:07:42 +04:00
}
void snapshot_remove ( Snapshot * s ) {
assert ( s ) ;
2014-11-27 22:20:23 +03:00
log_unit_info ( UNIT ( s ) - > id , " Removing snapshot %s. " , UNIT ( s ) - > id ) ;
2014-06-22 22:20:08 +04:00
2010-04-18 05:07:42 +04:00
unit_add_to_cleanup_queue ( UNIT ( s ) ) ;
2010-01-26 06:18:44 +03:00
}
2010-04-21 05:27:44 +04:00
static const char * const snapshot_state_table [ _SNAPSHOT_STATE_MAX ] = {
[ SNAPSHOT_DEAD ] = " dead " ,
[ SNAPSHOT_ACTIVE ] = " active "
} ;
DEFINE_STRING_TABLE_LOOKUP ( snapshot_state , SnapshotState ) ;
2010-01-26 23:39:06 +03:00
const UnitVTable snapshot_vtable = {
2012-01-15 13:53:49 +04:00
. object_size = sizeof ( Snapshot ) ,
2010-01-23 03:52:57 +03:00
2010-04-18 05:07:42 +04:00
. no_alias = true ,
. no_instances = true ,
2010-04-21 08:01:13 +04:00
. no_gc = true ,
2010-04-18 05:07:42 +04:00
2011-05-05 12:58:55 +04:00
. init = snapshot_init ,
2010-07-01 05:39:55 +04:00
. load = snapshot_load ,
2013-11-20 00:12:59 +04:00
2010-04-21 05:27:44 +04:00
. coldplug = snapshot_coldplug ,
2010-04-18 05:07:42 +04:00
. dump = snapshot_dump ,
. start = snapshot_start ,
. stop = snapshot_stop ,
2010-04-21 05:27:44 +04:00
. serialize = snapshot_serialize ,
. deserialize_item = snapshot_deserialize_item ,
2010-04-18 05:07:42 +04:00
. active_state = snapshot_active_state ,
. sub_state_to_string = snapshot_sub_state_to_string ,
2010-01-23 03:52:57 +03:00
2010-08-20 04:26:05 +04:00
. bus_interface = " org.freedesktop.systemd1.Snapshot " ,
2013-11-20 00:12:59 +04:00
. bus_vtable = bus_snapshot_vtable
2010-01-23 03:52:57 +03:00
} ;