Print this page
12721 would like svcadm disable -c


   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 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  * Copyright (c) 2015, Joyent, Inc. All rights reserved.
  26  */
  27 
  28 /*
  29  * Service state explanation.  For select services, display a description, the
  30  * state, and possibly why the service is in that state, what's causing it to
  31  * be in that state, and what other services it is keeping offline (impact).
  32  *
  33  * Explaining states other than offline is easy.  For maintenance and
  34  * degraded, we just use the auxiliary state.  For offline, we must determine
  35  * which dependencies are unsatisfied and recurse.  If a causal service is not
  36  * offline, then a svcptr to it is added to the offline service's causes list.
  37  * If a causal service is offline, then we recurse to determine its causes and
  38  * merge them into the causes list of the service in question (see
  39  * add_causes()).  Note that by adding a self-pointing svcptr to the causes
  40  * lists of services which are not offline or are offline for unknown reasons,
  41  * we can always merge the unsatisfied dependency's causes into the
  42  * dependent's list.
  43  *
  44  * Computing an impact list is more involved because the dependencies in the
  45  * repository are unidirectional; it requires determining the causes of all


 116         uu_panic("%s:%d: %s() failed with unknown error %d.\n",         \
 117             __FILE__, __LINE__, func, err);
 118 
 119 typedef struct {
 120         const char *svcname;
 121         const char *instname;
 122 
 123         /* restarter pg properties */
 124         char state[MAX_SCF_STATE_STRING_SZ];
 125         char next_state[MAX_SCF_STATE_STRING_SZ];
 126         struct timeval stime;
 127         const char *aux_state;
 128         const char *aux_fmri;
 129         int64_t start_method_waitstatus;
 130 
 131         uint8_t enabled;
 132         int temporary;
 133         const char *restarter;
 134         uu_list_t *dependencies;        /* list of dependency_group's */
 135 


 136         int active;                     /* In use?  (cycle detection) */
 137         int restarter_bad;
 138         const char *summary;
 139         uu_list_t *baddeps;             /* list of dependency's */
 140         uu_list_t *causes;              /* list of svcptrs */
 141         uu_list_t *impact_dependents;   /* list of svcptrs */
 142         uu_list_t *impact;              /* list of svcptrs */
 143 
 144         uu_list_node_t node;
 145 } inst_t;
 146 
 147 typedef struct service {
 148         const char *svcname;
 149         uu_list_t *instances;
 150         struct service *next;
 151 } svc_t;
 152 
 153 struct svcptr {
 154         inst_t *svcp;
 155         inst_t *next_hop;


 386                             max_scf_fmri_length + 1) < 0)
 387                                 scfdie();
 388 
 389                         uu_list_node_init(d, &d->node, deps);
 390                         (void) uu_list_append(dg->entities, d);
 391                 }
 392 
 393                 uu_list_node_init(dg, &dg->node, depgroups);
 394                 r = uu_list_append(svcp->dependencies, dg);
 395                 assert(r == 0);
 396         }
 397 
 398         return (0);
 399 }
 400 
 401 static void
 402 add_instance(const char *svcname, const char *instname, scf_instance_t *inst)
 403 {
 404         inst_t *instp;
 405         svc_t *svcp;
 406         int have_enabled = 0;
 407         uint8_t i;
 408         uint32_t h;
 409         int r;
 410 
 411         h = hash_name(svcname) & SVC_HASH_MASK;
 412         for (svcp = services[h]; svcp != NULL; svcp = svcp->next) {
 413                 if (strcmp(svcp->svcname, svcname) == 0)
 414                         break;
 415         }
 416 
 417         if (svcp == NULL) {
 418                 svcp = safe_malloc(sizeof (*svcp));
 419                 svcp->svcname = safe_strdup(svcname);
 420                 svcp->instances = uu_list_create(insts, svcp, UU_LIST_DEBUG);
 421                 if (svcp->instances == NULL)
 422                         uu_die(emsg_nomem);
 423                 svcp->next = services[h];
 424                 services[h] = svcp;
 425         }
 426 


 462                 return;
 463 
 464         /* restarter may not set aux_state, allow to continue in that case */
 465         if (pg_get_single_val(g_pg, SCF_PROPERTY_AUX_STATE, SCF_TYPE_ASTRING,
 466             g_fmri, g_fmri_sz, 0) == 0)
 467                 instp->aux_state = safe_strdup(g_fmri);
 468         else
 469                 instp->aux_state = safe_strdup(AUX_STATE_INVALID);
 470 
 471         (void) pg_get_single_val(g_pg, SCF_PROPERTY_START_METHOD_WAITSTATUS,
 472             SCF_TYPE_INTEGER, &instp->start_method_waitstatus, 0, 0);
 473 
 474         /* Get the optional auxiliary_fmri */
 475         if (pg_get_single_val(g_pg, SCF_PROPERTY_AUX_FMRI, SCF_TYPE_ASTRING,
 476             g_fmri, g_fmri_sz, 0) == 0)
 477                 instp->aux_fmri = safe_strdup(g_fmri);
 478 
 479         if (scf_instance_get_pg(inst, SCF_PG_GENERAL_OVR, g_pg) == 0) {
 480                 if (pg_get_single_val(g_pg, SCF_PROPERTY_ENABLED,
 481                     SCF_TYPE_BOOLEAN, &instp->enabled, 0, 0) == 0)
 482                         have_enabled = 1;



 483         } else {
 484                 switch (scf_error()) {
 485                 case SCF_ERROR_NOT_FOUND:
 486                         break;
 487 
 488                 case SCF_ERROR_DELETED:
 489                         return;
 490 
 491                 default:
 492                         scfdie();
 493                 }
 494         }
 495 
 496         if (scf_instance_get_pg_composed(inst, NULL, SCF_PG_GENERAL, g_pg) !=
 497             0) {
 498                 switch (scf_error()) {
 499                 case SCF_ERROR_DELETED:
 500                 case SCF_ERROR_NOT_FOUND:
 501                         return;
 502 
 503                 default:
 504                         scfdie();
 505                 }
 506         }
 507 
 508         if (pg_get_single_val(g_pg, SCF_PROPERTY_ENABLED, SCF_TYPE_BOOLEAN,
 509             &i, 0, 0) != 0)
 510                 return;
 511         if (!have_enabled) {



 512                 instp->enabled = i;
 513                 instp->temporary = 0;
 514         } else {
 515                 instp->temporary = (instp->enabled != i);
 516         }
 517 






 518         if (pg_get_single_val(g_pg, SCF_PROPERTY_RESTARTER, SCF_TYPE_ASTRING,
 519             g_fmri, g_fmri_sz, 0) == 0)
 520                 instp->restarter = safe_strdup(g_fmri);
 521         else
 522                 instp->restarter = SCF_SERVICE_STARTD;
 523 
 524         if (strcmp(instp->state, SCF_STATE_STRING_OFFLINE) == 0 &&
 525             load_dependencies(instp, inst) != 0)
 526                 return;
 527 
 528         uu_list_node_init(instp, &instp->node, insts);
 529         r = uu_list_append(svcp->instances, instp);
 530         assert(r == 0);
 531 }
 532 
 533 static void
 534 load_services(void)
 535 {
 536         scf_iter_t *siter, *iiter;
 537         int r;


1719                         goto diagcode;
1720 
1721                 default:
1722                         bad_error("get_fmri", r);
1723                 }
1724 
1725                 if (inst_running(rsp)) {
1726                         (void) printf(gettext("Reason: Restarter %s "
1727                             "has not initialized service state.\n"),
1728                             svcp->restarter);
1729                         dc = DC_UNINIT;
1730                 } else {
1731                         (void) printf(gettext(
1732                             "Reason: Restarter %s is not running.\n"),
1733                             svcp->restarter);
1734                         dc = DC_RSTRDEAD;
1735                 }
1736 
1737         } else if (strcmp(svcp->state, SCF_STATE_STRING_DISABLED) == 0) {
1738                 if (!svcp->temporary) {
1739                         (void) puts(gettext(
1740                             "Reason: Disabled by an administrator."));





1741                         dc = DC_DISABLED;
1742                 } else {
1743                         (void) puts(gettext("Reason: "
1744                             "Temporarily disabled by an administrator."));






1745                         dc = DC_TEMPDISABLED;
1746                 }
1747 
1748         } else if (strcmp(svcp->state, SCF_STATE_STRING_MAINT) == 0) {
1749                 if (strcmp(svcp->aux_state, "administrative_request") == 0) {
1750                         (void) puts(gettext("Reason: "
1751                             "Maintenance requested by an administrator."));
1752                         dc = DC_ADMINMAINT;
1753                 } else if (strcmp(svcp->aux_state, "dependency_cycle") == 0) {
1754                         (void) puts(gettext(
1755                             "Reason: Completes a dependency cycle."));
1756                         dc = DC_DEPCYCLE;
1757                 } else if (strcmp(svcp->aux_state, "fault_threshold_reached") ==
1758                     0) {
1759                         print_method_failure(svcp, &dc);
1760                 } else if (strcmp(svcp->aux_state, "service_request") == 0) {
1761                         if (svcp->aux_fmri) {
1762                                 (void) printf(gettext("Reason: Maintenance "
1763                                     "requested by \"%s\"\n"), svcp->aux_fmri);
1764                                 print_aux_fmri_logs(svcp->aux_fmri);




   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 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  * Copyright 2020 Joyent, Inc.
  26  */
  27 
  28 /*
  29  * Service state explanation.  For select services, display a description, the
  30  * state, and possibly why the service is in that state, what's causing it to
  31  * be in that state, and what other services it is keeping offline (impact).
  32  *
  33  * Explaining states other than offline is easy.  For maintenance and
  34  * degraded, we just use the auxiliary state.  For offline, we must determine
  35  * which dependencies are unsatisfied and recurse.  If a causal service is not
  36  * offline, then a svcptr to it is added to the offline service's causes list.
  37  * If a causal service is offline, then we recurse to determine its causes and
  38  * merge them into the causes list of the service in question (see
  39  * add_causes()).  Note that by adding a self-pointing svcptr to the causes
  40  * lists of services which are not offline or are offline for unknown reasons,
  41  * we can always merge the unsatisfied dependency's causes into the
  42  * dependent's list.
  43  *
  44  * Computing an impact list is more involved because the dependencies in the
  45  * repository are unidirectional; it requires determining the causes of all


 116         uu_panic("%s:%d: %s() failed with unknown error %d.\n",         \
 117             __FILE__, __LINE__, func, err);
 118 
 119 typedef struct {
 120         const char *svcname;
 121         const char *instname;
 122 
 123         /* restarter pg properties */
 124         char state[MAX_SCF_STATE_STRING_SZ];
 125         char next_state[MAX_SCF_STATE_STRING_SZ];
 126         struct timeval stime;
 127         const char *aux_state;
 128         const char *aux_fmri;
 129         int64_t start_method_waitstatus;
 130 
 131         uint8_t enabled;
 132         int temporary;
 133         const char *restarter;
 134         uu_list_t *dependencies;        /* list of dependency_group's */
 135 
 136         char comment[SCF_COMMENT_MAX_LENGTH];
 137 
 138         int active;                     /* In use?  (cycle detection) */
 139         int restarter_bad;
 140         const char *summary;
 141         uu_list_t *baddeps;             /* list of dependency's */
 142         uu_list_t *causes;              /* list of svcptrs */
 143         uu_list_t *impact_dependents;   /* list of svcptrs */
 144         uu_list_t *impact;              /* list of svcptrs */
 145 
 146         uu_list_node_t node;
 147 } inst_t;
 148 
 149 typedef struct service {
 150         const char *svcname;
 151         uu_list_t *instances;
 152         struct service *next;
 153 } svc_t;
 154 
 155 struct svcptr {
 156         inst_t *svcp;
 157         inst_t *next_hop;


 388                             max_scf_fmri_length + 1) < 0)
 389                                 scfdie();
 390 
 391                         uu_list_node_init(d, &d->node, deps);
 392                         (void) uu_list_append(dg->entities, d);
 393                 }
 394 
 395                 uu_list_node_init(dg, &dg->node, depgroups);
 396                 r = uu_list_append(svcp->dependencies, dg);
 397                 assert(r == 0);
 398         }
 399 
 400         return (0);
 401 }
 402 
 403 static void
 404 add_instance(const char *svcname, const char *instname, scf_instance_t *inst)
 405 {
 406         inst_t *instp;
 407         svc_t *svcp;
 408         int ovr_set = 0;
 409         uint8_t i;
 410         uint32_t h;
 411         int r;
 412 
 413         h = hash_name(svcname) & SVC_HASH_MASK;
 414         for (svcp = services[h]; svcp != NULL; svcp = svcp->next) {
 415                 if (strcmp(svcp->svcname, svcname) == 0)
 416                         break;
 417         }
 418 
 419         if (svcp == NULL) {
 420                 svcp = safe_malloc(sizeof (*svcp));
 421                 svcp->svcname = safe_strdup(svcname);
 422                 svcp->instances = uu_list_create(insts, svcp, UU_LIST_DEBUG);
 423                 if (svcp->instances == NULL)
 424                         uu_die(emsg_nomem);
 425                 svcp->next = services[h];
 426                 services[h] = svcp;
 427         }
 428 


 464                 return;
 465 
 466         /* restarter may not set aux_state, allow to continue in that case */
 467         if (pg_get_single_val(g_pg, SCF_PROPERTY_AUX_STATE, SCF_TYPE_ASTRING,
 468             g_fmri, g_fmri_sz, 0) == 0)
 469                 instp->aux_state = safe_strdup(g_fmri);
 470         else
 471                 instp->aux_state = safe_strdup(AUX_STATE_INVALID);
 472 
 473         (void) pg_get_single_val(g_pg, SCF_PROPERTY_START_METHOD_WAITSTATUS,
 474             SCF_TYPE_INTEGER, &instp->start_method_waitstatus, 0, 0);
 475 
 476         /* Get the optional auxiliary_fmri */
 477         if (pg_get_single_val(g_pg, SCF_PROPERTY_AUX_FMRI, SCF_TYPE_ASTRING,
 478             g_fmri, g_fmri_sz, 0) == 0)
 479                 instp->aux_fmri = safe_strdup(g_fmri);
 480 
 481         if (scf_instance_get_pg(inst, SCF_PG_GENERAL_OVR, g_pg) == 0) {
 482                 if (pg_get_single_val(g_pg, SCF_PROPERTY_ENABLED,
 483                     SCF_TYPE_BOOLEAN, &instp->enabled, 0, 0) == 0)
 484                         ovr_set = 1;
 485                 (void) pg_get_single_val(g_pg, SCF_PROPERTY_COMMENT,
 486                     SCF_TYPE_ASTRING, instp->comment,
 487                     sizeof (instp->comment), EMPTY_OK);
 488         } else {
 489                 switch (scf_error()) {
 490                 case SCF_ERROR_NOT_FOUND:
 491                         break;
 492 
 493                 case SCF_ERROR_DELETED:
 494                         return;
 495 
 496                 default:
 497                         scfdie();
 498                 }
 499         }
 500 
 501         if (scf_instance_get_pg_composed(inst, NULL, SCF_PG_GENERAL, g_pg) !=
 502             0) {
 503                 switch (scf_error()) {
 504                 case SCF_ERROR_DELETED:
 505                 case SCF_ERROR_NOT_FOUND:
 506                         return;
 507 
 508                 default:
 509                         scfdie();
 510                 }
 511         }
 512 
 513         if (pg_get_single_val(g_pg, SCF_PROPERTY_ENABLED, SCF_TYPE_BOOLEAN,
 514             &i, 0, 0) != 0)
 515                 return;
 516 
 517         if (ovr_set) {
 518                 instp->temporary = (instp->enabled != i);
 519         } else {
 520                 instp->enabled = i;
 521                 instp->temporary = 0;


 522         }
 523 
 524         if (!instp->temporary) {
 525                 (void) pg_get_single_val(g_pg, SCF_PROPERTY_COMMENT,
 526                     SCF_TYPE_ASTRING, instp->comment,
 527                     sizeof (instp->comment), EMPTY_OK);
 528         }
 529 
 530         if (pg_get_single_val(g_pg, SCF_PROPERTY_RESTARTER, SCF_TYPE_ASTRING,
 531             g_fmri, g_fmri_sz, 0) == 0)
 532                 instp->restarter = safe_strdup(g_fmri);
 533         else
 534                 instp->restarter = SCF_SERVICE_STARTD;
 535 
 536         if (strcmp(instp->state, SCF_STATE_STRING_OFFLINE) == 0 &&
 537             load_dependencies(instp, inst) != 0)
 538                 return;
 539 
 540         uu_list_node_init(instp, &instp->node, insts);
 541         r = uu_list_append(svcp->instances, instp);
 542         assert(r == 0);
 543 }
 544 
 545 static void
 546 load_services(void)
 547 {
 548         scf_iter_t *siter, *iiter;
 549         int r;


1731                         goto diagcode;
1732 
1733                 default:
1734                         bad_error("get_fmri", r);
1735                 }
1736 
1737                 if (inst_running(rsp)) {
1738                         (void) printf(gettext("Reason: Restarter %s "
1739                             "has not initialized service state.\n"),
1740                             svcp->restarter);
1741                         dc = DC_UNINIT;
1742                 } else {
1743                         (void) printf(gettext(
1744                             "Reason: Restarter %s is not running.\n"),
1745                             svcp->restarter);
1746                         dc = DC_RSTRDEAD;
1747                 }
1748 
1749         } else if (strcmp(svcp->state, SCF_STATE_STRING_DISABLED) == 0) {
1750                 if (!svcp->temporary) {
1751                         if (svcp->comment[0] != '\0') {
1752                                 (void) printf(gettext("Reason: Disabled by "
1753                                     "an administrator: %s\n"), svcp->comment);
1754                         } else {
1755                                 (void) printf(gettext("Reason: Disabled by "
1756                                     "an administrator.\n"));
1757                         }
1758                         dc = DC_DISABLED;
1759                 } else {
1760                         if (svcp->comment[0] != '\0') {
1761                                 (void) printf(gettext("Reason: Temporarily "
1762                                     "disabled by an administrator: %s\n"),
1763                                     svcp->comment);
1764                         } else {
1765                                 (void) printf(gettext("Reason: Temporarily "
1766                                     "disabled by an administrator.\n"));
1767                         }
1768                         dc = DC_TEMPDISABLED;
1769                 }
1770 
1771         } else if (strcmp(svcp->state, SCF_STATE_STRING_MAINT) == 0) {
1772                 if (strcmp(svcp->aux_state, "administrative_request") == 0) {
1773                         (void) puts(gettext("Reason: "
1774                             "Maintenance requested by an administrator."));
1775                         dc = DC_ADMINMAINT;
1776                 } else if (strcmp(svcp->aux_state, "dependency_cycle") == 0) {
1777                         (void) puts(gettext(
1778                             "Reason: Completes a dependency cycle."));
1779                         dc = DC_DEPCYCLE;
1780                 } else if (strcmp(svcp->aux_state, "fault_threshold_reached") ==
1781                     0) {
1782                         print_method_failure(svcp, &dc);
1783                 } else if (strcmp(svcp->aux_state, "service_request") == 0) {
1784                         if (svcp->aux_fmri) {
1785                                 (void) printf(gettext("Reason: Maintenance "
1786                                     "requested by \"%s\"\n"), svcp->aux_fmri);
1787                                 print_aux_fmri_logs(svcp->aux_fmri);