Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #ifndef	_LIBRESTART_H
     27 #define	_LIBRESTART_H
     28 
     29 #include <libsysevent.h>
     30 #include <libcontract.h>
     31 #include <libscf.h>
     32 #include <limits.h>
     33 #include <priv.h>
     34 #include <pwd.h>
     35 #include <sys/types.h>
     36 
     37 #ifdef	__cplusplus
     38 extern "C" {
     39 #endif
     40 
     41 /*
     42  * There are 3 parts to librestart.
     43  *	1) The event protocol from the master restarter to its delegates.
     44  *	2) A functional interface for updating the repository.
     45  *	3) Convenience functions for common restarter tasks.
     46  *
     47  * Event protocol
     48  *	We need a reliable event protocol, as there's no way to define
     49  *	restarter events as idempotent.
     50  *
     51  *	Currently using sysevent channels as the reliable event implementation.
     52  *	This could change if the implementation proves unsuitable, but
     53  *	the API defined here should abstract anything but a change in
     54  *	the fundamental event model.
     55  *
     56  *	We offer functions to tease apart the event rather than generic
     57  *	nvpair interfaces. This is because each event type has a well-
     58  *	defined set of fields.
     59  */
     60 
     61 /*
     62  * Some of the functions have external contracted consumers, review contracts
     63  * when making incompatible changes.
     64  */
     65 
     66 typedef struct restarter_event_handle restarter_event_handle_t;
     67 typedef struct restarter_event restarter_event_t;
     68 
     69 typedef uint32_t restarter_event_type_t;
     70 
     71 /*
     72  * Define an event protocol version. In theory, we could use this in
     73  * the future to support delegated restarters which use an older
     74  * protocol. In practice, increment RESTARTER_EVENT_VERSION whenever the
     75  * protocol might have changed.
     76  */
     77 #define	RESTARTER_EVENT_VERSION		4
     78 
     79 #define	RESTARTER_FLAG_DEBUG		1
     80 
     81 #define	RESTARTER_ERRMSGSZ		1024
     82 
     83 /*
     84  * Event types
     85  *	RESTARTER_EVENT_TYPE_ADD_INSTANCE
     86  *		responsible for a new (stopped) instance
     87  *	RESTARTER_EVENT_TYPE_REMOVE_INSTANCE
     88  *		no longer responsible for this instance; stop it and return
     89  *	RESTARTER_EVENT_TYPE_ENABLE
     90  *		no guarantee that dependencies are met; see
     91  *		RESTARTER_EVENT_TYPE_START
     92  *	RESTARTER_EVENT_TYPE_DISABLE
     93  *		no guarantee that instance was running
     94  *	RESTARTER_EVENT_TYPE_ADMIN_DEGRADED
     95  *	RESTARTER_EVENT_TYPE_ADMIN_REFRESH
     96  *	RESTARTER_EVENT_TYPE_ADMIN_RESTART
     97  *	RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF
     98  *	RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON
     99  *	RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON_IMMEDIATE
    100  *	RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF
    101  *	RESTARTER_EVENT_TYPE_STOP
    102  *		dependencies are, or are becoming, unsatisfied
    103  *	RESTARTER_EVENT_TYPE_START
    104  *		dependencies have become satisfied
    105  *	RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE
    106  *		instance caused a dependency cycle
    107  *	RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY
    108  *		instance has an invalid dependency
    109  */
    110 
    111 #define	RESTARTER_EVENT_TYPE_INVALID			0
    112 #define	RESTARTER_EVENT_TYPE_ADD_INSTANCE		1
    113 #define	RESTARTER_EVENT_TYPE_REMOVE_INSTANCE		2
    114 #define	RESTARTER_EVENT_TYPE_ENABLE			3
    115 #define	RESTARTER_EVENT_TYPE_DISABLE			4
    116 #define	RESTARTER_EVENT_TYPE_ADMIN_DEGRADED		5
    117 #define	RESTARTER_EVENT_TYPE_ADMIN_REFRESH		6
    118 #define	RESTARTER_EVENT_TYPE_ADMIN_RESTART		7
    119 #define	RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF		8
    120 #define	RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON		9
    121 #define	RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON_IMMEDIATE	10
    122 #define	RESTARTER_EVENT_TYPE_STOP			11
    123 #define	RESTARTER_EVENT_TYPE_START			12
    124 #define	RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE		13
    125 #define	RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY		14
    126 #define	RESTARTER_EVENT_TYPE_ADMIN_DISABLE		15
    127 #define	RESTARTER_EVENT_TYPE_STOP_RESET			16
    128 
    129 #define	RESTARTER_EVENT_ERROR			-1
    130 
    131 #define	RESTARTER_EVENT_INSTANCE_DISABLED	0
    132 #define	RESTARTER_EVENT_INSTANCE_ENABLED	1
    133 
    134 typedef enum {
    135 	RESTARTER_STATE_NONE,
    136 	RESTARTER_STATE_UNINIT,
    137 	RESTARTER_STATE_MAINT,
    138 	RESTARTER_STATE_OFFLINE,
    139 	RESTARTER_STATE_DISABLED,
    140 	RESTARTER_STATE_ONLINE,
    141 	RESTARTER_STATE_DEGRADED
    142 } restarter_instance_state_t;
    143 
    144 /*
    145  * These values are ordered by severity of required restart, as we use
    146  * integer comparisons to determine error flow.
    147  */
    148 typedef enum {
    149 	RERR_UNSUPPORTED = -1,
    150 	RERR_NONE = 0,			/* no error, restart, refresh */
    151 	RERR_FAULT,			/* fault occurred */
    152 	RERR_RESTART,			/* transition due to restart */
    153 	RERR_REFRESH			/* transition due to refresh */
    154 } restarter_error_t;
    155 /*
    156  * restarter_store_contract() and restarter_remove_contract() types
    157  */
    158 typedef enum {
    159 	RESTARTER_CONTRACT_PRIMARY,
    160 	RESTARTER_CONTRACT_TRANSIENT
    161 } restarter_contract_type_t;
    162 
    163 /*
    164  * restarter_bind_handle() registers a delegate with svc.startd to
    165  * begin consuming events.
    166  *
    167  * On initial bind, the delgated restarter receives an event for each
    168  * instance it is responsible for, as if that instance was new.
    169  *
    170  * callers must have superuser privileges
    171  *
    172  * The event handler can return 0 for success, or EAGAIN to request
    173  * retry of event delivery. EAGAIN may be returned 3 times before the
    174  * event is discarded.
    175  */
    176 int restarter_bind_handle(uint32_t, const char *,
    177     int (*event_handler)(restarter_event_t *), int,
    178     restarter_event_handle_t **);
    179 
    180 restarter_event_type_t restarter_event_get_type(restarter_event_t *);
    181 uint64_t restarter_event_get_seq(restarter_event_t *);
    182 void restarter_event_get_time(restarter_event_t *, hrtime_t *);
    183 ssize_t restarter_event_get_instance(restarter_event_t *, char *, size_t);
    184 restarter_event_handle_t *restarter_event_get_handle(restarter_event_t *);
    185 
    186 /*
    187  * The following functions work only on certain types of events.
    188  * They fail with a return of -1 if they're called on an inappropriate event.
    189  */
    190 int restarter_event_get_enabled(restarter_event_t *);
    191 int restarter_event_get_current_states(restarter_event_t *,
    192     restarter_instance_state_t *, restarter_instance_state_t *);
    193 
    194 /*
    195  * Functions for updating the repository.
    196  */
    197 
    198 /*
    199  * When setting state to "maintenance", callers of restarter_set_states() can
    200  * set aux_state to "service_request" to communicate that another service has
    201  * requested maintenance state for the target service.
    202  *
    203  * Callers should use restarter_inst_validate_aux_fmri() to validate the fmri
    204  * of the requested service and pass "service_request" for aux_state when
    205  * calling restarter_set_states(). See inetd and startd for examples.
    206  */
    207 int restarter_set_states(restarter_event_handle_t *, const char *,
    208     restarter_instance_state_t, restarter_instance_state_t,
    209     restarter_instance_state_t, restarter_instance_state_t, restarter_error_t,
    210     const char *);
    211 int restarter_event_publish_retry(evchan_t *, const char *, const char *,
    212     const char *, const char *, nvlist_t *, uint32_t);
    213 
    214 int restarter_store_contract(scf_instance_t *, ctid_t,
    215     restarter_contract_type_t);
    216 int restarter_remove_contract(scf_instance_t *, ctid_t,
    217     restarter_contract_type_t);
    218 
    219 ssize_t restarter_state_to_string(restarter_instance_state_t, char *, size_t);
    220 restarter_instance_state_t restarter_string_to_state(char *);
    221 
    222 #define	RESTARTER_METHOD_CONTEXT_VERSION	7
    223 
    224 struct method_context {
    225 	/* Stable */
    226 	uid_t		uid, euid;
    227 	gid_t		gid, egid;
    228 	int		ngroups;		/* -1 means use initgroups(). */
    229 	gid_t		groups[NGROUPS_MAX];
    230 	priv_set_t	*lpriv_set, *priv_set;
    231 	char		*corefile_pattern;	/* Optional. */
    232 	char		*project;		/* NULL for no change */
    233 	char		*resource_pool;		/* NULL for project default */
    234 	char		*working_dir;		/* NULL for :default */
    235 	char		**env;			/* NULL for no env */
    236 	size_t		env_sz;			/* size of env array */
    237 
    238 	/* Private */
    239 	char		*vbuf;
    240 	ssize_t		vbuf_sz;
    241 	struct passwd	pwd;
    242 	char		*pwbuf;
    243 	ssize_t		pwbufsz;
    244 };
    245 
    246 /*
    247  * An error structure that contains a message string, and a type
    248  * that can be used to determine course of action by the reciever
    249  * of the error structure.
    250  *
    251  * type - usually will be an errno equivalent but could contain
    252  * 	defined error types for exampe SCF_ERROR_XXX
    253  * msg - must be at the end of the structure as if the message is
    254  * 	longer than EMSGSIZE we will reallocate the structure to
    255  * 	handle the overflow
    256  */
    257 typedef struct mc_error {
    258 	int	destroy;	/* Flag to indicate destruction steps */
    259 	int	type;		/* Type of error for decision making */
    260 	int	size;		/* The size of the error message string */
    261 	char 	msg[RESTARTER_ERRMSGSZ];
    262 } mc_error_t;
    263 
    264 int restarter_rm_libs_loadable(void);
    265 /* instance, restarter name, method name, command line, structure pointer */
    266 mc_error_t *restarter_get_method_context(uint_t, scf_instance_t *,
    267     scf_snapshot_t *, const char *, const char *, struct method_context **);
    268 void restarter_mc_error_destroy(mc_error_t *);
    269 int restarter_set_method_context(struct method_context *, const char **);
    270 void restarter_free_method_context(struct method_context *);
    271 
    272 
    273 int restarter_is_null_method(const char *);
    274 int restarter_is_kill_method(const char *);
    275 int restarter_is_kill_proc_method(const char *);
    276 
    277 /* Validate the inst fmri specified in  restarter_actions/auxiliary_fmri */
    278 int restarter_inst_validate_ractions_aux_fmri(scf_instance_t *);
    279 
    280 /* Delete instance's restarter_actions/auxiliary_fmri property */
    281 int restarter_inst_reset_ractions_aux_fmri(scf_instance_t *);
    282 
    283 /* Get boolean value from instance's restarter_actions/auxiliary_tty */
    284 int restarter_inst_ractions_from_tty(scf_instance_t *);
    285 
    286 /* Delete instance's restarter/auxiliary_fmri property */
    287 int restarter_inst_reset_aux_fmri(scf_instance_t *);
    288 
    289 /*
    290  * Set instance's restarter/auxiliary_fmri, value come from
    291  * restarter_actions/auxliary_fmri
    292  */
    293 int restarter_inst_set_aux_fmri(scf_instance_t *);
    294 
    295 #ifdef	__cplusplus
    296 }
    297 #endif
    298 
    299 #endif	/* _LIBRESTART_H */
    300