xref: /illumos-gate/usr/src/lib/librestart/common/librestart.h (revision 93a18d6d401e844455263f926578e9d2aa6b47ec)
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