Beispiel #1
0
/********************************************************************
* FUNCTION dump_error_info
*
* Dump the error-info struct
*
* INPUTS:
*   errinfo == rpc_err_info_t struct to dump
*
*********************************************************************/
static void
    dump_error_info (const rpc_err_info_t  *errinfo)
{
    const xmlChar *prefix;

    log_write("\n  error-info: %s T:%s = ", 
           (errinfo->name) ? (const char *)errinfo->name : "--",
           tk_get_btype_sym(errinfo->val_btype));

    if (errinfo->isqname) {
        prefix = xmlns_get_ns_prefix(errinfo->val_nsid);
        log_write("%s:%s", 
                  (prefix) ? prefix : (const xmlChar *)"--",
                  (errinfo->v.strval) ? 
                  (const char *)errinfo->v.strval : "--");
        return;
    }

    switch (errinfo->val_btype) {
    case NCX_BT_BINARY:
    case NCX_BT_STRING:
    case NCX_BT_INSTANCE_ID:
        log_write("%s", (errinfo->v.strval) ? 
               (const char *)errinfo->v.strval : "--");
        break;
    case NCX_BT_BOOLEAN:
        SET_ERROR(ERR_NCX_OPERATION_NOT_SUPPORTED);
        /***/
        break;
    case NCX_BT_INT8:
    case NCX_BT_INT16:
    case NCX_BT_INT32:
    case NCX_BT_INT64:
    case NCX_BT_UINT8:
    case NCX_BT_UINT16:
    case NCX_BT_UINT32:
    case NCX_BT_UINT64:
    case NCX_BT_DECIMAL64:
    case NCX_BT_FLOAT64:
        ncx_printf_num(&errinfo->v.numval, errinfo->val_btype);
        break;
    default:
        val_dump_value((val_value_t *)errinfo->v.cpxval,
                       NCX_DEF_INDENT*2);
    }

}  /* dump_error_info */
Beispiel #2
0
/********************************************************************
* FUNCTION parse_parm
* 
* Parse, and fill one val_value_t struct during
* processing of a parmset
*
* Error messages are printed by this function!!
* Do not duplicate error messages upon error return
*
*
* INPUTS:
*   tkc == token chain
*   val == container val to fill in
*   keepvals == TRUE to save existing parms in 'ps', as needed
*               FALSE to overwrite old parms in 'ps', as needed
*
* RETURNS:
*   status of the operation
*********************************************************************/
static status_t 
    parse_parm (tk_chain_t  *tkc,
                val_value_t *val,
                boolean keepvals)
{
    obj_template_t         *obj;
    const xmlChar          *modname;
    val_value_t            *curparm, *newparm;
    status_t                res;
    ncx_iqual_t             iqual;
    boolean                 match, usewarning, isdefault;

    
    /* get the next token, which must be a TSTRING
     * representing the parameter name 
     */
    if (TK_CUR_TYP(tkc) != TK_TT_TSTRING) {
        res = ERR_NCX_WRONG_TKTYPE;
        ncx_conf_exp_err(tkc, res, "parameter name");
        return res;
    }

    curparm = NULL;
    usewarning = ncx_warning_enabled(ERR_NCX_CONF_PARM_EXISTS);

    /* check if this TSTRING is a parameter in this parmset
     * make sure to always check for prefix:identifier
     * This is automatically processed in tk.c
     */
    if (TK_CUR_MOD(tkc)) {
        modname = xmlns_get_module
            (xmlns_find_ns_by_prefix(TK_CUR_MOD(tkc)));
        if (modname) {
            curparm = val_find_child(val, 
                                     modname,
                                     TK_CUR_VAL(tkc));
        }
    }  else {
        curparm = val_find_child(val, 
                                 val_get_mod_name(val),
                                 TK_CUR_VAL(tkc));
    }
        
    if (curparm) {
        obj = curparm->obj;
    } else {
        obj = obj_find_child(val->obj, 
                             TK_CUR_MOD(tkc),
                             TK_CUR_VAL(tkc));
    }
    if (!obj) {
        res = ERR_NCX_UNKNOWN_PARM;
        if (TK_CUR_MOD(tkc)) {
            log_error("\nError: parameter '%s:%s' not found",
                      TK_CUR_MOD(tkc),
                      TK_CUR_VAL(tkc));
        } else {
            log_error("\nError: parameter '%s' not found",
                      TK_CUR_VAL(tkc));
        }
        ncx_conf_exp_err(tkc, res, "parameter name");
        return res;
    }

    /* got a valid parameter name, now create a new parm
     * even if it may not be kept.  There are corner-cases
     * that require the new value be parsed before knowing
     * if a parm value is a duplicate or not
     */
    newparm = val_new_value();
    if (!newparm) {
        res = ERR_INTERNAL_MEM;
        ncx_print_errormsg(tkc, NULL, res);
        return res;
    }
    val_init_from_template(newparm, obj);

    /* parse the parameter value */
    res = parse_val(tkc, obj, newparm);
    if (res != NO_ERR) {
        val_free_value(newparm);
        return res;
    }

    /* check if a potential current value exists, or just
     * add the newparm to the parmset
     */
    if (curparm) {
        isdefault = val_set_by_default(curparm);
        iqual = obj_get_iqualval(obj);
        if (iqual == NCX_IQUAL_ONE || iqual == NCX_IQUAL_OPT) {
            /* only one allowed, check really a match */
            match = TRUE;
            if (val_has_index(curparm) &&
                !val_index_match(newparm, curparm)) {
                match = FALSE;
            }

            if (!match) {
                val_add_child(newparm, val);
            } else if (isdefault) {
                dlq_remove(curparm);
                val_free_value(curparm);
                val_add_child(newparm, val);
            } else if (keepvals) {
                if (usewarning) {
                    /* keep current value and toss new value */
                    log_warn("\nWarning: Parameter '%s' already exists. "
                             "Not using new value\n", 
                             curparm->name);
                    if (LOGDEBUG2) {
                        val_dump_value(newparm, NCX_DEF_INDENT);
                        log_debug2("\n");
                    }
                }
                val_free_value(newparm);
            } else {
                if (usewarning) {
                    /* replace current value and warn old value tossed */
                    log_warn("\nconf: Parameter '%s' already exists. "
                             "Overwriting with new value\n",
                             curparm->name);
                    if (LOGDEBUG2) {
                        val_dump_value(newparm, NCX_DEF_INDENT);
                        log_debug2("\n");
                    }
                }
                dlq_remove(curparm);
                val_free_value(curparm);
                val_add_child(newparm, val);
            }
        } else {
            /* mutliple instances allowed */
            val_add_child(newparm, val);
        }
    } else {
        val_add_child(newparm, val);
    }

    return NO_ERR;

}  /* parse_parm */
Beispiel #3
0
/********************************************************************
* FUNCTION load_running_config
* 
* Load the NV startup config into the running config
* 
* INPUTS:
*   startup == startup filespec provided by the user
*           == NULL if not set by user 
*              (use default name and specified search path instead)
*   loaded == address of return config loaded flag
*
* OUTPUTS:
*   *loaded == TRUE if some config file was loaded
*
*   The <running> config is loaded from NV-storage,
*   if the NV-storage <startup> config can be found an read
* RETURNS:
*   status
*********************************************************************/
static status_t
    load_running_config (const xmlChar *startup,
                         boolean *loaded)
{
    cfg_template_t  *cfg;
    xmlChar         *fname;
    agt_profile_t   *profile;
    status_t         res;

    res = NO_ERR;
    *loaded = FALSE;
    profile = agt_get_profile();

    cfg = cfg_get_config(NCX_CFG_RUNNING);
    if (!cfg) {
        log_error("\nagt: No running config found!!");
        return SET_ERROR(ERR_INTERNAL_VAL);
    }

    /* use the user-set startup or default filename */
    if (startup) {
        /* relative filespec, use search path */
        fname = ncxmod_find_data_file(startup, FALSE, &res);
    } else {
        /* search for the default startup-cfg.xml filename */
        fname = ncxmod_find_data_file(NCX_DEF_STARTUP_FILE, FALSE, &res);
    }

    /* check if error finding the filespec */
    if (!fname) {
        if (startup) {
            if (res == NO_ERR) {
                res = ERR_NCX_MISSING_FILE;
            }
            log_error("\nError: Startup config file (%s) not found (%s).",
                      startup, get_error_string(res));
            return res;
        } else {
            log_info("\nDefault startup config file (%s) not found."
                     "\n   Booting with default running configuration!\n",
                     NCX_DEF_STARTUP_FILE);
            return NO_ERR;
        }
    } else if (LOGDEBUG2) {
        log_debug2("\nFound startup config: '%s'", fname);
    }
    
    /* try to load the config file that was found or given */
    res = agt_ncx_cfg_load(cfg, CFG_LOC_FILE, fname);
    if (res == ERR_XML_READER_START_FAILED) {
        log_error("\nagt: Error: Could not open startup config file"
                  "\n     (%s)\n", fname);
    } else if (res != NO_ERR) {
        /* if an error is returned then it was a hard error
         * since the startup_error and running_error profile
         * variables have already been accounted for.
         * An error in the setup or in the AGT_RPC_PH_INVOKE phase
         * of the <load-config> operation occurred
         */
        log_error("\nError: load startup config failed (%s)",
                  get_error_string(res));
        if (!dlq_empty(&cfg->load_errQ)) {
            *loaded = TRUE;
        }
    } else {
        /* assume OK or startup and running continue; if 1 or both is not
         * set then the server will exit anyway and the config state
         * will not matter
         */
        profile->agt_config_state = AGT_CFG_STATE_OK;

        *loaded = TRUE;

        boolean errdone = FALSE;
        boolean errcontinue = FALSE;

        if (profile->agt_load_validate_errors) {
            if (profile->agt_startup_error) {
                /* quit if any startup validation errors */
                log_error("\nError: validation errors occurred loading the "
                          "<running> database\n   from NV-storage"
                          " (%s)\n", fname);
                errdone = TRUE;
            } else {
                /* continue if any startup errors */
                log_warn("\nWarning: validation errors occurred loading "
                         "the <running> database\n   from NV-storage"
                         " (%s)\n", fname);
                errcontinue = TRUE;
            }
        }
        if (!errdone && profile->agt_load_rootcheck_errors) {
            if (profile->agt_startup_error) {
                /* quit if any startup root-check validation errors */
                log_error("\nError: root-check validation errors "
                          "occurred loading the <running> database\n"
                          "   from NV-storage (%s)\n", fname);
                errdone = TRUE;
            } else {
                /* continue if any root-check validation errors */
                log_warn("\nWarning: root-check validation errors "
                         "occurred loading the <running> database\n"
                         "   from NV-storage (%s)\n", fname);
                errcontinue = TRUE;
            }
        }
        if (!errdone && profile->agt_load_top_rootcheck_errors) {
            if (profile->agt_running_error) {
                /* quit if any top-level root-check validation errors */
                log_error("\nError: top-node root-check validation errors "
                          "occurred loading the <running> database\n"
                          "   from NV-storage (%s)\n", fname);
                errdone = TRUE;
            } else {
                /* continue if any startup errors */
                log_warn("\nWarning: top-node root-check validation errors "
                         "occurred loading the <running> database\n"
                         "   from NV-storage (%s)\n", fname);
                profile->agt_config_state = AGT_CFG_STATE_BAD;
                errcontinue = TRUE;
            }
        }
        if (!errdone && profile->agt_load_apply_errors) {
            /* quit if any apply-to-running SIL errors */
            errdone = TRUE;
            log_error("\nError: fatal errors "
                      "occurred loading the <running> database "
                      "from NV-storage\n     (%s)\n", fname);
        }

        if (errdone) {
            res = ERR_NCX_OPERATION_FAILED;
        } else if (errcontinue) {
            val_purge_errors_from_root(cfg->root);
            log_info("\nagt: Startup config loaded after pruning error nodes\n"
                     "Source: %s\n", fname);
        } else {
            log_info("\nagt: Startup config loaded OK\n     Source: %s\n",
                     fname);
        }
    }

    if (LOGDEBUG) {
        log_debug("\nContents of %s configuration:", cfg->name);
        val_dump_value(cfg->root, 0);
        log_debug("\n");
    }

    if (fname) {
        m__free(fname);
    }

    return res;

} /* load_running_config */
/********************************************************************
 * FUNCTION process_apply
 * (config mode input received)
 *  Handle the apply command and check if there are edits
 *  to apply to the server.  If so apply the edits.
 *
 * INPUTS:
 *    server_cb == server control block to use
 *    session_cb == session control block to use
 *
 * RETURNS:
 *   status
 *********************************************************************/
