99b44c3bba5a515aba1e56c2104f53af320a848dlianep/*
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * CDDL HEADER START
99b44c3bba5a515aba1e56c2104f53af320a848dlianep *
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * The contents of this file are subject to the terms of the
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * Common Development and Distribution License (the "License").
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * You may not use this file except in compliance with the License.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep *
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * or http://www.opensolaris.org/os/licensing.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * See the License for the specific language governing permissions
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * and limitations under the License.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep *
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * When distributing Covered Code, include this CDDL HEADER in each
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * If applicable, add the following below this CDDL HEADER, with the
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * fields enclosed by brackets "[]" replaced with your own identifying
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * information: Portions Copyright [yyyy] [name of copyright owner]
99b44c3bba5a515aba1e56c2104f53af320a848dlianep *
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * CDDL HEADER END
99b44c3bba5a515aba1e56c2104f53af320a848dlianep */
99b44c3bba5a515aba1e56c2104f53af320a848dlianep/*
845e9415a97ec0124f099537b21fc0364883850fRenaud Manus * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * Use is subject to license terms.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep */
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep/*
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * transition.c - Graph State Machine
99b44c3bba5a515aba1e56c2104f53af320a848dlianep *
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * The graph state machine is implemented here, with a typical approach
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * of a function per state. Separating the implementation allows more
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * clarity into the actions taken on notification of state change, as well
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * as a place for future expansion including hooks for configurable actions.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * All functions are called with dgraph_lock held.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep *
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * The start action for this state machine is not explicit. The states
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos * (ONLINE and DEGRADED) which need to know when they're entering the state
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * due to a daemon restart implement this understanding by checking for
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * transition from uninitialized. In the future, this would likely be better
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * as an explicit start action instead of relying on an overloaded transition.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep *
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * All gt_enter functions use the same set of return codes.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * 0 success
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * ECONNABORTED repository connection aborted
99b44c3bba5a515aba1e56c2104f53af320a848dlianep */
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep#include "startd.h"
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianepstatic int
99b44c3bba5a515aba1e56c2104f53af320a848dlianepgt_running(restarter_instance_state_t state)
99b44c3bba5a515aba1e56c2104f53af320a848dlianep{
99b44c3bba5a515aba1e56c2104f53af320a848dlianep if (state == RESTARTER_STATE_ONLINE ||
99b44c3bba5a515aba1e56c2104f53af320a848dlianep state == RESTARTER_STATE_DEGRADED)
99b44c3bba5a515aba1e56c2104f53af320a848dlianep return (1);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep return (0);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep}
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianepstatic int
99b44c3bba5a515aba1e56c2104f53af320a848dlianepgt_enter_uninit(scf_handle_t *h, graph_vertex_t *v,
99b44c3bba5a515aba1e56c2104f53af320a848dlianep restarter_instance_state_t old_state, restarter_error_t rerr)
99b44c3bba5a515aba1e56c2104f53af320a848dlianep{
99b44c3bba5a515aba1e56c2104f53af320a848dlianep int err;
99b44c3bba5a515aba1e56c2104f53af320a848dlianep scf_instance_t *inst;
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep /* Initialize instance by refreshing it. */
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep err = libscf_fmri_get_instance(h, v->gv_name, &inst);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep switch (err) {
99b44c3bba5a515aba1e56c2104f53af320a848dlianep case 0:
99b44c3bba5a515aba1e56c2104f53af320a848dlianep break;
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep case ECONNABORTED:
99b44c3bba5a515aba1e56c2104f53af320a848dlianep return (ECONNABORTED);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep case ENOENT:
99b44c3bba5a515aba1e56c2104f53af320a848dlianep return (0);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep case EINVAL:
99b44c3bba5a515aba1e56c2104f53af320a848dlianep case ENOTSUP:
99b44c3bba5a515aba1e56c2104f53af320a848dlianep default:
99b44c3bba5a515aba1e56c2104f53af320a848dlianep bad_error("libscf_fmri_get_instance", err);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep }
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep err = refresh_vertex(v, inst);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep if (err == 0)
99b44c3bba5a515aba1e56c2104f53af320a848dlianep graph_enable_by_vertex(v, v->gv_flags & GV_ENABLED, 0);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep scf_instance_destroy(inst);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep /* If the service was running, propagate a stop event. */
99b44c3bba5a515aba1e56c2104f53af320a848dlianep if (gt_running(old_state)) {
99b44c3bba5a515aba1e56c2104f53af320a848dlianep log_framework(LOG_DEBUG, "Propagating stop of %s.\n",
99b44c3bba5a515aba1e56c2104f53af320a848dlianep v->gv_name);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep graph_transition_propagate(v, PROPAGATE_STOP, rerr);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep }
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep graph_transition_sulogin(RESTARTER_STATE_UNINIT, old_state);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep return (0);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep}
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos/* ARGSUSED */
99b44c3bba5a515aba1e56c2104f53af320a848dlianepstatic int
99b44c3bba5a515aba1e56c2104f53af320a848dlianepgt_enter_maint(scf_handle_t *h, graph_vertex_t *v,
99b44c3bba5a515aba1e56c2104f53af320a848dlianep restarter_instance_state_t old_state, restarter_error_t rerr)
99b44c3bba5a515aba1e56c2104f53af320a848dlianep{
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus int to_offline = v->gv_flags & GV_TOOFFLINE;
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep /*
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep * If the service was running, propagate a stop event. If the
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep * service was not running the maintenance transition may satisfy
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep * optional dependencies and should be propagated to determine
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep * whether new dependents are satisfiable.
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus * Instances that transition to maintenance and have the GV_TOOFFLINE
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus * flag are special because they can expose new subtree leaves so
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus * propagate the offline to the instance dependencies.
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep */
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus /* instance transitioning to maintenance is considered disabled */
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus v->gv_flags &= ~GV_TODISABLE;
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus v->gv_flags &= ~GV_TOOFFLINE;
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus
99b44c3bba5a515aba1e56c2104f53af320a848dlianep if (gt_running(old_state)) {
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus /*
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus * Handle state change during instance disabling.
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus * Propagate offline to the new exposed leaves.
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus */
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus if (to_offline) {
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus log_framework(LOG_DEBUG, "%s removed from subtree\n",
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus v->gv_name);
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus graph_offline_subtree_leaves(v, (void *)h);
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus }
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep log_framework(LOG_DEBUG, "Propagating maintenance (stop) of "
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep "%s.\n", v->gv_name);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep graph_transition_propagate(v, PROPAGATE_STOP, rerr);
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep } else {
99b44c3bba5a515aba1e56c2104f53af320a848dlianep log_framework(LOG_DEBUG, "Propagating maintenance of %s.\n",
99b44c3bba5a515aba1e56c2104f53af320a848dlianep v->gv_name);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep graph_transition_propagate(v, PROPAGATE_SAT, rerr);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep }
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep graph_transition_sulogin(RESTARTER_STATE_MAINT, old_state);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep return (0);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep}
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos/* ARGSUSED */
99b44c3bba5a515aba1e56c2104f53af320a848dlianepstatic int
99b44c3bba5a515aba1e56c2104f53af320a848dlianepgt_enter_offline(scf_handle_t *h, graph_vertex_t *v,
99b44c3bba5a515aba1e56c2104f53af320a848dlianep restarter_instance_state_t old_state, restarter_error_t rerr)
99b44c3bba5a515aba1e56c2104f53af320a848dlianep{
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus int to_offline = v->gv_flags & GV_TOOFFLINE;
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus v->gv_flags &= ~GV_TOOFFLINE;
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus
99b44c3bba5a515aba1e56c2104f53af320a848dlianep /*
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * If the instance should be enabled, see if we can start it.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * Otherwise send a disable command.
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus * If a instance has the GV_TOOFFLINE flag set then it must
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus * remains offline until the disable process completes.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep */
99b44c3bba5a515aba1e56c2104f53af320a848dlianep if (v->gv_flags & GV_ENABLED) {
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus if (to_offline == 0)
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus graph_start_if_satisfied(v);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep } else {
99b44c3bba5a515aba1e56c2104f53af320a848dlianep if (gt_running(old_state) && v->gv_post_disable_f)
99b44c3bba5a515aba1e56c2104f53af320a848dlianep v->gv_post_disable_f();
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus
99b44c3bba5a515aba1e56c2104f53af320a848dlianep vertex_send_event(v, RESTARTER_EVENT_TYPE_DISABLE);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep }
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
73b709ea25679d17a96a8d7f8db6531cbcc800d5rm /*
73b709ea25679d17a96a8d7f8db6531cbcc800d5rm * If the service was running, propagate a stop event. If the
73b709ea25679d17a96a8d7f8db6531cbcc800d5rm * service was not running the offline transition may satisfy
73b709ea25679d17a96a8d7f8db6531cbcc800d5rm * optional dependencies and should be propagated to determine
73b709ea25679d17a96a8d7f8db6531cbcc800d5rm * whether new dependents are satisfiable.
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus * Instances that transition to offline and have the GV_TOOFFLINE flag
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus * are special because they can expose new subtree leaves so propagate
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus * the offline to the instance dependencies.
73b709ea25679d17a96a8d7f8db6531cbcc800d5rm */
99b44c3bba5a515aba1e56c2104f53af320a848dlianep if (gt_running(old_state)) {
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus /*
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus * Handle state change during instance disabling.
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus * Propagate offline to the new exposed leaves.
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus */
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus if (to_offline) {
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus log_framework(LOG_DEBUG, "%s removed from subtree\n",
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus v->gv_name);
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus graph_offline_subtree_leaves(v, (void *)h);
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus }
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus
99b44c3bba5a515aba1e56c2104f53af320a848dlianep log_framework(LOG_DEBUG, "Propagating stop of %s.\n",
99b44c3bba5a515aba1e56c2104f53af320a848dlianep v->gv_name);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep graph_transition_propagate(v, PROPAGATE_STOP, rerr);
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus /*
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus * The offline transition may satisfy require_any/restart
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus * dependencies and should be propagated to determine
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus * whether new dependents are satisfiable.
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus */
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus graph_transition_propagate(v, PROPAGATE_SAT, rerr);
73b709ea25679d17a96a8d7f8db6531cbcc800d5rm } else {
73b709ea25679d17a96a8d7f8db6531cbcc800d5rm log_framework(LOG_DEBUG, "Propagating offline of %s.\n",
73b709ea25679d17a96a8d7f8db6531cbcc800d5rm v->gv_name);
73b709ea25679d17a96a8d7f8db6531cbcc800d5rm
73b709ea25679d17a96a8d7f8db6531cbcc800d5rm graph_transition_propagate(v, PROPAGATE_SAT, rerr);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep }
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep graph_transition_sulogin(RESTARTER_STATE_OFFLINE, old_state);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep return (0);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep}
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos/* ARGSUSED */
99b44c3bba5a515aba1e56c2104f53af320a848dlianepstatic int
99b44c3bba5a515aba1e56c2104f53af320a848dlianepgt_enter_disabled(scf_handle_t *h, graph_vertex_t *v,
99b44c3bba5a515aba1e56c2104f53af320a848dlianep restarter_instance_state_t old_state, restarter_error_t rerr)
99b44c3bba5a515aba1e56c2104f53af320a848dlianep{
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus int to_offline = v->gv_flags & GV_TOOFFLINE;
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus v->gv_flags &= ~GV_TODISABLE;
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus v->gv_flags &= ~GV_TOOFFLINE;
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus
99b44c3bba5a515aba1e56c2104f53af320a848dlianep /*
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * If the instance should be disabled, no problem. Otherwise,
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * send an enable command, which should result in the instance
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus * moving to OFFLINE unless the instance is part of a subtree
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus * (non root) and in this case the result is unpredictable.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep */
99b44c3bba5a515aba1e56c2104f53af320a848dlianep if (v->gv_flags & GV_ENABLED) {
99b44c3bba5a515aba1e56c2104f53af320a848dlianep vertex_send_event(v, RESTARTER_EVENT_TYPE_ENABLE);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep } else if (gt_running(old_state) && v->gv_post_disable_f) {
99b44c3bba5a515aba1e56c2104f53af320a848dlianep v->gv_post_disable_f();
99b44c3bba5a515aba1e56c2104f53af320a848dlianep }
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep /*
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep * If the service was running, propagate this as a stop. If the
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep * service was not running the disabled transition may satisfy
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep * optional dependencies and should be propagated to determine
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep * whether new dependents are satisfiable.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep */
99b44c3bba5a515aba1e56c2104f53af320a848dlianep if (gt_running(old_state)) {
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus /*
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus * We need to propagate the offline to new exposed leaves in
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus * case we've just disabled an instance that was part of a
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus * subtree.
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus */
207246e91737934c04805051c3fd6aa8892f0931Renaud Manus if (to_offline) {
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus log_framework(LOG_DEBUG, "%s removed from subtree\n",
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus v->gv_name);
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus /*
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus * Handle state change during instance disabling.
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus * Propagate offline to the new exposed leaves.
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus */
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus graph_offline_subtree_leaves(v, (void *)h);
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus }
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus
aca380d78daaa1b42289bf234c6ab0bdd9afe538Renaud Manus
99b44c3bba5a515aba1e56c2104f53af320a848dlianep log_framework(LOG_DEBUG, "Propagating stop of %s.\n",
99b44c3bba5a515aba1e56c2104f53af320a848dlianep v->gv_name);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep graph_transition_propagate(v, PROPAGATE_STOP, rerr);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep } else {
99b44c3bba5a515aba1e56c2104f53af320a848dlianep log_framework(LOG_DEBUG, "Propagating disable of %s.\n",
99b44c3bba5a515aba1e56c2104f53af320a848dlianep v->gv_name);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep graph_transition_propagate(v, PROPAGATE_SAT, rerr);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep }
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep graph_transition_sulogin(RESTARTER_STATE_DISABLED, old_state);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep return (0);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep}
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianepstatic int
99b44c3bba5a515aba1e56c2104f53af320a848dlianepgt_internal_online_or_degraded(scf_handle_t *h, graph_vertex_t *v,
99b44c3bba5a515aba1e56c2104f53af320a848dlianep restarter_instance_state_t old_state, restarter_error_t rerr)
99b44c3bba5a515aba1e56c2104f53af320a848dlianep{
99b44c3bba5a515aba1e56c2104f53af320a848dlianep int r;
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep /*
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * If the instance has just come up, update the start
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * snapshot.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep */
99b44c3bba5a515aba1e56c2104f53af320a848dlianep if (gt_running(old_state) == 0) {
99b44c3bba5a515aba1e56c2104f53af320a848dlianep /*
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * Don't fire if we're just recovering state
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * after a restart.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep */
99b44c3bba5a515aba1e56c2104f53af320a848dlianep if (old_state != RESTARTER_STATE_UNINIT &&
99b44c3bba5a515aba1e56c2104f53af320a848dlianep v->gv_post_online_f)
99b44c3bba5a515aba1e56c2104f53af320a848dlianep v->gv_post_online_f();
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep r = libscf_snapshots_poststart(h, v->gv_name, B_TRUE);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep switch (r) {
99b44c3bba5a515aba1e56c2104f53af320a848dlianep case 0:
99b44c3bba5a515aba1e56c2104f53af320a848dlianep case ENOENT:
99b44c3bba5a515aba1e56c2104f53af320a848dlianep /*
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * If ENOENT, the instance must have been
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * deleted. Pretend we were successful since
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * we should get a delete event later.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep */
99b44c3bba5a515aba1e56c2104f53af320a848dlianep break;
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep case ECONNABORTED:
99b44c3bba5a515aba1e56c2104f53af320a848dlianep return (ECONNABORTED);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep case EACCES:
99b44c3bba5a515aba1e56c2104f53af320a848dlianep case ENOTSUP:
99b44c3bba5a515aba1e56c2104f53af320a848dlianep default:
99b44c3bba5a515aba1e56c2104f53af320a848dlianep bad_error("libscf_snapshots_poststart", r);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep }
99b44c3bba5a515aba1e56c2104f53af320a848dlianep }
845e9415a97ec0124f099537b21fc0364883850fRenaud Manus
845e9415a97ec0124f099537b21fc0364883850fRenaud Manus if (!(v->gv_flags & GV_ENABLED)) {
99b44c3bba5a515aba1e56c2104f53af320a848dlianep vertex_send_event(v, RESTARTER_EVENT_TYPE_DISABLE);
845e9415a97ec0124f099537b21fc0364883850fRenaud Manus } else if (v->gv_flags & GV_TOOFFLINE) {
845e9415a97ec0124f099537b21fc0364883850fRenaud Manus /*
845e9415a97ec0124f099537b21fc0364883850fRenaud Manus * If the vertex has the GV_TOOFFLINE flag set then that's
845e9415a97ec0124f099537b21fc0364883850fRenaud Manus * because the instance was transitioning from offline to
845e9415a97ec0124f099537b21fc0364883850fRenaud Manus * online and the reverse disable algorithm doesn't offline
845e9415a97ec0124f099537b21fc0364883850fRenaud Manus * those instances because it was already appearing offline.
845e9415a97ec0124f099537b21fc0364883850fRenaud Manus * So do it now.
845e9415a97ec0124f099537b21fc0364883850fRenaud Manus */
845e9415a97ec0124f099537b21fc0364883850fRenaud Manus offline_vertex(v);
845e9415a97ec0124f099537b21fc0364883850fRenaud Manus }
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep if (gt_running(old_state) == 0) {
99b44c3bba5a515aba1e56c2104f53af320a848dlianep log_framework(LOG_DEBUG, "Propagating start of %s.\n",
99b44c3bba5a515aba1e56c2104f53af320a848dlianep v->gv_name);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep graph_transition_propagate(v, PROPAGATE_START, rerr);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep } else if (rerr == RERR_REFRESH) {
99b44c3bba5a515aba1e56c2104f53af320a848dlianep /* For refresh we'll get a message sans state change */
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep log_framework(LOG_DEBUG, "Propagating refresh of %s.\n",
99b44c3bba5a515aba1e56c2104f53af320a848dlianep v->gv_name);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep graph_transition_propagate(v, PROPAGATE_STOP, rerr);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep }
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep return (0);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep}
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianepstatic int
99b44c3bba5a515aba1e56c2104f53af320a848dlianepgt_enter_online(scf_handle_t *h, graph_vertex_t *v,
99b44c3bba5a515aba1e56c2104f53af320a848dlianep restarter_instance_state_t old_state, restarter_error_t rerr)
99b44c3bba5a515aba1e56c2104f53af320a848dlianep{
99b44c3bba5a515aba1e56c2104f53af320a848dlianep int r;
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep r = gt_internal_online_or_degraded(h, v, old_state, rerr);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep if (r != 0)
99b44c3bba5a515aba1e56c2104f53af320a848dlianep return (r);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep graph_transition_sulogin(RESTARTER_STATE_ONLINE, old_state);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep return (0);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep}
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianepstatic int
99b44c3bba5a515aba1e56c2104f53af320a848dlianepgt_enter_degraded(scf_handle_t *h, graph_vertex_t *v,
99b44c3bba5a515aba1e56c2104f53af320a848dlianep restarter_instance_state_t old_state, restarter_error_t rerr)
99b44c3bba5a515aba1e56c2104f53af320a848dlianep{
99b44c3bba5a515aba1e56c2104f53af320a848dlianep int r;
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep r = gt_internal_online_or_degraded(h, v, old_state, rerr);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep if (r != 0)
99b44c3bba5a515aba1e56c2104f53af320a848dlianep return (r);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep graph_transition_sulogin(RESTARTER_STATE_DEGRADED, old_state);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep return (0);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep}
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep/*
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * gt_transition() implements the state transition for the graph
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * state machine. It can return:
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * 0 success
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * ECONNABORTED repository connection aborted
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep *
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep * v->gv_state should be set to the state we're transitioning to before
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep * calling this function.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep */
99b44c3bba5a515aba1e56c2104f53af320a848dlianepint
99b44c3bba5a515aba1e56c2104f53af320a848dlianepgt_transition(scf_handle_t *h, graph_vertex_t *v, restarter_error_t rerr,
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep restarter_instance_state_t old_state)
99b44c3bba5a515aba1e56c2104f53af320a848dlianep{
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos int err;
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos int lost_repository = 0;
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep /*
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * If there's a common set of work to be done on exit from the
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * old_state, include it as a separate set of functions here. For
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * now there's no such work, so there are no gt_exit functions.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep */
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos err = vertex_subgraph_dependencies_shutdown(h, v, old_state);
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos switch (err) {
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos case 0:
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos break;
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos case ECONNABORTED:
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos lost_repository = 1;
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos break;
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos default:
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos bad_error("vertex_subgraph_dependencies_shutdown", err);
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos }
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos
99b44c3bba5a515aba1e56c2104f53af320a848dlianep /*
99b44c3bba5a515aba1e56c2104f53af320a848dlianep * Now call the appropriate gt_enter function for the new state.
99b44c3bba5a515aba1e56c2104f53af320a848dlianep */
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep switch (v->gv_state) {
99b44c3bba5a515aba1e56c2104f53af320a848dlianep case RESTARTER_STATE_UNINIT:
99b44c3bba5a515aba1e56c2104f53af320a848dlianep err = gt_enter_uninit(h, v, old_state, rerr);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep break;
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep case RESTARTER_STATE_DISABLED:
99b44c3bba5a515aba1e56c2104f53af320a848dlianep err = gt_enter_disabled(h, v, old_state, rerr);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep break;
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep case RESTARTER_STATE_OFFLINE:
99b44c3bba5a515aba1e56c2104f53af320a848dlianep err = gt_enter_offline(h, v, old_state, rerr);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep break;
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep case RESTARTER_STATE_ONLINE:
99b44c3bba5a515aba1e56c2104f53af320a848dlianep err = gt_enter_online(h, v, old_state, rerr);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep break;
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep case RESTARTER_STATE_DEGRADED:
99b44c3bba5a515aba1e56c2104f53af320a848dlianep err = gt_enter_degraded(h, v, old_state, rerr);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep break;
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep case RESTARTER_STATE_MAINT:
99b44c3bba5a515aba1e56c2104f53af320a848dlianep err = gt_enter_maint(h, v, old_state, rerr);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep break;
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
99b44c3bba5a515aba1e56c2104f53af320a848dlianep default:
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep /* Shouldn't be in an invalid state. */
99b44c3bba5a515aba1e56c2104f53af320a848dlianep#ifndef NDEBUG
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos uu_warn("%s:%d: Invalid state %d.\n", __FILE__, __LINE__,
cd3bce3e1981250fe9793d5d51d701e9c54d2feelianep v->gv_state);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep#endif
99b44c3bba5a515aba1e56c2104f53af320a848dlianep abort();
99b44c3bba5a515aba1e56c2104f53af320a848dlianep }
99b44c3bba5a515aba1e56c2104f53af320a848dlianep
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos switch (err) {
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos case 0:
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos break;
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos case ECONNABORTED:
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos lost_repository = 1;
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos break;
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos default:
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos#ifndef NDEBUG
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos uu_warn("%s:%d: "
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos "gt_enter_%s() failed with unexpected error %d.\n",
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos __FILE__, __LINE__, instance_state_str[v->gv_state], err);
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos#endif
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos abort();
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos }
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos
56e2393871ebc8ef99ec6ceaded2cd17f208ee61bustos return (lost_repository ? ECONNABORTED : 0);
99b44c3bba5a515aba1e56c2104f53af320a848dlianep}