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.
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.
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]
22 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
28 #include <libsysevent.h>
29 #include <libcontract.h>
34 #include <sys/types.h>
35 #include <sys/secflags.h>
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.
48 * We need a reliable event protocol, as there's no way to define
49 * restarter events as idempotent.
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.
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.
62 * Some of the functions have external contracted consumers, review contracts
63 * when making incompatible changes.
66 typedef struct restarter_event_handle restarter_event_handle_t
;
67 typedef struct restarter_event restarter_event_t
;
69 typedef uint32_t restarter_event_type_t
;
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.
77 #define RESTARTER_EVENT_VERSION 5
79 #define RESTARTER_FLAG_DEBUG 1
81 #define RESTARTER_ERRMSGSZ 1024
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
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
129 #define RESTARTER_EVENT_ERROR -1
131 #define RESTARTER_EVENT_INSTANCE_DISABLED 0
132 #define RESTARTER_EVENT_INSTANCE_ENABLED 1
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
;
145 * These values are ordered by severity of required restart, as we use
146 * integer comparisons to determine error flow.
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 */
156 * restarter_store_contract() and restarter_remove_contract() types
159 RESTARTER_CONTRACT_PRIMARY
,
160 RESTARTER_CONTRACT_TRANSIENT
161 } restarter_contract_type_t
;
164 * restarter_bind_handle() registers a delegate with svc.startd to
165 * begin consuming events.
167 * On initial bind, the delgated restarter receives an event for each
168 * instance it is responsible for, as if that instance was new.
170 * callers must have superuser privileges
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.
176 int restarter_bind_handle(uint32_t, const char *,
177 int (*event_handler
)(restarter_event_t
*), int,
178 restarter_event_handle_t
**);
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
*);
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.
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
*);
195 * State transition reasons
200 restarter_str_administrative_request
,
201 restarter_str_bad_repo_state
,
202 restarter_str_clear_request
,
203 restarter_str_ct_ev_core
,
204 restarter_str_ct_ev_exit
,
205 restarter_str_ct_ev_hwerr
,
206 restarter_str_ct_ev_signal
,
207 restarter_str_dependencies_satisfied
,
208 restarter_str_dependency_activity
,
209 restarter_str_dependency_cycle
,
210 restarter_str_disable_request
,
211 restarter_str_enable_request
,
212 restarter_str_fault_threshold_reached
,
213 restarter_str_insert_in_graph
,
214 restarter_str_invalid_dependency
,
215 restarter_str_invalid_restarter
,
216 restarter_str_method_failed
,
217 restarter_str_per_configuration
,
218 restarter_str_refresh
,
219 restarter_str_restart_request
,
220 restarter_str_restarting_too_quickly
,
221 restarter_str_service_request
,
222 restarter_str_startd_restart
225 struct restarter_state_transition_reason
{
226 restarter_str_t str_key
;
227 const char *str_short
;
228 const char *str_long
;
232 * Functions for updating the repository.
236 * When setting state to "maintenance", callers of restarter_set_states() can
237 * set aux_state to "service_request" to communicate that another service has
238 * requested maintenance state for the target service.
240 * Callers should use restarter_inst_validate_aux_fmri() to validate the fmri
241 * of the requested service and pass "service_request" for aux_state when
242 * calling restarter_set_states(). See inetd and startd for examples.
244 int restarter_set_states(restarter_event_handle_t
*, const char *,
245 restarter_instance_state_t
, restarter_instance_state_t
,
246 restarter_instance_state_t
, restarter_instance_state_t
, restarter_error_t
,
248 int restarter_event_publish_retry(evchan_t
*, const char *, const char *,
249 const char *, const char *, nvlist_t
*, uint32_t);
252 * functions for retrieving the state transition reason messages
255 #define RESTARTER_STRING_VERSION 1
257 uint32_t restarter_str_version(void);
258 const char *restarter_get_str_short(restarter_str_t
);
259 const char *restarter_get_str_long(restarter_str_t
);
261 int restarter_store_contract(scf_instance_t
*, ctid_t
,
262 restarter_contract_type_t
);
263 int restarter_remove_contract(scf_instance_t
*, ctid_t
,
264 restarter_contract_type_t
);
266 ssize_t
restarter_state_to_string(restarter_instance_state_t
, char *, size_t);
267 restarter_instance_state_t
restarter_string_to_state(char *);
269 #define RESTARTER_METHOD_CONTEXT_VERSION 8
271 struct method_context
{
275 int ngroups
; /* -1 means use initgroups(). */
276 gid_t groups
[NGROUPS_MAX
];
277 scf_secflags_t def_secflags
;
278 secflagdelta_t secflag_delta
;
279 priv_set_t
*lpriv_set
, *priv_set
;
280 char *corefile_pattern
; /* Optional. */
281 char *project
; /* NULL for no change */
282 char *resource_pool
; /* NULL for project default */
283 char *working_dir
; /* NULL for :default */
284 char **env
; /* NULL for no env */
285 size_t env_sz
; /* size of env array */
296 * An error structure that contains a message string, and a type
297 * that can be used to determine course of action by the reciever
298 * of the error structure.
300 * type - usually will be an errno equivalent but could contain
301 * defined error types for exampe SCF_ERROR_XXX
302 * msg - must be at the end of the structure as if the message is
303 * longer than EMSGSIZE we will reallocate the structure to
304 * handle the overflow
306 typedef struct mc_error
{
307 int destroy
; /* Flag to indicate destruction steps */
308 int type
; /* Type of error for decision making */
309 int size
; /* The size of the error message string */
310 char msg
[RESTARTER_ERRMSGSZ
];
313 int restarter_rm_libs_loadable(void);
314 /* instance, restarter name, method name, command line, structure pointer */
315 mc_error_t
*restarter_get_method_context(uint_t
, scf_instance_t
*,
316 scf_snapshot_t
*, const char *, const char *, struct method_context
**);
317 void restarter_mc_error_destroy(mc_error_t
*);
318 int restarter_set_method_context(struct method_context
*, const char **);
319 void restarter_free_method_context(struct method_context
*);
322 int restarter_is_null_method(const char *);
323 int restarter_is_kill_method(const char *);
324 int restarter_is_kill_proc_method(const char *);
326 /* Validate the inst fmri specified in restarter_actions/auxiliary_fmri */
327 int restarter_inst_validate_ractions_aux_fmri(scf_instance_t
*);
329 /* Delete instance's restarter_actions/auxiliary_fmri property */
330 int restarter_inst_reset_ractions_aux_fmri(scf_instance_t
*);
332 /* Get boolean value from instance's restarter_actions/auxiliary_tty */
333 int restarter_inst_ractions_from_tty(scf_instance_t
*);
335 /* Delete instance's restarter/auxiliary_fmri property */
336 int restarter_inst_reset_aux_fmri(scf_instance_t
*);
338 /* Get boolean value from instance's restarter_actions/do_dump */
339 int restarter_inst_dump(scf_instance_t
*);
342 * Set instance's restarter/auxiliary_fmri, value come from
343 * restarter_actions/auxliary_fmri
345 int restarter_inst_set_aux_fmri(scf_instance_t
*);
351 #endif /* _LIBRESTART_H */