static status_t
    process_apply (server_cb_t *server_cb,
                   session_cb_t *session_cb)
{
    if (dlq_empty(&session_cb->config_editQ)) {
        if (LOGDEBUG2) {
            log_debug2("\nSkipping apply, no edits");
        }
        session_cb->config_edit_dirty = FALSE;
        return NO_ERR;
    }

    /* make a dummy config root -- it will not be used; only the child
     * nodes added to this container will be added to the <config>
     * parameter in the <edit-config> operation
     */
    val_value_t *configval = xml_val_new_root(NCX_EL_CONFIG, xmlns_nc_id());
    if (configval == NULL) {
        log_error("\nError: malloc failed");
        return ERR_INTERNAL_MEM;
    }
 
    status_t res = NO_ERR;
    boolean anyedits = FALSE;
    uint32 editcnt = dlq_count(&session_cb->config_editQ);
    
    while (!dlq_empty(&session_cb->config_editQ)) {
        config_edit_t *edit = (config_edit_t *)
            dlq_deque(&session_cb->config_editQ);

        /* compare the edit to the shadow config to see if it
         * represents any change or not   */
        boolean ischange = check_edit(session_cb, edit);

        if (ischange) {
            /** TBD: add to tree and collapse all edits!!! */
            val_add_child(edit->edit_payload, configval);
            edit->edit_payload = NULL;
            anyedits = TRUE;
        } else if (LOGDEBUG3) {
            log_debug3("\nSkipping edit due to no change:\n");
            val_dump_value(edit->edit_payload, 0);
        }
        free_config_edit(edit);
    }

    if (!anyedits) {
        val_free_value(configval);
        return NO_ERR;
    }

    if (server_cb->program_mode == PROG_MODE_SERVER) {
        if (LOGDEBUG) {
            if (editcnt == 1) {
                log_debug("\nApplying 1 edit\n");
            } else {
                log_debug("\nApplying %u edits\n", editcnt);
            }
        }
    } else {
        if (LOGINFO) {
            const xmlChar *sesname = (session_cb->session_cfg)
                ? session_cb->session_cfg->name : NCX_EL_DEFAULT;

            if (editcnt == 1) {
                log_info("\nApplying 1 edit to session '%s'\n", sesname);
            } else {
                log_info("\nApplying %u edits to session '%s'\n", editcnt,
                         sesname);
            }
        }
    }

    session_cb->command_mode = CMD_MODE_CONF_APPLY;
    session_cb->config_edit_dirty = FALSE;

    res = send_edit_config_to_server(server_cb, session_cb, NULL,
                                     configval, TRUE, session_cb->timeout,
                                     OP_DEFOP_MERGE);
    /* configval consumed no matter what! */

    return res;

}  /* process_apply */