xref: /titanic_41/usr/src/lib/librestart/common/librestart.h (revision 20ae46ebaff1237662e05edf9db61538aa85d448)
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 2008 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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
30 
31 #include <libsysevent.h>
32 #include <libcontract.h>
33 #include <libscf.h>
34 #include <limits.h>
35 #include <priv.h>
36 #include <pwd.h>
37 #include <sys/types.h>
38 
39 #ifdef	__cplusplus
40 extern "C" {
41 #endif
42 
43 /*
44  * There are 3 parts to librestart.
45  *	1) The event protocol from the master restarter to its delegates.
46  *	2) A functional interface for updating the repository.
47  *	3) Convenience functions for common restarter tasks.
48  *
49  * Event protocol
50  *	We need a reliable event protocol, as there's no way to define
51  *	restarter events as idempotent.
52  *
53  *	Currently using sysevent channels as the reliable event implementation.
54  *	This could change if the implementation proves unsuitable, but
55  *	the API defined here should abstract anything but a change in
56  *	the fundamental event model.
57  *
58  *	We offer functions to tease apart the event rather than generic
59  *	nvpair interfaces. This is because each event type has a well-
60  *	defined set of fields.
61  */
62 
63 typedef struct restarter_event_handle restarter_event_handle_t;
64 typedef struct restarter_event restarter_event_t;
65 
66 typedef uint32_t restarter_event_type_t;
67 
68 /*
69  * Define an event protocol version. In theory, we could use this in
70  * the future to support delegated restarters which use an older
71  * protocol. In practice, increment RESTARTER_EVENT_VERSION whenever the
72  * protocol might have changed.
73  */
74 #define	RESTARTER_EVENT_VERSION		4
75 
76 #define	RESTARTER_FLAG_DEBUG		1
77 
78 /*
79  * Event types
80  *	RESTARTER_EVENT_TYPE_ADD_INSTANCE
81  *		responsible for a new (stopped) instance
82  *	RESTARTER_EVENT_TYPE_REMOVE_INSTANCE
83  *		no longer responsible for this instance; stop it and return
84  *	RESTARTER_EVENT_TYPE_ENABLE
85  *		no guarantee that dependencies are met; see
86  *		RESTARTER_EVENT_TYPE_START
87  *	RESTARTER_EVENT_TYPE_DISABLE
88  *		no guarantee that instance was running
89  *	RESTARTER_EVENT_TYPE_ADMIN_DEGRADED
90  *	RESTARTER_EVENT_TYPE_ADMIN_REFRESH
91  *	RESTARTER_EVENT_TYPE_ADMIN_RESTART
92  *	RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF
93  *	RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON
94  *	RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON_IMMEDIATE
95  *	RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF
96  *	RESTARTER_EVENT_TYPE_STOP
97  *		dependencies are, or are becoming, unsatisfied
98  *	RESTARTER_EVENT_TYPE_START
99  *		dependencies have become satisfied
100  *	RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE
101  *		instance caused a dependency cycle
102  *	RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY
103  *		instance has an invalid dependency
104  */
105 
106 #define	RESTARTER_EVENT_TYPE_INVALID			0
107 #define	RESTARTER_EVENT_TYPE_ADD_INSTANCE		1
108 #define	RESTARTER_EVENT_TYPE_REMOVE_INSTANCE		2
109 #define	RESTARTER_EVENT_TYPE_ENABLE			3
110 #define	RESTARTER_EVENT_TYPE_DISABLE			4
111 #define	RESTARTER_EVENT_TYPE_ADMIN_DEGRADED		5
112 #define	RESTARTER_EVENT_TYPE_ADMIN_REFRESH		6
113 #define	RESTARTER_EVENT_TYPE_ADMIN_RESTART		7
114 #define	RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF		8
115 #define	RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON		9
116 #define	RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON_IMMEDIATE	10
117 #define	RESTARTER_EVENT_TYPE_STOP			11
118 #define	RESTARTER_EVENT_TYPE_START			12
119 #define	RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE		13
120 #define	RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY		14
121 #define	RESTARTER_EVENT_TYPE_ADMIN_DISABLE		15
122 
123 #define	RESTARTER_EVENT_ERROR			-1
124 
125 #define	RESTARTER_EVENT_INSTANCE_DISABLED	0
126 #define	RESTARTER_EVENT_INSTANCE_ENABLED	1
127 
128 typedef enum {
129 	RESTARTER_STATE_NONE,
130 	RESTARTER_STATE_UNINIT,
131 	RESTARTER_STATE_MAINT,
132 	RESTARTER_STATE_OFFLINE,
133 	RESTARTER_STATE_DISABLED,
134 	RESTARTER_STATE_ONLINE,
135 	RESTARTER_STATE_DEGRADED
136 } restarter_instance_state_t;
137 
138 /*
139  * These values are ordered by severity of required restart, as we use
140  * integer comparisons to determine error flow.
141  */
142 typedef enum {
143 	RERR_UNSUPPORTED = -1,
144 	RERR_NONE = 0,			/* no error, restart, refresh */
145 	RERR_FAULT,			/* fault occurred */
146 	RERR_RESTART,			/* transition due to restart */
147 	RERR_REFRESH			/* transition due to refresh */
148 } restarter_error_t;
149 
150 /*
151  * restarter_store_contract() and restarter_remove_contract() types
152  */
153 typedef enum {
154 	RESTARTER_CONTRACT_PRIMARY,
155 	RESTARTER_CONTRACT_TRANSIENT
156 } restarter_contract_type_t;
157 
158 /*
159  * restarter_bind_handle() registers a delegate with svc.startd to
160  * begin consuming events.
161  *
162  * On initial bind, the delgated restarter receives an event for each
163  * instance it is responsible for, as if that instance was new.
164  *
165  * callers must have superuser privileges
166  *
167  * The event handler can return 0 for success, or EAGAIN to request
168  * retry of event delivery. EAGAIN may be returned 3 times before the
169  * event is discarded.
170  */
171 int restarter_bind_handle(uint32_t, const char *,
172     int (*event_handler)(restarter_event_t *), int,
173     restarter_event_handle_t **);
174 
175 restarter_event_type_t restarter_event_get_type(restarter_event_t *);
176 uint64_t restarter_event_get_seq(restarter_event_t *);
177 void restarter_event_get_time(restarter_event_t *, hrtime_t *);
178 ssize_t restarter_event_get_instance(restarter_event_t *, char *, size_t);
179 restarter_event_handle_t *restarter_event_get_handle(restarter_event_t *);
180 
181 /*
182  * The following functions work only on certain types of events.
183  * They fail with a return of -1 if they're called on an inappropriate event.
184  */
185 int restarter_event_get_enabled(restarter_event_t *);
186 int restarter_event_get_current_states(restarter_event_t *,
187     restarter_instance_state_t *, restarter_instance_state_t *);
188 
189 /*
190  * Functions for updating the repository.
191  */
192 int restarter_set_states(restarter_event_handle_t *, const char *,
193     restarter_instance_state_t, restarter_instance_state_t,
194     restarter_instance_state_t, restarter_instance_state_t, restarter_error_t,
195     const char *);
196 int restarter_event_publish_retry(evchan_t *, const char *, const char *,
197     const char *, const char *, nvlist_t *, uint32_t);
198 
199 int restarter_store_contract(scf_instance_t *, ctid_t,
200     restarter_contract_type_t);
201 int restarter_remove_contract(scf_instance_t *, ctid_t,
202     restarter_contract_type_t);
203 
204 ssize_t restarter_state_to_string(restarter_instance_state_t, char *, size_t);
205 restarter_instance_state_t restarter_string_to_state(char *);
206 
207 #define	RESTARTER_METHOD_CONTEXT_VERSION	6
208 
209 struct method_context {
210 	/* Stable */
211 	uid_t		uid, euid;
212 	gid_t		gid, egid;
213 	int		ngroups;		/* -1 means use initgroups(). */
214 	gid_t		groups[NGROUPS_MAX-1];
215 	priv_set_t	*lpriv_set, *priv_set;
216 	char		*corefile_pattern;	/* Optional. */
217 	char		*project;		/* NULL for no change */
218 	char		*resource_pool;		/* NULL for project default */
219 	char		*working_dir;		/* NULL for :default */
220 	char		**env;			/* NULL for no env */
221 	size_t		env_sz;			/* size of env array */
222 
223 	/* Private */
224 	char		*vbuf;
225 	ssize_t		vbuf_sz;
226 	struct passwd	pwd;
227 	char		*pwbuf;
228 	ssize_t		pwbufsz;
229 };
230 
231 int restarter_rm_libs_loadable(void);
232 /* instance, restarter name, method name, command line, structure pointer */
233 const char *restarter_get_method_context(uint_t, scf_instance_t *,
234     scf_snapshot_t *, const char *, const char *, struct method_context **);
235 int restarter_set_method_context(struct method_context *, const char **);
236 void restarter_free_method_context(struct method_context *);
237 
238 
239 int restarter_is_null_method(const char *);
240 int restarter_is_kill_method(const char *);
241 int restarter_is_kill_proc_method(const char *);
242 
243 #ifdef	__cplusplus
244 }
245 #endif
246 
247 #endif	/* _LIBRESTART_H */
248