diff options
Diffstat (limited to 'usr/src')
| -rw-r--r-- | usr/src/cmd/svc/svccfg/svccfg.h | 2 | ||||
| -rw-r--r-- | usr/src/cmd/svc/svccfg/svccfg_libscf.c | 215 |
2 files changed, 140 insertions, 77 deletions
diff --git a/usr/src/cmd/svc/svccfg/svccfg.h b/usr/src/cmd/svc/svccfg/svccfg.h index bf73e5202f..28d6b42ffb 100644 --- a/usr/src/cmd/svc/svccfg/svccfg.h +++ b/usr/src/cmd/svc/svccfg/svccfg.h @@ -55,6 +55,7 @@ extern "C" { #define SCI_FORCE 0x20 /* Override-import. */ #define SCI_KEEP 0x40 /* Don't delete when SCI_FORCEing */ #define SCI_NOSNAP 0x80 /* Don't take last-import snapshot */ +#define SCI_DELAYENABLE 0x100 /* Delay the general/enable property */ /* Flags for lscf_service_export() */ #define SCE_ALL_VALUES 0x01 /* Include all property values */ @@ -244,6 +245,7 @@ typedef struct scf_callback { int sc_service; /* True if sc_parent is a service. */ uint_t sc_flags; pgroup_t *sc_general; /* pointer to general property group */ + property_t *sc_enable; /* pointer to enable property */ const char *sc_source_fmri; const char *sc_target_fmri; diff --git a/usr/src/cmd/svc/svccfg/svccfg_libscf.c b/usr/src/cmd/svc/svccfg/svccfg_libscf.c index 52887a370c..2440306534 100644 --- a/usr/src/cmd/svc/svccfg/svccfg_libscf.c +++ b/usr/src/cmd/svc/svccfg/svccfg_libscf.c @@ -1500,6 +1500,79 @@ stash_scferror(scf_callback_t *cbp) return (stash_scferror_err(cbp, scf_error())); } +/* + * Create or update a snapshot of inst. snap is a required scratch object. + * + * Returns + * 0 - success + * ECONNABORTED - repository connection broken + * EPERM - permission denied + * ENOSPC - configd is out of resources + * ECANCELED - inst was deleted + * -1 - unknown libscf error (message printed) + */ +static int +take_snap(scf_instance_t *inst, const char *name, scf_snapshot_t *snap) +{ +again: + if (scf_instance_get_snapshot(inst, name, snap) == 0) { + if (_scf_snapshot_take_attach(inst, snap) != 0) { + switch (scf_error()) { + case SCF_ERROR_CONNECTION_BROKEN: + case SCF_ERROR_PERMISSION_DENIED: + case SCF_ERROR_NO_RESOURCES: + return (scferror2errno(scf_error())); + + case SCF_ERROR_NOT_SET: + case SCF_ERROR_INVALID_ARGUMENT: + default: + bad_error("_scf_snapshot_take_attach", + scf_error()); + } + } + } else { + switch (scf_error()) { + case SCF_ERROR_NOT_FOUND: + break; + + case SCF_ERROR_DELETED: + case SCF_ERROR_CONNECTION_BROKEN: + return (scferror2errno(scf_error())); + + case SCF_ERROR_HANDLE_MISMATCH: + case SCF_ERROR_NOT_BOUND: + case SCF_ERROR_INVALID_ARGUMENT: + case SCF_ERROR_NOT_SET: + default: + bad_error("scf_instance_get_snapshot", scf_error()); + } + + if (_scf_snapshot_take_new(inst, name, snap) != 0) { + switch (scf_error()) { + case SCF_ERROR_EXISTS: + goto again; + + case SCF_ERROR_CONNECTION_BROKEN: + case SCF_ERROR_NO_RESOURCES: + case SCF_ERROR_PERMISSION_DENIED: + return (scferror2errno(scf_error())); + + default: + scfwarn(); + return (-1); + + case SCF_ERROR_NOT_SET: + case SCF_ERROR_INTERNAL: + case SCF_ERROR_INVALID_ARGUMENT: + case SCF_ERROR_HANDLE_MISMATCH: + bad_error("_scf_snapshot_take_new", + scf_error()); + } + } + } + + return (0); +} /* * Import. These functions import a bundle into the repository. @@ -1527,9 +1600,12 @@ lscf_property_import(void *v, void *pvt) scf_value_t *val; scf_type_t tp; - if (lcbdata->sc_flags & SCI_NOENABLED && - strcmp(p->sc_property_name, SCF_PROPERTY_ENABLED) == 0) + if ((lcbdata->sc_flags & SCI_NOENABLED || + lcbdata->sc_flags & SCI_DELAYENABLE) && + strcmp(p->sc_property_name, SCF_PROPERTY_ENABLED) == 0) { + lcbdata->sc_enable = p; return (UU_WALK_NEXT); + } entr = scf_entry_create(lcbdata->sc_handle); if (entr == NULL) { @@ -1796,6 +1872,7 @@ props: cbdata.sc_parent = imp_pg; cbdata.sc_flags = lcbdata->sc_flags; cbdata.sc_trans = imp_tx; + cbdata.sc_enable = NULL; if (scf_transaction_start(imp_tx, imp_pg) != 0) { switch (scf_error()) { @@ -1839,6 +1916,54 @@ props: return (UU_WALK_ERROR); } + if ((lcbdata->sc_flags & SCI_DELAYENABLE) && cbdata.sc_enable) { + cbdata.sc_flags = cbdata.sc_flags & (~SCI_DELAYENABLE); + + /* + * take the snapshot running snapshot then + * import the stored general/enable property + */ + r = take_snap(ent, snap_running, imp_rsnap); + switch (r) { + case 0: + break; + + case ECONNABORTED: + warn(gettext("Could not take %s snapshot on import " + "(repository connection broken).\n"), + snap_running); + lcbdata->sc_err = r; + return (UU_WALK_ERROR); + case ECANCELED: + warn(emsg_deleted); + lcbdata->sc_err = r; + return (UU_WALK_ERROR); + + case EPERM: + warn(gettext("Could not take %s snapshot " + "(permission denied).\n"), snap_running); + lcbdata->sc_err = r; + return (UU_WALK_ERROR); + + case ENOSPC: + warn(gettext("Could not take %s snapshot" + "(repository server out of resources).\n"), + snap_running); + lcbdata->sc_err = r; + return (UU_WALK_ERROR); + + default: + bad_error("take_snap", r); + } + + r = lscf_property_import(cbdata.sc_enable, &cbdata); + if (r != UU_WALK_NEXT) { + if (r != UU_WALK_ERROR) + bad_error("lscf_property_import", r); + return (EINVAL); + } + } + r = scf_transaction_commit(imp_tx); switch (r) { case 1: @@ -1915,7 +2040,8 @@ lscf_import_instance_pgs(scf_instance_t *inst, const char *target_fmri, cbdata.sc_handle = scf_instance_handle(inst); cbdata.sc_parent = inst; cbdata.sc_service = 0; - cbdata.sc_general = 0; + cbdata.sc_general = NULL; + cbdata.sc_enable = NULL; cbdata.sc_flags = flags; cbdata.sc_source_fmri = iinst->sc_fmri; cbdata.sc_target_fmri = target_fmri; @@ -1930,6 +2056,15 @@ lscf_import_instance_pgs(scf_instance_t *inst, const char *target_fmri, if ((flags & SCI_GENERALLAST) && cbdata.sc_general) { cbdata.sc_flags = flags & (~SCI_GENERALLAST); + /* + * If importing with the SCI_NOENABLED flag then + * skip the delay, but if not then add the delay + * of the enable property. + */ + if (!(cbdata.sc_flags & SCI_NOENABLED)) { + cbdata.sc_flags |= SCI_DELAYENABLE; + } + if (entity_pgroup_import(cbdata.sc_general, &cbdata) != UU_WALK_NEXT) return (cbdata.sc_err); @@ -5006,80 +5141,6 @@ upgrade_props(void *ent, scf_snaplevel_t *running, scf_snaplevel_t *snpl, } /* - * Create or update a snapshot of inst. snap is a required scratch object. - * - * Returns - * 0 - success - * ECONNABORTED - repository connection broken - * EPERM - permission denied - * ENOSPC - configd is out of resources - * ECANCELED - inst was deleted - * -1 - unknown libscf error (message printed) - */ -static int -take_snap(scf_instance_t *inst, const char *name, scf_snapshot_t *snap) -{ -again: - if (scf_instance_get_snapshot(inst, name, snap) == 0) { - if (_scf_snapshot_take_attach(inst, snap) != 0) { - switch (scf_error()) { - case SCF_ERROR_CONNECTION_BROKEN: - case SCF_ERROR_PERMISSION_DENIED: - case SCF_ERROR_NO_RESOURCES: - return (scferror2errno(scf_error())); - - case SCF_ERROR_NOT_SET: - case SCF_ERROR_INVALID_ARGUMENT: - default: - bad_error("_scf_snapshot_take_attach", - scf_error()); - } - } - } else { - switch (scf_error()) { - case SCF_ERROR_NOT_FOUND: - break; - - case SCF_ERROR_DELETED: - case SCF_ERROR_CONNECTION_BROKEN: - return (scferror2errno(scf_error())); - - case SCF_ERROR_HANDLE_MISMATCH: - case SCF_ERROR_NOT_BOUND: - case SCF_ERROR_INVALID_ARGUMENT: - case SCF_ERROR_NOT_SET: - default: - bad_error("scf_instance_get_snapshot", scf_error()); - } - - if (_scf_snapshot_take_new(inst, name, snap) != 0) { - switch (scf_error()) { - case SCF_ERROR_EXISTS: - goto again; - - case SCF_ERROR_CONNECTION_BROKEN: - case SCF_ERROR_NO_RESOURCES: - case SCF_ERROR_PERMISSION_DENIED: - return (scferror2errno(scf_error())); - - default: - scfwarn(); - return (-1); - - case SCF_ERROR_NOT_SET: - case SCF_ERROR_INTERNAL: - case SCF_ERROR_INVALID_ARGUMENT: - case SCF_ERROR_HANDLE_MISMATCH: - bad_error("_scf_snapshot_take_new", - scf_error()); - } - } - } - - return (0); -} - -/* * Import an instance. If it doesn't exist, create it. If it has * a last-import snapshot, upgrade its properties. Finish by updating its * last-import snapshot. If it doesn't have a last-import snapshot then it |
