2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#ifndef _LIBRESTART_H
2N/A#define _LIBRESTART_H
2N/A
2N/A#include <libsysevent.h>
2N/A#include <libcontract.h>
2N/A#include <libscf.h>
2N/A#include <limits.h>
2N/A#include <priv.h>
2N/A#include <xpol.h>
2N/A#include <pwd.h>
2N/A#include <sys/types.h>
2N/A
2N/A#ifdef __cplusplus
2N/Aextern "C" {
2N/A#endif
2N/A
2N/A/*
2N/A * There are 3 parts to librestart.
2N/A * 1) The event protocol from the master restarter to its delegates.
2N/A * 2) A functional interface for updating the repository.
2N/A * 3) Convenience functions for common restarter tasks.
2N/A *
2N/A * Event protocol
2N/A * We need a reliable event protocol, as there's no way to define
2N/A * restarter events as idempotent.
2N/A *
2N/A * Currently using sysevent channels as the reliable event implementation.
2N/A * This could change if the implementation proves unsuitable, but
2N/A * the API defined here should abstract anything but a change in
2N/A * the fundamental event model.
2N/A *
2N/A * We offer functions to tease apart the event rather than generic
2N/A * nvpair interfaces. This is because each event type has a well-
2N/A * defined set of fields.
2N/A */
2N/A
2N/A/*
2N/A * Some of the functions have external contracted consumers, review contracts
2N/A * when making incompatible changes.
2N/A */
2N/A
2N/Atypedef struct restarter_event_handle restarter_event_handle_t;
2N/Atypedef struct restarter_event restarter_event_t;
2N/A
2N/Atypedef uint32_t restarter_event_type_t;
2N/A
2N/A/*
2N/A * Define an event protocol version. In theory, we could use this in
2N/A * the future to support delegated restarters which use an older
2N/A * protocol. In practice, increment RESTARTER_EVENT_VERSION whenever the
2N/A * protocol might have changed.
2N/A */
2N/A#define RESTARTER_EVENT_VERSION 5
2N/A
2N/A#define RESTARTER_FLAG_DEBUG 1
2N/A
2N/A#define RESTARTER_ERRMSGSZ 1024
2N/A
2N/A/*
2N/A * Event types
2N/A * RESTARTER_EVENT_TYPE_ADD_INSTANCE
2N/A * responsible for a new (stopped) instance
2N/A * RESTARTER_EVENT_TYPE_REMOVE_INSTANCE
2N/A * no longer responsible for this instance; stop it and return
2N/A * RESTARTER_EVENT_TYPE_ENABLE
2N/A * no guarantee that dependencies are met; see
2N/A * RESTARTER_EVENT_TYPE_START
2N/A * RESTARTER_EVENT_TYPE_DISABLE
2N/A * no guarantee that instance was running
2N/A * RESTARTER_EVENT_TYPE_ADMIN_DEGRADED
2N/A * RESTARTER_EVENT_TYPE_ADMIN_REFRESH
2N/A * RESTARTER_EVENT_TYPE_ADMIN_RESTART
2N/A * RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF
2N/A * RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON
2N/A * RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON_IMMEDIATE
2N/A * RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF
2N/A * RESTARTER_EVENT_TYPE_STOP
2N/A * dependencies are, or are becoming, unsatisfied
2N/A * RESTARTER_EVENT_TYPE_START
2N/A * dependencies have become satisfied
2N/A * RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE
2N/A * instance caused a dependency cycle
2N/A * RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY
2N/A * instance has an invalid dependency
2N/A */
2N/A
2N/A#define RESTARTER_EVENT_TYPE_INVALID 0
2N/A#define RESTARTER_EVENT_TYPE_ADD_INSTANCE 1
2N/A#define RESTARTER_EVENT_TYPE_REMOVE_INSTANCE 2
2N/A#define RESTARTER_EVENT_TYPE_ENABLE 3
2N/A#define RESTARTER_EVENT_TYPE_DISABLE 4
2N/A#define RESTARTER_EVENT_TYPE_ADMIN_DEGRADED 5
2N/A#define RESTARTER_EVENT_TYPE_ADMIN_REFRESH 6
2N/A#define RESTARTER_EVENT_TYPE_ADMIN_RESTART 7
2N/A#define RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF 8
2N/A#define RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON 9
2N/A#define RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON_IMMEDIATE 10
2N/A#define RESTARTER_EVENT_TYPE_STOP 11
2N/A#define RESTARTER_EVENT_TYPE_START 12
2N/A#define RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE 13
2N/A#define RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY 14
2N/A#define RESTARTER_EVENT_TYPE_ADMIN_DISABLE 15
2N/A#define RESTARTER_EVENT_TYPE_STOP_RESET 16
2N/A
2N/A#define RESTARTER_EVENT_ERROR -1
2N/A
2N/A#define RESTARTER_EVENT_INSTANCE_DISABLED 0
2N/A#define RESTARTER_EVENT_INSTANCE_ENABLED 1
2N/A
2N/Atypedef enum {
2N/A RESTARTER_STATE_NONE,
2N/A RESTARTER_STATE_UNINIT,
2N/A RESTARTER_STATE_MAINT,
2N/A RESTARTER_STATE_OFFLINE,
2N/A RESTARTER_STATE_DISABLED,
2N/A RESTARTER_STATE_ONLINE,
2N/A RESTARTER_STATE_DEGRADED
2N/A} restarter_instance_state_t;
2N/A
2N/A/*
2N/A * These values are ordered by severity of required restart, as we use
2N/A * integer comparisons to determine error flow.
2N/A */
2N/Atypedef enum {
2N/A RERR_UNSUPPORTED = -1,
2N/A RERR_NONE = 0, /* no error, restart, refresh */
2N/A RERR_FAULT, /* fault occurred */
2N/A RERR_RESTART, /* transition due to restart */
2N/A RERR_REFRESH /* transition due to refresh */
2N/A} restarter_error_t;
2N/A/*
2N/A * restarter_store_contract() and restarter_remove_contract() types
2N/A */
2N/Atypedef enum {
2N/A RESTARTER_CONTRACT_PRIMARY,
2N/A RESTARTER_CONTRACT_TRANSIENT
2N/A} restarter_contract_type_t;
2N/A
2N/A/*
2N/A * restarter_bind_handle() registers a delegate with svc.startd to
2N/A * begin consuming events.
2N/A *
2N/A * On initial bind, the delgated restarter receives an event for each
2N/A * instance it is responsible for, as if that instance was new.
2N/A *
2N/A * callers must have superuser privileges
2N/A *
2N/A * The event handler can return 0 for success, or EAGAIN to request
2N/A * retry of event delivery. EAGAIN may be returned 3 times before the
2N/A * event is discarded.
2N/A */
2N/Aint restarter_bind_handle(uint32_t, const char *,
2N/A int (*event_handler)(restarter_event_t *), int,
2N/A restarter_event_handle_t **);
2N/A
2N/Arestarter_event_type_t restarter_event_get_type(restarter_event_t *);
2N/Auint64_t restarter_event_get_seq(restarter_event_t *);
2N/Avoid restarter_event_get_time(restarter_event_t *, hrtime_t *);
2N/Assize_t restarter_event_get_instance(restarter_event_t *, char *, size_t);
2N/Arestarter_event_handle_t *restarter_event_get_handle(restarter_event_t *);
2N/A
2N/A/*
2N/A * The following functions work only on certain types of events.
2N/A * They fail with a return of -1 if they're called on an inappropriate event.
2N/A */
2N/Aint restarter_event_get_enabled(restarter_event_t *);
2N/Aint restarter_event_get_current_states(restarter_event_t *,
2N/A restarter_instance_state_t *, restarter_instance_state_t *);
2N/A
2N/A/*
2N/A * State transition reasons
2N/A */
2N/A
2N/Atypedef enum {
2N/A restarter_str_none,
2N/A restarter_str_administrative_request,
2N/A restarter_str_bad_repo_state,
2N/A restarter_str_clear_request,
2N/A restarter_str_ct_ev_core,
2N/A restarter_str_ct_ev_exit,
2N/A restarter_str_ct_ev_hwerr,
2N/A restarter_str_ct_ev_signal,
2N/A restarter_str_dependencies_satisfied,
2N/A restarter_str_dependency_activity,
2N/A restarter_str_dependency_cycle,
2N/A restarter_str_disable_request,
2N/A restarter_str_enable_request,
2N/A restarter_str_fault_threshold_reached,
2N/A restarter_str_insert_in_graph,
2N/A restarter_str_invalid_dependency,
2N/A restarter_str_invalid_restarter,
2N/A restarter_str_method_failed,
2N/A restarter_str_per_configuration,
2N/A restarter_str_refresh,
2N/A restarter_str_restart_request,
2N/A restarter_str_restarting_too_quickly,
2N/A restarter_str_service_request,
2N/A restarter_str_startd_restart,
2N/A restarter_str_instance_conflict,
2N/A restarter_str_custom
2N/A} restarter_str_t;
2N/A
2N/Astruct restarter_state_transition_reason {
2N/A restarter_str_t str_key;
2N/A const char *str_short;
2N/A const char *str_long;
2N/A};
2N/A
2N/A/*
2N/A * Functions for updating the repository.
2N/A */
2N/A
2N/A/*
2N/A * When setting state to "maintenance", callers of restarter_set_states() can
2N/A * set aux_state to "service_request" to communicate that another service has
2N/A * requested maintenance state for the target service.
2N/A *
2N/A * Callers should use restarter_inst_validate_aux_fmri() to validate the fmri
2N/A * of the requested service and pass "service_request" for aux_state when
2N/A * calling restarter_set_states(). See inetd and startd for examples.
2N/A */
2N/Aint restarter_set_states(restarter_event_handle_t *, const char *,
2N/A restarter_instance_state_t, restarter_instance_state_t,
2N/A restarter_instance_state_t, restarter_instance_state_t, restarter_error_t,
2N/A restarter_str_t);
2N/Aint restarter_event_publish_retry(evchan_t *, const char *, const char *,
2N/A const char *, const char *, nvlist_t *, uint32_t);
2N/A
2N/A/*
2N/A * functions for retrieving the state transition reason messages
2N/A */
2N/A
2N/A#define RESTARTER_STRING_VERSION 2
2N/A
2N/Auint32_t restarter_str_version(void);
2N/Aconst char *restarter_get_str_short(restarter_str_t);
2N/Aconst char *restarter_get_str_long(restarter_str_t);
2N/A
2N/Aint restarter_store_contract(scf_instance_t *, ctid_t,
2N/A restarter_contract_type_t);
2N/Aint restarter_remove_contract(scf_instance_t *, ctid_t,
2N/A restarter_contract_type_t);
2N/A
2N/Assize_t restarter_state_to_string(restarter_instance_state_t, char *, size_t);
2N/Arestarter_instance_state_t restarter_string_to_state(char *);
2N/A
2N/A#define RESTARTER_METHOD_CONTEXT_VERSION 7
2N/A
2N/Astruct method_context {
2N/A /* Stable */
2N/A uid_t uid, euid;
2N/A gid_t gid, egid;
2N/A int ngroups; /* -1 means use initgroups(). */
2N/A gid_t groups[NGROUPS_MAX];
2N/A priv_set_t *lpriv_set, *priv_set;
2N/A char *corefile_pattern; /* Optional. */
2N/A char *project; /* NULL for no change */
2N/A char *resource_pool; /* NULL for project default */
2N/A char *working_dir; /* NULL for :default */
2N/A char **env; /* NULL for no env */
2N/A size_t env_sz; /* size of env array */
2N/A xpol_ctxt_t *xpctxt; /* Xpol context */
2N/A
2N/A /* Private */
2N/A char *vbuf;
2N/A ssize_t vbuf_sz;
2N/A struct passwd pwd;
2N/A char *pwbuf;
2N/A ssize_t pwbufsz;
2N/A};
2N/A
2N/A/*
2N/A * An error structure that contains a message string, and a type
2N/A * that can be used to determine course of action by the reciever
2N/A * of the error structure.
2N/A *
2N/A * type - usually will be an errno equivalent but could contain
2N/A * defined error types for exampe SCF_ERROR_XXX
2N/A * msg - must be at the end of the structure as if the message is
2N/A * longer than EMSGSIZE we will reallocate the structure to
2N/A * handle the overflow
2N/A */
2N/Atypedef struct mc_error {
2N/A int destroy; /* Flag to indicate destruction steps */
2N/A int type; /* Type of error for decision making */
2N/A int size; /* The size of the error message string */
2N/A char msg[RESTARTER_ERRMSGSZ];
2N/A} mc_error_t;
2N/A
2N/Aint restarter_rm_libs_loadable(void);
2N/A/* instance, restarter name, method name, command line, structure pointer */
2N/Amc_error_t *restarter_get_method_context(uint_t, scf_instance_t *,
2N/A scf_snapshot_t *, const char *, const char *, struct method_context **);
2N/Avoid restarter_mc_error_destroy(mc_error_t *);
2N/Aint restarter_set_method_context(struct method_context *, const char **);
2N/Avoid restarter_free_method_context(struct method_context *);
2N/A
2N/A
2N/Aint restarter_is_null_method(const char *);
2N/Aint restarter_is_kill_method(const char *);
2N/Aint restarter_is_kill_proc_method(const char *);
2N/A
2N/A/* Validate the inst fmri specified in restarter_actions/auxiliary_fmri */
2N/Aint restarter_inst_validate_ractions_aux_fmri(scf_instance_t *);
2N/A
2N/A/* Delete instance's restarter_actions/auxiliary_fmri property */
2N/Aint restarter_inst_reset_ractions_aux_fmri(scf_instance_t *);
2N/A
2N/A/* Get boolean value from instance's restarter_actions/auxiliary_tty */
2N/Aint restarter_inst_ractions_from_tty(scf_instance_t *);
2N/A
2N/A/* Delete instance's restarter/auxiliary_fmri property */
2N/Aint restarter_inst_reset_aux_fmri(scf_instance_t *);
2N/A
2N/A/*
2N/A * Set instance's restarter/auxiliary_fmri, value come from
2N/A * restarter_actions/auxliary_fmri
2N/A */
2N/Aint restarter_inst_set_aux_fmri(scf_instance_t *);
2N/A
2N/A#ifdef __cplusplus
2N/A}
2N/A#endif
2N/A
2N/A#endif /* _LIBRESTART_H */