Mercurial > illumos > illumos-gate
changeset 10029:8377504a53e1
6855845 Allow Property Modification in SMF profiles
6855772 svccfg dumps core during installation
author | Antonello Cruz <Antonello.Cruz@Sun.COM> |
---|---|
date | Thu, 02 Jul 2009 15:41:03 -0700 |
parents | 2de34ea54ad5 |
children | 93a7ff2e6767 |
files | usr/src/cmd/svc/svccfg/svccfg.y usr/src/cmd/svc/svccfg/svccfg_engine.c usr/src/cmd/svc/svccfg/svccfg_libscf.c usr/src/cmd/svc/svccfg/svccfg_xml.c |
diffstat | 4 files changed, 212 insertions(+), 86 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/svc/svccfg/svccfg.y Thu Jul 02 15:06:50 2009 -0700 +++ b/usr/src/cmd/svc/svccfg/svccfg.y Thu Jul 02 15:41:03 2009 -0700 @@ -21,7 +21,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -241,7 +241,23 @@ | SCC_RESTORE error terminator { synerr(SCC_RESTORE); return(0); } apply_cmd : SCC_APPLY SCV_WORD terminator - { (void) engine_apply($2); free($2); } + { + (void) engine_apply($2, 1); + free($2); + } + | SCC_APPLY SCV_WORD SCV_WORD terminator + { + if (strcmp($2, "-n") == 0) { + (void) engine_apply($3, 0); + free($2); + free($3); + } else { + synerr(SCC_APPLY); + free($2); + free($3); + return (0); + } + } | SCC_APPLY error terminator { synerr(SCC_APPLY); return(0); } extract_cmd: SCC_EXTRACT terminator { lscf_profile_extract(NULL); }
--- a/usr/src/cmd/svc/svccfg/svccfg_engine.c Thu Jul 02 15:06:50 2009 -0700 +++ b/usr/src/cmd/svc/svccfg/svccfg_engine.c Thu Jul 02 15:41:03 2009 -0700 @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -637,7 +637,7 @@ } int -engine_apply(const char *file) +engine_apply(const char *file, int apply_changes) { int ret; bundle_t *b; @@ -657,6 +657,11 @@ return (-1); } + if (!apply_changes) { /* we don't want to apply, just test */ + internal_bundle_free(b); + return (0); + } + if (lscf_bundle_apply(b, file) != 0) { internal_bundle_free(b); return (-1);
--- a/usr/src/cmd/svc/svccfg/svccfg_libscf.c Thu Jul 02 15:06:50 2009 -0700 +++ b/usr/src/cmd/svc/svccfg/svccfg_libscf.c Thu Jul 02 15:41:03 2009 -0700 @@ -2143,6 +2143,7 @@ default: bad_error("scf_transaction_commit", scf_error()); } + break; default: bad_error("scf_transaction_commit", r); @@ -2171,6 +2172,49 @@ * EBUSY - new property group changed (error printed) */ static int +lscf_import_service_pgs(scf_service_t *svc, const char *target_fmri, + const entity_t *isvc, int flags) +{ + scf_callback_t cbdata; + + cbdata.sc_handle = scf_service_handle(svc); + cbdata.sc_parent = svc; + cbdata.sc_service = 1; + cbdata.sc_general = 0; + cbdata.sc_enable = 0; + cbdata.sc_flags = flags; + cbdata.sc_source_fmri = isvc->sc_fmri; + cbdata.sc_target_fmri = target_fmri; + + if (uu_list_walk(isvc->sc_pgroups, entity_pgroup_import, &cbdata, + UU_DEFAULT) != 0) { + if (uu_error() != UU_ERROR_CALLBACK_FAILED) + bad_error("uu_list_walk", uu_error()); + + return (cbdata.sc_err); + } + + return (0); +} + +/* + * Returns + * 0 - success + * ECONNABORTED - repository connection broken + * ENOMEM - out of memory + * ENOSPC - svc.configd is out of resources + * ECANCELED - inst was deleted + * EPERM - could not create property group (permission denied) (error printed) + * - could not modify property group (permission denied) (error printed) + * EROFS - could not create property group (repository is read-only) + * EACCES - could not create property group (backend access denied) + * EEXIST - could not create property group (already exists) + * EINVAL - invalid property group name (error printed) + * - invalid property name (error printed) + * - invalid value (error printed) + * EBUSY - new property group changed (error printed) + */ +static int lscf_import_instance_pgs(scf_instance_t *inst, const char *target_fmri, const entity_t *iinst, int flags) { @@ -7303,6 +7347,69 @@ return (result); } +/* + * _lscf_import_err() summarize the error handling returned by + * lscf_import_{instance | service}_pgs + * Return values are: + * IMPORT_NEXT + * IMPORT_OUT + * IMPORT_BAD + */ + +#define IMPORT_BAD -1 +#define IMPORT_NEXT 0 +#define IMPORT_OUT 1 + +static int +_lscf_import_err(int err, const char *fmri) +{ + switch (err) { + case 0: + if (g_verbose) + warn(gettext("%s updated.\n"), fmri); + return (IMPORT_NEXT); + + case ECONNABORTED: + warn(gettext("Could not update %s " + "(repository connection broken).\n"), fmri); + return (IMPORT_OUT); + + case ENOMEM: + warn(gettext("Could not update %s (out of memory).\n"), fmri); + return (IMPORT_OUT); + + case ENOSPC: + warn(gettext("Could not update %s " + "(repository server out of resources).\n"), fmri); + return (IMPORT_OUT); + + case ECANCELED: + warn(gettext( + "Could not update %s (deleted).\n"), fmri); + return (IMPORT_NEXT); + + case EPERM: + case EINVAL: + case EBUSY: + return (IMPORT_NEXT); + + case EROFS: + warn(gettext("Could not update %s (repository read-only).\n"), + fmri); + return (IMPORT_OUT); + + case EACCES: + warn(gettext("Could not update %s " + "(backend access denied).\n"), fmri); + return (IMPORT_NEXT); + + case EEXIST: + default: + return (IMPORT_BAD); + } + + /*NOTREACHED*/ +} /* * Returns @@ -7316,6 +7423,7 @@ scf_scope_t *rscope; scf_service_t *rsvc; scf_instance_t *rinst; + scf_iter_t *iter; int annotation_set = 0; int r; @@ -7324,6 +7432,7 @@ if ((rscope = scf_scope_create(g_hndl)) == NULL || (rsvc = scf_service_create(g_hndl)) == NULL || (rinst = scf_instance_create(g_hndl)) == NULL || + (iter = scf_iter_create(g_hndl)) == NULL || (imp_pg = scf_pg_create(g_hndl)) == NULL || (imp_tx = scf_transaction_create(g_hndl)) == NULL) scfdie(); @@ -7364,6 +7473,8 @@ for (svc = uu_list_first(bndl->sc_bundle_services); svc != NULL; svc = uu_list_next(bndl->sc_bundle_services, svc)) { + int refresh = 0; + if (scf_scope_get_service(rscope, svc->sc_name, rsvc) != 0) { switch (scf_error()) { case SCF_ERROR_NOT_FOUND: @@ -7377,6 +7488,27 @@ } } + /* + * if we have pgs in the profile, we need to refresh ALL + * instances of the service + */ + if (uu_list_numnodes(svc->sc_pgroups) != 0) { + refresh = 1; + r = lscf_import_service_pgs(rsvc, svc->sc_fmri, svc, + SCI_FORCE | SCI_KEEP); + switch (_lscf_import_err(r, svc->sc_fmri)) { + case IMPORT_NEXT: + break; + + case IMPORT_OUT: + goto out; + + case IMPORT_BAD: + default: + bad_error("lscf_import_service_pgs", r); + } + } + for (inst = uu_list_first( svc->sc_u.sc_service.sc_service_instances); inst != NULL; @@ -7401,57 +7533,30 @@ r = lscf_import_instance_pgs(rinst, inst->sc_fmri, inst, SCI_FORCE | SCI_KEEP); - switch (r) { - case 0: - if (g_verbose) - warn(gettext("%s updated.\n"), - inst->sc_fmri); + switch (_lscf_import_err(r, inst->sc_fmri)) { + case IMPORT_NEXT: break; - case ECONNABORTED: - warn(gettext("Could not update %s " - "(repository connection broken).\n"), - inst->sc_fmri); - goto out; - - case ENOMEM: - warn(gettext("Could not update %s " - "(out of memory).\n"), inst->sc_fmri); - goto out; - - case ENOSPC: - warn(gettext("Could not update %s " - "(repository server out of resources).\n"), - inst->sc_fmri); + case IMPORT_OUT: goto out; - case ECANCELED: - warn(gettext( - "Could not update %s (deleted).\n"), - inst->sc_fmri); - break; - - case EPERM: - case EINVAL: - case EBUSY: - break; - - case EROFS: - warn(gettext("Could not update %s " - "(repository read-only).\n"), - inst->sc_fmri); - goto out; - - case EACCES: - warn(gettext("Could not update %s " - "(backend access denied).\n"), - inst->sc_fmri); - break; - - case EEXIST: + case IMPORT_BAD: default: bad_error("lscf_import_instance_pgs", r); } + + /* refresh only if there is no pgs in the service */ + if (refresh == 0) + (void) refresh_entity(0, rinst, inst->sc_fmri, + NULL, NULL, NULL); + } + + if (refresh == 1) { + char *name_buf = safe_malloc(max_scf_name_len + 1); + + (void) refresh_entity(1, rsvc, svc->sc_name, rinst, + iter, name_buf); + free(name_buf); } } @@ -7466,6 +7571,7 @@ scf_pg_destroy(imp_pg); imp_pg = NULL; + scf_iter_destroy(iter); scf_instance_destroy(rinst); scf_service_destroy(rsvc); scf_scope_destroy(rscope);
--- a/usr/src/cmd/svc/svccfg/svccfg_xml.c Thu Jul 02 15:06:50 2009 -0700 +++ b/usr/src/cmd/svc/svccfg/svccfg_xml.c Thu Jul 02 15:41:03 2009 -0700 @@ -2815,18 +2815,19 @@ /* * Translate an instance element into an internal property tree, added to - * service. If op is SVCCFG_OP_APPLY (i.e., apply a profile), forbid - * subelements and set the enabled property to override. + * service. If op is SVCCFG_OP_APPLY (i.e., apply a profile), set the + * enabled property to override. */ static int -lxml_get_instance(entity_t *service, xmlNodePtr inst, svccfg_op_t op) +lxml_get_instance(entity_t *service, xmlNodePtr inst, bundle_type_t bt, + svccfg_op_t op) { entity_t *i; pgroup_t *pg; property_t *p; xmlNodePtr cursor; xmlChar *enabled; - int r; + int r, e_val; /* * Fetch its attributes, as appropriate. @@ -2844,24 +2845,36 @@ enabled = xmlGetProp(inst, (xmlChar *)enabled_attr); - /* - * New general property group with enabled boolean property set. - */ - pg = internal_pgroup_new(); - (void) internal_attach_pgroup(i, pg); - - pg->sc_pgroup_name = (char *)scf_pg_general; - pg->sc_pgroup_type = (char *)scf_group_framework; - pg->sc_pgroup_flags = 0; - - p = internal_property_create(SCF_PROPERTY_ENABLED, SCF_TYPE_BOOLEAN, 1, - (uint64_t)(strcmp(true, (const char *)enabled) == 0 ? 1 : 0)); - - p->sc_property_override = (op == SVCCFG_OP_APPLY); - - (void) internal_attach_property(pg, p); - - xmlFree(enabled); + if (enabled == NULL) { + if (bt == SVCCFG_MANIFEST) { + semerr(gettext("Instance \"%s\" missing attribute " + "\"%s\".\n"), i->sc_name, enabled_attr); + return (-1); + } + } else { /* enabled != NULL */ + if (strcmp(true, (const char *)enabled) != 0 && + strcmp(false, (const char *)enabled) != 0) { + xmlFree(enabled); + semerr(gettext("Invalid enabled value\n")); + return (-1); + } + pg = internal_pgroup_new(); + (void) internal_attach_pgroup(i, pg); + + pg->sc_pgroup_name = (char *)scf_pg_general; + pg->sc_pgroup_type = (char *)scf_group_framework; + pg->sc_pgroup_flags = 0; + + e_val = (strcmp(true, (const char *)enabled) == 0); + p = internal_property_create(SCF_PROPERTY_ENABLED, + SCF_TYPE_BOOLEAN, 1, (uint64_t)e_val); + + p->sc_property_override = (op == SVCCFG_OP_APPLY); + + (void) internal_attach_property(pg, p); + + xmlFree(enabled); + } /* * Walk its child elements, as appropriate. @@ -2871,13 +2884,6 @@ if (lxml_ignorable_block(cursor)) continue; - if (op == SVCCFG_OP_APPLY) { - semerr(gettext("Instance \"%s\" may not contain " - "elements in profiles.\n"), i->sc_name, - cursor->name); - return (-1); - } - switch (lxml_xlate_element(cursor->name)) { case SC_RESTARTER: (void) lxml_get_restarter(i, cursor); @@ -2972,17 +2978,10 @@ e = lxml_xlate_element(cursor->name); - if (op == SVCCFG_OP_APPLY && e != SC_INSTANCE) { - semerr(gettext("Service \"%s\" may not contain the " - "non-instance element \"%s\" in a profile.\n"), - s->sc_name, cursor->name); - - return (-1); - } - switch (e) { case SC_INSTANCE: - if (lxml_get_instance(s, cursor, op) != 0) + if (lxml_get_instance(s, cursor, + bundle->sc_bundle_type, op) != 0) return (-1); break; case SC_TEMPLATE: