Пример #1
0
static void
test_df4(void **state)
{
    struct state *st = (*state);
    const char *xml1 = "<df xmlns=\"urn:libyang:tests:defaults\">"
                        "<b1_2>x</b1_2><foo>42</foo><b1_1>42</b1_1>"
                      "</df><hidden xmlns=\"urn:libyang:tests:defaults\">"
                        "<foo>42</foo><baz>42</baz></hidden>";
    const char *xml2 = "<df xmlns=\"urn:libyang:tests:defaults\" "
                          "xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\">"
                        "<b2>1</b2><foo ncwd:default=\"true\">42</foo>"
                      "</df><hidden xmlns=\"urn:libyang:tests:defaults\" "
                          "xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\">"
                        "<foo ncwd:default=\"true\">42</foo><baz ncwd:default=\"true\">42</baz></hidden>";
    const char *xml3 = "<df xmlns=\"urn:libyang:tests:defaults\" "
                          "xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\">"
                        "<s2a>1</s2a><foo ncwd:default=\"true\">42</foo>"
                      "</df><hidden xmlns=\"urn:libyang:tests:defaults\" "
                          "xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\">"
                        "<foo ncwd:default=\"true\">42</foo><baz ncwd:default=\"true\">42</baz></hidden>";

    st->dt = lyd_new(NULL, st->mod, "df");
    assert_ptr_not_equal(st->dt, NULL);

    /* select2 - s2a */
    assert_ptr_not_equal(lyd_new_leaf(st->dt, NULL, "s2a", "1"), NULL);
    assert_int_equal(lyd_validate(&(st->dt), LYD_OPT_CONFIG), 0);
    assert_int_equal(lyd_wd_add(NULL, &(st->dt), LYD_OPT_CONFIG | LYD_WD_ALL_TAG), 0);

    assert_int_equal(lyd_print_mem(&(st->xml), st->dt, LYD_XML, LYP_WITHSIBLINGS), 0);
    assert_ptr_not_equal(st->xml, NULL);
    assert_string_equal(st->xml, xml3);

    assert_int_equal(lyd_wd_cleanup(&(st->dt), 0), 0);
    free(st->xml);
    st->xml = NULL;

    /* select2 - s2b - b2 */
    assert_ptr_not_equal(lyd_new_leaf(st->dt, NULL, "b2", "1"), NULL);
    assert_int_equal(lyd_validate(&(st->dt), LYD_OPT_CONFIG), 0);
    assert_int_equal(lyd_wd_add(NULL, &(st->dt), LYD_OPT_CONFIG | LYD_WD_ALL_TAG), 0);

    assert_int_equal(lyd_print_mem(&(st->xml), st->dt, LYD_XML, LYP_WITHSIBLINGS), 0);
    assert_ptr_not_equal(st->xml, NULL);
    assert_string_equal(st->xml, xml2);

    assert_int_equal(lyd_wd_cleanup(&(st->dt), 0), 0);
    free(st->xml);
    st->xml = NULL;

    /* select2 - s2b - b1 */
    assert_ptr_not_equal(lyd_new_leaf(st->dt, NULL, "b1_2", "x"), NULL);
    assert_int_equal(lyd_validate(&(st->dt), LYD_OPT_CONFIG), 0);
    assert_int_equal(lyd_wd_add(NULL, &(st->dt), LYD_OPT_CONFIG | LYD_WD_ALL), 0);

    assert_int_equal(lyd_print_mem(&(st->xml), st->dt, LYD_XML, LYP_WITHSIBLINGS), 0);
    assert_ptr_not_equal(st->xml, NULL);
    assert_string_equal(st->xml, xml1);
}
Пример #2
0
static void
test_df3(void **state)
{
    struct state *st = (*state);
    struct lyd_node *node;
    const char *xml1 = "<df xmlns=\"urn:libyang:tests:defaults\">"
                        "<a1>1</a1>"
                        "<foo>42</foo><b1_1>42</b1_1>"
                      "</df><hidden xmlns=\"urn:libyang:tests:defaults\">"
                        "<foo>42</foo><baz>42</baz></hidden>";
    const char *xml2 = "<df xmlns=\"urn:libyang:tests:defaults\" "
                          "xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\">"
                        "<c><x ncwd:default=\"true\">42</x></c>"
                        "<foo ncwd:default=\"true\">42</foo><b1_1 ncwd:default=\"true\">42</b1_1>"
                      "</df><hidden xmlns=\"urn:libyang:tests:defaults\" "
                          "xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\">"
                        "<foo ncwd:default=\"true\">42</foo><baz ncwd:default=\"true\">42</baz></hidden>";

    st->dt = lyd_new(NULL, st->mod, "df");
    assert_ptr_not_equal(st->dt, NULL);

    /* select - c */
    assert_ptr_not_equal((node = lyd_new(st->dt, NULL, "c")), NULL);
    assert_int_equal(lyd_validate(&(st->dt), LYD_OPT_CONFIG), 0);
    assert_int_equal(lyd_wd_add(NULL, &(st->dt), LYD_OPT_CONFIG | LYD_WD_ALL_TAG), 0);

    assert_int_equal(lyd_print_mem(&(st->xml), st->dt, LYD_XML, LYP_WITHSIBLINGS), 0);
    assert_ptr_not_equal(st->xml, NULL);
    assert_string_equal(st->xml, xml2);

    assert_int_equal(lyd_wd_cleanup(&(st->dt), 0), 0);
    free(st->xml);
    st->xml = NULL;

    /* select - a */
    assert_ptr_not_equal(lyd_new_leaf(st->dt, NULL, "a1", "1"), NULL);
    assert_int_equal(lyd_validate(&(st->dt), LYD_OPT_CONFIG), 0);
    assert_int_equal(lyd_wd_add(NULL, &(st->dt), LYD_OPT_CONFIG | LYD_WD_ALL), 0);

    assert_int_equal(lyd_print_mem(&(st->xml), st->dt, LYD_XML, LYP_WITHSIBLINGS), 0);
    assert_ptr_not_equal(st->xml, NULL);
    assert_string_equal(st->xml, xml1);
}
Пример #3
0
/**
 * @brief Import content of the specified datastore for the given module from a file
 * referenced by the descriptor 'fd_in'
 */
static int
srcfg_import_datastore(struct ly_ctx *ly_ctx, int fd_in, const char *module_name, srcfg_datastore_t datastore,
                       LYD_FORMAT format, bool permanent)
{
    int rc = SR_ERR_INTERNAL;
    unsigned i = 0;
    struct lyd_node *new_data_tree = NULL;
    struct lyd_node *current_data_tree = NULL;
    struct lyd_difflist *diff = NULL;
    char *first_xpath = NULL, *second_xpath = NULL;
    char *input_data = NULL;
    int ret = 0;
    struct stat info;

    CHECK_NULL_ARG2(ly_ctx, module_name);

    /* parse input data */
    ret = fstat(fd_in, &info);
    CHECK_NOT_MINUS1_LOG_GOTO(ret, rc, SR_ERR_INTERNAL, cleanup,
                              "Unable to obtain input file info: %s.", sr_strerror_safe(errno));
    ly_errno = LY_SUCCESS;
    if (S_ISREG(info.st_mode)) {
        /* load (using mmap) and parse the input data in one step */
        new_data_tree = lyd_parse_fd(ly_ctx, fd_in, format, LYD_OPT_STRICT | LYD_OPT_CONFIG);
    } else { /* most likely STDIN */
        /* load input data into the memory first */
        ret = srcfg_read_file_content(fd_in, &input_data);
        CHECK_RC_MSG_GOTO(ret, cleanup, "Unable to read the input data.");
        /* parse the input data stored inside memory buffer */
        new_data_tree = lyd_parse_mem(ly_ctx, input_data, format, LYD_OPT_STRICT | LYD_OPT_CONFIG);
    }
    if (NULL == new_data_tree && LY_SUCCESS != ly_errno) {
        SR_LOG_ERR("Unable to parse the input data: %s", ly_errmsg());
        goto cleanup;
    }

    /* validate input data */
    if (NULL != new_data_tree) {
        ret = lyd_validate(&new_data_tree, LYD_OPT_STRICT | LYD_OPT_CONFIG | LYD_WD_IMPL_TAG);
        CHECK_ZERO_LOG_GOTO(ret, rc, SR_ERR_INTERNAL, cleanup, "Input data are not valid: %s", ly_errmsg());
    }

    /* remove default nodes */
    lyd_wd_cleanup(&new_data_tree, 0);

    /* get data tree of currently stored configuration */
    rc = srcfg_get_module_data(ly_ctx, module_name, &current_data_tree);
    if (SR_ERR_OK != rc) {
        goto cleanup;
    }

    /* get the list of changes made by the user */
    diff = lyd_diff(current_data_tree, new_data_tree, 0);
    if (NULL == diff) {
        SR_LOG_ERR("Unable to get the list of changes: %s", ly_errmsg());
        goto cleanup;
    }

    /* iterate over the list of differences and for each issue corresponding Sysrepo command(s) */
    while (diff->type && LYD_DIFF_END != diff->type[i]) {
        if (NULL != diff->first[i]) {
            first_xpath = lyd_path(diff->first[i]);
            if (NULL == first_xpath) {
                SR_LOG_ERR("Error returned from lyd_path: %s.", ly_errmsg());
                goto cleanup;
            }
        }
        if (NULL != diff->second[i]) {
            second_xpath = lyd_path(diff->second[i]);
            if (NULL == second_xpath) {
                free(first_xpath);
                first_xpath = NULL;
                SR_LOG_ERR("Error returned from lyd_path: %s.", ly_errmsg());
                goto cleanup;
            }
        }
        switch (diff->type[i]) {
            case LYD_DIFF_DELETED:
                SR_LOG_DBG("<LYD_DIFF_DELETED> node: %s", first_xpath);
                rc = srcfg_convert_lydiff_deleted(first_xpath);
                break;
            case LYD_DIFF_CHANGED:
                SR_LOG_DBG("<LYD_DIFF_CHANGED> orig: %s, new: %s", first_xpath, second_xpath);
                rc = srcfg_convert_lydiff_changed(first_xpath, diff->second[i]);
                break;
            case LYD_DIFF_MOVEDAFTER1:
                SR_LOG_DBG("<LYD_DIFF_MOVEDAFTER1> moved: %s, after: %s", first_xpath, second_xpath);
                rc = srcfg_convert_lydiff_movedafter(first_xpath, second_xpath);
                break;
            case LYD_DIFF_CREATED:
                SR_LOG_DBG("<LYD_DIFF_CREATED> parent: %s, new node: %s", first_xpath, second_xpath);
                rc = srcfg_convert_lydiff_created(diff->second[i]);
                break;
            case LYD_DIFF_MOVEDAFTER2:
                SR_LOG_DBG("<LYD_DIFF_MOVEDAFTER2> after: %s, this new node was inserted: %s", first_xpath, second_xpath);
                rc = srcfg_convert_lydiff_movedafter(second_xpath, first_xpath);
                break;
            default:
                assert(0 && "not reachable");
        }
        free(first_xpath);
        free(second_xpath);
        first_xpath = second_xpath = NULL;
        if (SR_ERR_OK != rc) {
            goto cleanup;
        }
        ++i;
    }
    if (0 == i) {
        SR_LOG_DBG_MSG("No changes were made.");
    } else {
        /* commit the changes */
        rc = sr_commit(srcfg_session);
        if (SR_ERR_OK != rc) {
            SR_LOG_ERR("Error returned from sr_commit: %s.", sr_strerror(rc));
            goto cleanup;
        }
        if (SRCFG_STORE_RUNNING == datastore && permanent) {
            /* copy running datastore data into the startup datastore */
            rc = sr_copy_config(srcfg_session, module_name, SR_DS_RUNNING, SR_DS_STARTUP);
            if (SR_ERR_OK != rc) {
                SR_LOG_ERR("Error returned from sr_copy_config: %s.", sr_strerror(rc));
                goto cleanup;
            }
        }
    }

    rc = SR_ERR_OK;

cleanup:
    if (NULL != diff) {
        lyd_free_diff(diff);
    }
    if (NULL != current_data_tree) {
        lyd_free_withsiblings(current_data_tree);
    }
    if (NULL != new_data_tree) {
        lyd_free_withsiblings(new_data_tree);
    }
    if (input_data) {
        free(input_data);
    }
    return rc;
}
Пример #4
0
/**
 * @brief Get complete libyang data tree of a specified module from sysrepo.
 */
static int
srcfg_get_module_data(struct ly_ctx *ly_ctx, const char *module_name, struct lyd_node **data_tree)
{
    int rc = SR_ERR_OK, ret = 0;
    sr_val_t *value = NULL;
    sr_val_iter_t *iter = NULL;
    struct lyd_node *node = NULL;
    const struct lys_node *schema = NULL;
    char query[PATH_MAX] = { 0, };
    char *string_val = NULL;

    snprintf(query, PATH_MAX, "/%s:*//.", module_name);
    rc = sr_get_items_iter(srcfg_session, query, &iter);
    if (SR_ERR_OK != rc) {
        SR_LOG_ERR("Error by sr_get_items_iter: %s", sr_strerror(rc));
        goto cleanup;
    }

    *data_tree = NULL;
    ly_errno = LY_SUCCESS;
    ly_diminish_errors = true;
    while (SR_ERR_OK == (rc = sr_get_item_next(srcfg_session, iter, &value))) {
        ly_diminish_errors = false;
        if (NULL == value) {
            goto next;
        }
        /* get node schema */
        schema = ly_ctx_get_node2(ly_ctx, NULL, value->xpath, 0);
        if (!schema) {
            SR_LOG_ERR("Error by ly_ctx_get_node2: %s", ly_errmsg());
            goto fail;
        }

        /* skip default values */
        if (schema->nodetype == LYS_LEAF && value->dflt) {
            goto next;
        }

        /* skip non-presence containers */
        if (value->type == SR_CONTAINER_T) {
            goto next;
        }

        /* convert value to string */
        rc = sr_val_to_str(value, schema, &string_val);
        if (SR_ERR_OK != rc) {
            SR_LOG_ERR("Error by sr_val_to_str: %s", sr_strerror(rc));
            goto fail;
        }

        /* add node to data tree */
        ly_errno = LY_SUCCESS;
        node = lyd_new_path(*data_tree, ly_ctx, value->xpath, string_val, LYD_PATH_OPT_UPDATE);
        if (!node && LY_SUCCESS != ly_errno) {
            SR_LOG_ERR("Error by lyd_new_path: %s", ly_errmsg());
            goto fail;
        }
        if (NULL == *data_tree) {
            *data_tree = node;
        }
next:
        /* cleanup before next iteration */
        if (NULL != string_val) {
            free(string_val);
            string_val = NULL;
        }
        if (NULL != value) {
            sr_free_val(value);
            value = NULL;
        }
        ly_diminish_errors = true;
    }
    ly_diminish_errors = false;

    if (SR_ERR_NOT_FOUND == rc) {
        rc = SR_ERR_OK;
    }
    if (SR_ERR_OK == rc) {
        if (NULL != *data_tree) {
            /* validate returned data, but most importantly resolve leafrefs */
            ret = lyd_validate(data_tree, LYD_OPT_STRICT | LYD_OPT_CONFIG | LYD_WD_IMPL_TAG);
            CHECK_ZERO_LOG_GOTO(ret, rc, SR_ERR_INTERNAL, fail, "Received data tree from sysrepo is not valid: %s", ly_errmsg());
            /* remove default nodes added by validation */
            lyd_wd_cleanup(data_tree, 0);
        }
        goto cleanup;
    }

fail:
    rc = SR_ERR_INTERNAL;
    if (NULL != *data_tree) {
        lyd_free_withsiblings(*data_tree);
        *data_tree = NULL;
    }

cleanup:
    if (NULL != string_val) {
        free(string_val);
    }
    if (NULL != value) {
        sr_free_val(value);
    }
    if (NULL != iter) {
        sr_free_val_iter(iter);
    }
    return rc;
}