1 /*************************************************************************
3 * Copyright 2020 highstreet technologies GmbH and others
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ***************************************************************************/
21 #include "utils/log_utils.h"
22 #include "utils/rand_utils.h"
23 #include "utils/type_utils.h"
24 #include "utils/sys_utils.h"
30 #include "core/session.h"
31 #include "core/framework.h"
35 #define LEAFREF_TOTAL_TEST_ENTRIES 11
42 const struct lys_module **modules;
45 struct lyd_node *operational;
46 struct lyd_node *running;
47 } generate_instance_t;
50 struct lyd_node *operational;
51 struct lyd_node *running;
54 int late_resolve_count;
55 struct lys_node **late_resolve_schema;
56 struct lyd_node **late_resolve_parent_o;
57 struct lyd_node **late_resolve_parent_r;
58 generate_instance_t **late_resolve_instance;
61 static int generate_recursive(generate_job_t *job, generate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r);
62 static int generate_add_leaf(generate_job_t *job, generate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r);
64 static int generate_late_resolve(generate_job_t *job);
65 static int generate_validate(generate_instance_t *instance, int count);
66 static int generate_export_data(generate_job_t *job, const char *running_filename, const char *operational_filename);
68 static int instance_add_module(generate_instance_t *instance, const struct lys_module *module);
69 static int generate_late_resolve_add_leaf(generate_job_t *job, generate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r);
70 static const char* leafref_test_val(int index);
72 static int generate_get_instance_count(const char *path);
73 static char *generate_get_restrict_schema(const char *path);
75 struct lyd_node *datastore_load_external(const char *filename, bool operational) {
77 struct lyd_node *data_tree = 0;
80 if(file_exists(filename)) {
81 LYD_FORMAT format = LYD_JSON;
82 if(strstr(filename, ".xml") != 0) {
86 int flags = LYD_OPT_TRUSTED | LYD_OPT_NOSIBLINGS;
88 flags |= LYD_OPT_DATA;
91 flags |= LYD_OPT_CONFIG;
94 data_tree = lyd_parse_path(session_context, filename, format, flags);
96 log_error("lyd_parse_path failed\n");
104 int datastore_generate_data(const char *running_filename, const char *operational_filename) {
107 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"datastore_generate_data() begin\n"LOG_COLOR_RESET);
112 job.late_resolve_count = 0;
113 job.late_resolve_instance = 0;
114 job.late_resolve_schema = 0;
115 job.late_resolve_parent_o = 0;
116 job.late_resolve_parent_r = 0;
117 job.late_resolving = false;
120 //load pre-populated data
121 for(int i = 0; i < framework_config.datastore_populate.preg_running_count; i++) {
122 char *filename = framework_config.datastore_populate.preg_running[i];
123 struct lyd_node *data = datastore_load_external(filename, false);
125 log_add_verbose(2, "datastore_load_external() could not load %s\n", filename);
128 log_add_verbose(1, "loaded into running %s (%s)\n", filename, data->schema->module->name);
130 int rc = lyd_merge(job.running, data, 0);
132 log_error("lyd_merge failed\n");
135 lyd_free_withsiblings(data);
142 //also load as operational
143 data = datastore_load_external(filename, true);
145 log_add_verbose(2, "datastore_load_external() could not load %s\n", filename);
148 log_add_verbose(1, "loaded into operational %s (%s)\n", filename, data->schema->module->name);
149 if(job.operational) {
150 int rc = lyd_merge(job.operational, data, 0);
152 log_error("lyd_merge failed\n");
155 lyd_free_withsiblings(data);
158 job.operational = data;
163 for(int i = 0; i < framework_config.datastore_populate.preg_operational_count; i++) {
164 char *filename = framework_config.datastore_populate.preg_operational[i];
165 struct lyd_node *data = datastore_load_external(filename, true);
167 log_add_verbose(2, "datastore_load_external() could not load %s\n", filename);
170 log_add_verbose(1, "loaded into operational %s (%s)\n", filename, data->schema->module->name);
171 if(job.operational) {
172 int rc = lyd_merge(job.operational, data, 0);
174 log_error("lyd_merge failed\n");
177 lyd_free_withsiblings(data);
180 job.operational = data;
185 if(framework_config.datastore_populate.random_generation_enabled) {
187 int instance_count = datastore_schema_get_xpaths(&xpaths);
188 if(instance_count < 0) {
189 log_error("datastore_schema_get_xpaths failed\n");
190 return NTS_ERR_FAILED;
193 //exclude pre-populated modules
194 struct lyd_node *elem;
195 LY_TREE_FOR(job.operational, elem) {
196 for(int i = 0; i < instance_count; i++) {
197 if(strstr(xpaths[i], elem->schema->module->name) == (xpaths[i] + 1)) { //xpaths[i] is "/module:container"
201 for(int j = i; j < instance_count; j++) {
202 xpaths[j] = xpaths[j + 1];
210 generate_instance_t *instance = (generate_instance_t *)malloc(sizeof(generate_instance_t) * instance_count);
212 log_error("bad malloc\n");
213 for(int i = 0; i < instance_count; i++) {
217 return NTS_ERR_FAILED;
221 //RANDOM generate everything
222 for(int i = 0; i < instance_count; i++) {
223 log_add_verbose(1, "generating "LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET" data...\n", xpaths[i]);
225 struct lys_node *schema_node = (struct lys_node *)ly_ctx_get_node(session_context, 0, xpaths[i], 0);
226 if(schema_node == 0) {
227 log_error("ly_ctx_get_node failed for %s\n", xpaths[i]);
228 return NTS_ERR_FAILED;
231 if(schema_node == 0) {
232 log_add_verbose(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET);
233 log_error("ly_ctx_get_node failed for %s\n", xpaths[i]);
234 return NTS_ERR_FAILED;
237 if(!schema_node->module->implemented) {
238 log_add_verbose(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET);
239 log_error("module is not implemented for %s\n", xpaths[i]);
240 return NTS_ERR_FAILED;
243 if((schema_node->flags & LYS_STATUS_DEPRC) != 0) {
244 log_add_verbose(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET);
245 log_error("module is deprecated for %s\n", xpaths[i]);
246 return NTS_ERR_FAILED;
249 //populate current instance vals
250 instance[i].init = 0;
251 instance[i].xpath = strdup(xpaths[i]);
252 instance[i].modules = 0;
253 instance[i].mod_count = 0;
254 instance[i].operational = 0;
255 instance[i].running = 0;
257 //do the actual population
258 int rc = generate_recursive(&job, &instance[i], schema_node, 0, 0);
259 if(rc != NTS_ERR_OK) {
260 log_error("generate_recursive failed instance %d with xpath %s\n", i, instance[i].xpath);
265 //link everything so we would be able to find everything in late-resolve
266 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"datastore_generate_data() done generating, now linking... (%d root nodes)\n"LOG_COLOR_RESET, instance_count);
267 for(int i = 0; i < instance_count; i++) {
269 if(instance[i].operational) {
270 if(job.operational) {
271 int rc = lyd_insert_sibling(&job.operational, instance[i].operational);
273 log_error("lyd_insert_sibling\n");
274 return NTS_ERR_FAILED;
278 job.operational = instance[i].operational;
282 if(instance[i].running) {
284 int rc = lyd_insert_sibling(&job.running, instance[i].running);
286 log_error("lyd_insert_sibling\n");
287 return NTS_ERR_FAILED;
291 job.running = instance[i].running;
297 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"datastore_generate_data() starting late-resolve process...\n"LOG_COLOR_RESET);
298 if(job.late_resolve_count) {
299 int rc = generate_late_resolve(&job);
300 if(rc != NTS_ERR_OK) {
301 log_error("generate_late_resolve failed\n");
306 //validate data and remove invalid nodes
307 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"datastore_generate_data() validating\n"LOG_COLOR_RESET);
308 int rc = generate_validate(instance, instance_count);
309 if(rc != NTS_ERR_OK) {
310 log_error("generate_validate failed\n");
314 for(int i = 0; i < instance_count; i++) {
315 log_add(1, "%d ", i);
317 free(instance[i].modules);
318 free(instance[i].xpath);
323 free(job.late_resolve_instance);
324 free(job.late_resolve_schema);
325 free(job.late_resolve_parent_o);
326 free(job.late_resolve_parent_r);
329 //export generated data
330 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"datastore_generate_data() exporting data\n"LOG_COLOR_RESET);
331 int rc = generate_export_data(&job, running_filename, operational_filename);
332 if(rc != NTS_ERR_OK) {
333 log_error("generate_export_data failed\n");
338 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"datastore_generate_data() cleaning up... "LOG_COLOR_RESET);
341 lyd_free_withsiblings(job.operational);
342 lyd_free_withsiblings(job.running);
345 log_add_verbose(1, LOG_COLOR_BOLD_GREEN"datastore_generate_data() finished\n"LOG_COLOR_RESET);
350 int datastore_generate_external(void) {
352 sprintf(cmd, "%s --generate", framework_arguments.argv[0]);
353 if(system(cmd) == 0) {
357 return NTS_ERR_FAILED;
362 static int generate_recursive(generate_job_t *job, generate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r) {
367 char *resolved_schema_path = lys_path(schema, LYS_PATH_FIRST_PREFIX);
368 bool schema_operational = ((schema->flags & LYS_CONFIG_W) == 0);
370 generate_recursive_rerun_switch:
371 switch(schema->nodetype) {
372 //for container, just add it to the xpath, and iterate it's childeren to further traverse the tree
373 case LYS_CONTAINER: {
376 struct lyd_node *new_parent_o = parent_o;
377 struct lyd_node *new_parent_r = parent_r;
379 new_parent_o = lyd_new(parent_o, schema->module, schema->name);
381 log_error("error creating container operational -> %s\n", schema->name);
382 log_error("ly_error: %s\n", ly_errmsg(session_context));
383 return NTS_ERR_FAILED;
386 if(!schema_operational) {
387 new_parent_r = lyd_new(parent_r, schema->module, schema->name);
389 log_error("error creating container running -> %s\n", schema->name);
390 log_error("ly_error: %s\n", ly_errmsg(session_context));
391 return NTS_ERR_FAILED;
395 if(!instance->init) {
396 instance->init = true;
397 instance->operational = new_parent_o;
398 instance->running = new_parent_r;
401 char mandatory = ' ';
402 if((schema->flags & LYS_MAND_TRUE) != 0) {
405 if((schema->parent) && (schema->parent->nodetype == LYS_CASE)) {
406 if((schema->parent->flags & LYS_MAND_TRUE) != 0) {
410 bool node_operational = ((schema->flags & LYS_CONFIG_W) == 0);
411 char *xpath = lyd_path(new_parent_o);
412 log_add_verbose(1, LOG_COLOR_BOLD_MAGENTA"[%15s] "LOG_COLOR_BOLD_YELLOW"[%c%c]"LOG_COLOR_RESET" %s\n", "CONTAINER", node_operational ? 'O' : 'R', mandatory, xpath);
415 int rc = instance_add_module(instance, schema->module);
416 if(rc != NTS_ERR_OK) {
417 log_error("instance_add_module failed\n");
421 struct lys_node *child = 0;
422 LY_TREE_FOR(schema->child, child) {
423 int rc = generate_recursive(job, instance, child, new_parent_o, new_parent_r);
424 if(rc != NTS_ERR_OK) {
425 log_error("generate_recursive failed\n");
431 //choice does not appear into the data path. get all the avalable choices, and choose a random one
434 struct lys_node_case *choice = (struct lys_node_case *)schema->child;
437 choice = (struct lys_node_case *)choice->next;
440 //select a random choice
441 choice_no = rand_uint16() % choice_no;
444 choice = (struct lys_node_case *)schema->child;
445 while(i < choice_no) {
447 choice = (struct lys_node_case *)choice->next;
450 //after the choice was made, rerun the adding without other tree-searching (will run into a CASE)
451 schema = (struct lys_node *)choice;
452 goto generate_recursive_rerun_switch;
455 //the actual "case" is this node's child, so we skip directly to that
457 //case contains mandatory
459 schema = schema->child;
460 goto generate_recursive_rerun_switch;
470 //get min-max for current list
471 struct lys_node_list *list = (struct lys_node_list *)schema;
472 int min_added = list->min ? list->min : 1;
473 int max_added = list->max ? list->max : 65536;
475 int populating_times = generate_get_instance_count(resolved_schema_path);
476 if(populating_times != 0) {
477 if(min_added < populating_times) {
478 min_added = populating_times;
480 if(min_added > max_added) {
481 min_added = max_added;
482 log_error("min-elements exceeds max-elements for path %s. truncated to %d\n", resolved_schema_path, max_added);
484 log_add_verbose(2, "populating %d times list '%s'\n", min_added, resolved_schema_path);
486 //populate node with the intended number of values
490 struct lyd_node *new_parent_o = parent_o;
491 struct lyd_node *new_parent_r = parent_r;
493 new_parent_o = lyd_new(parent_o, schema->module, schema->name);
495 log_error("error creating list operational -> %s\n", schema->name);
496 log_error("ly_error: %s\n", ly_errmsg(session_context));
497 return NTS_ERR_FAILED;
500 if(!schema_operational) {
501 new_parent_r = lyd_new(parent_r, schema->module, schema->name);
503 log_error("error creating container running -> %s\n", schema->name);
504 log_error("ly_error: %s\n", ly_errmsg(session_context));
505 return NTS_ERR_FAILED;
509 if(!instance->init) {
510 instance->init = true;
511 instance->operational = new_parent_o;
512 instance->running = new_parent_r;
515 char mandatory = ' ';
516 if((schema->flags & LYS_MAND_TRUE) != 0) {
519 if((schema->parent) && (schema->parent->nodetype == LYS_CASE)) {
520 if((schema->parent->flags & LYS_MAND_TRUE) != 0) {
524 bool node_operational = ((schema->flags & LYS_CONFIG_W) == 0);
525 char *xpath = lyd_path(new_parent_o);
526 log_add_verbose(1, LOG_COLOR_BOLD_MAGENTA"[%15s] "LOG_COLOR_BOLD_YELLOW"[%c%c]"LOG_COLOR_RESET" %s\n", "LIST", node_operational ? 'O' : 'R', mandatory, xpath);
529 int rc = instance_add_module(instance, schema->module);
530 if(rc != NTS_ERR_OK) {
531 log_error("instance_add_module failed\n");
535 //populate all list elements below in the tree
536 struct lys_node *child = 0;
537 LY_TREE_FOR(schema->child, child) {
538 int rc = generate_recursive(job, instance, child, new_parent_o, new_parent_r);
539 if(rc != NTS_ERR_OK) {
540 log_error("generate_recursive failed\n");
549 log_add_verbose(2, "not populating list '%s'\n", resolved_schema_path);
555 if(generate_add_leaf(job, instance, schema, parent_o, parent_r) != NTS_ERR_OK) {
556 return NTS_ERR_FAILED;
560 //leaflist is treated the same as a LEAF, but with min/max characteristics of a LIST
562 //get min-max for the current leaflist
563 struct lys_node_leaflist *list = (struct lys_node_leaflist *)schema;
564 int min_added = list->min ? list->min : 1;
565 int max_added = list->max ? list->max : 65536;
567 int populating_times = generate_get_instance_count(resolved_schema_path);
568 if(populating_times != 0) {
569 if(min_added < populating_times) {
570 min_added = populating_times;
572 if(min_added > max_added) {
573 min_added = max_added;
574 log_error("min-elements exceeds max-elements for path %s truncated to %d\n", resolved_schema_path, max_added);
576 log_add_verbose(2, "populating %d times leaflist '%s'\n", min_added, resolved_schema_path);
580 if(generate_add_leaf(job, instance, schema, parent_o, parent_r) != NTS_ERR_OK) {
581 return NTS_ERR_FAILED;
587 log_add_verbose(2, "not populating leaflist '%s'\n", resolved_schema_path);
595 //don't do anything, since we don't want to add this or go further down the tree when we meet them
598 //other node types (grouping, uses, augment, etc just traverse)
600 log_add_verbose(1, "[%15s] %s\n", typeutils_yang_nodetype_to_str(schema->nodetype), resolved_schema_path);
602 //traverse the tree down for any other node types, without adding anything to the path
603 struct lys_node *child = 0;
604 LY_TREE_FOR(schema->child, child) {
605 int rc = generate_recursive(job, instance, child, parent_o, parent_r);
606 if(rc != NTS_ERR_OK) {
613 free(resolved_schema_path);
618 static int generate_add_leaf(generate_job_t *job, generate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r) {
624 int rc = instance_add_module(instance, schema->module);
625 if(rc != NTS_ERR_OK) {
626 log_error("bad schema_instance_add module\n");
630 struct lys_type *type = &((struct lys_node_leaf *)schema)->type;
632 char *data_xpath = lyd_path(parent_o);
633 data_xpath = (char *)realloc(data_xpath, sizeof(char) * (strlen(data_xpath) + 1 + strlen(schema->name) + 1));
635 log_error("lyd_path failed\n");
636 return NTS_ERR_FAILED;
638 strcat(data_xpath, "/");
639 strcat(data_xpath, schema->name);
641 //check whether the value is MANDATORY or not (for logging purposes)
642 char mandatory = ' ';
643 if((schema->flags & LYS_MAND_TRUE) != 0) {
647 if((schema->parent) && (schema->parent->nodetype == LYS_CASE)) {
648 if((schema->parent->flags & LYS_MAND_TRUE) != 0) {
653 bool node_operational = ((schema->flags & LYS_CONFIG_W) == 0);
654 log_add_verbose(1, LOG_COLOR_BOLD_MAGENTA"[%15s] "LOG_COLOR_BOLD_YELLOW"[%c%c]"LOG_COLOR_RESET" %s <-- ", typeutils_yang_type_to_str(type->base), node_operational ? 'O' : 'R', mandatory, data_xpath);
658 char *resolved_schema_path = lys_path(schema, LYS_PATH_FIRST_PREFIX);
659 char *value = generate_get_restrict_schema(resolved_schema_path);
660 free(resolved_schema_path);
662 generate_add_leaf_rerun_switch:
665 if((type->info.uni.count == 0) && (type->der != 0)) {
666 type = &type->der->type;
669 type = &type->info.uni.types[0];
670 goto generate_add_leaf_rerun_switch;
674 struct lyd_node *parent = parent_o;
675 while(parent->parent) {
676 parent = parent->parent;
680 value = lyd_path(parent);
683 goto generate_add_leaf_actual_add;
687 if(rand_bool()) { //if present, add it
688 log_add(1, LOG_COLOR_CYAN"present"LOG_COLOR_RESET"\n");
689 goto generate_add_leaf_actual_add;
692 log_add(1, LOG_COLOR_CYAN"empty"LOG_COLOR_RESET"\n");
697 case LY_TYPE_LEAFREF: {
700 struct lyd_node *new_node = 0;
701 while((new_node == 0) && (index < LEAFREF_TOTAL_TEST_ENTRIES)) {
702 new_node = lyd_new_leaf(parent_o, schema->module, schema->name, leafref_test_val(index));
707 log_error("error on lyd_new_leaf schema %s. didn't work with any temp val\n", schema->name);
708 return NTS_ERR_FAILED;
711 //based on the new_node's path, try to find elements of relative path for the leafref
712 struct ly_set *set = lyd_find_path(new_node, type->info.lref.path);
715 if(set && set->number) {
716 //choose a random schema and get its value
717 static int set_number = 0; //checkAL aici trebuia oare random ?
719 if(set_number >= set->number) {
722 asprintf(&value, "%s", ((struct lyd_node_leaf_list *)set->set.d[set_number])->value_str);
724 log_error("bad asprintf\n");
725 return NTS_ERR_FAILED;
728 int rc = instance_add_module(instance, set->set.d[set_number]->schema->module);
729 if(rc != NTS_ERR_OK) {
730 log_error("bad schema_instance_add module\n");
736 goto generate_add_leaf_actual_add;
739 //adding to late-resolve list, as we don't have any nodes in the leafref path
740 int rc = generate_late_resolve_add_leaf(job, instance, schema, parent_o, parent_r);
741 if(rc != NTS_ERR_OK) {
745 if(!job->late_resolving) {
746 log_add(1, LOG_COLOR_BOLD_YELLOW"added to late-resolve list...\n"LOG_COLOR_RESET);
749 log_add(1, LOG_COLOR_BOLD_YELLOW"REadded to late-resolve list...\n"LOG_COLOR_RESET);
759 value = rand_get_populate_value(type);
761 goto generate_add_leaf_actual_add;
765 generate_add_leaf_actual_add: {
766 //add schema to operational
767 struct lyd_node *new_node = lyd_new_leaf(parent_o, schema->module, schema->name, value);
769 log_error("error on lyd_new_leaf operational: %s\n", ly_errmsg(session_context));
770 return NTS_ERR_FAILED;
773 //print out the value
775 log_add(1, LOG_COLOR_CYAN"'%s'"LOG_COLOR_RESET"\n", value);
781 //if it fits the case, add it also to running
782 if(!node_operational) {
783 struct lyd_node *new_node = lyd_new_leaf(parent_r, schema->module, schema->name, value);
785 log_error("error on lyd_new_leaf running: %s\n", ly_errmsg(session_context));
786 return NTS_ERR_FAILED;
798 static int generate_late_resolve(generate_job_t *job) {
801 job->late_resolving = true;
803 int prev_count = job->late_resolve_count + 1;
805 while(prev_count > job->late_resolve_count) {
806 int late_resolve_count = job->late_resolve_count;
807 struct lys_node **late_resolve_schema = job->late_resolve_schema;
808 struct lyd_node **late_resolve_parent_o = job->late_resolve_parent_o;
809 struct lyd_node **late_resolve_parent_r = job->late_resolve_parent_r;
810 generate_instance_t **late_resolve_instance = job->late_resolve_instance;
812 job->late_resolve_count = 0;
813 job->late_resolve_schema = 0;
814 job->late_resolve_parent_o = 0;
815 job->late_resolve_parent_r = 0;
816 job->late_resolve_instance = 0;
818 prev_count = late_resolve_count;
820 for(int i = 0; i < late_resolve_count; i++) {
821 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"late-populating "LOG_COLOR_RESET": ");
822 int rc = generate_add_leaf(job, late_resolve_instance[i], late_resolve_schema[i], late_resolve_parent_o[i], late_resolve_parent_r[i]);
823 if(rc != NTS_ERR_OK) {
824 log_error("generate_add_leaf failed on late-resolve\n");
829 free(late_resolve_schema);
830 free(late_resolve_parent_o);
831 free(late_resolve_parent_r);
832 free(late_resolve_instance);
834 job->late_resolving = false;
836 if(prev_count != 0) {
837 log_error("generate_late_resolve detected circular loop!\n");
843 static int generate_validate(generate_instance_t *instance, int count) {
847 int commit_ok = NTS_ERR_OK;
849 for(int i = 0; i < count; i++) {
850 if(instance[i].operational) {
851 log_add_verbose(2, "available modules:");
852 for(int j = 0; j < instance[i].mod_count; j++) {
853 log_add(2, " %s", instance[i].modules[j]->name);
856 log_add_verbose(1, "validating OPERATIONAL for [%d] : %s... ", i, instance[i].xpath);
858 int solved_instance_errors = 1;
859 int solved_errors = 0;
860 bool success = false;
861 while(instance[i].operational && solved_instance_errors) {
862 solved_instance_errors = 0;
863 rc = lyd_validate_modules(&instance[i].operational, instance[i].modules, instance[i].mod_count, LYD_OPT_DATA, 0);
865 log_add(1, LOG_COLOR_BOLD_GREEN"success (%d)\n"LOG_COLOR_RESET, solved_errors);
872 struct ly_err_item *err = ly_err_first(session_context);
874 if((err->vecode == LYVE_NOWHEN) || (err->vecode == LYVE_NOMUST) || (err->vecode == LYVE_NOCONSTR) || (err->vecode == LYVE_NOLEAFREF) || (err->vecode == LYVE_NOMIN) || (err->vecode == LYVE_INVAL)) {
875 struct ly_set *set = lyd_find_path(instance[i].operational, err->path);
876 if(set && set->number) {
877 log_add_verbose(2, "operational error code %d on path %s with msg %s\n", err->vecode, err->path, err->msg);
878 log_add_verbose(2, LOG_COLOR_BOLD_RED" [WHEN-DELETE O]"LOG_COLOR_RESET" %s ... ", err->path);
880 bool mandatory = false;
881 if((set->set.d[0]->schema->flags & LYS_MAND_TRUE) != 0) {
885 if((set->set.d[0]->schema->parent) && (set->set.d[0]->schema->parent->nodetype == LYS_CASE)) {
886 if((set->set.d[0]->schema->parent->flags & LYS_MAND_TRUE) != 0) {
891 if((set->set.d[0]->dflt != 0) || (lys_is_key((const struct lys_node_leaf *)set->set.d[0]->schema, 0)) || (mandatory) || (err->vecode == LYVE_NOMIN)) {
892 //delete whole parent
893 log_add(2, "deleted parent : %s\n", lyd_path(set->set.d[0]->parent));
894 struct lyd_node *p = set->set.d[0]->parent;
895 lyd_free_withsiblings(set->set.d[0]);
897 if(p == instance[i].operational) {
898 log_add_verbose(1, "instance became empty "LOG_COLOR_BOLD_GREEN"success\n"LOG_COLOR_RESET);
900 instance[i].operational = 0;
905 //delete THIS node only
906 lyd_free(set->set.d[0]);
907 log_add(2, "deleted\n");
908 if(set->set.d[0] == instance[i].operational) {
909 log_add_verbose(1, "instance became empty "LOG_COLOR_BOLD_GREEN"success\n"LOG_COLOR_RESET);
911 instance[i].operational = 0;
915 solved_instance_errors++;
920 else if((err->vecode != 0) && (err->vecode != 29)) {
921 log_add_verbose(2, "operational error code %d on path %s with msg %s\n", err->vecode, err->path, err->msg);
926 ly_err_clean(session_context, 0);
929 solved_errors += solved_instance_errors;
934 log_add(1, LOG_COLOR_BOLD_YELLOW"failed"LOG_COLOR_RESET"\n%s\n", ly_errmsg(session_context));
937 log_add(1, LOG_COLOR_BOLD_YELLOW"partially solved (%d)"LOG_COLOR_RESET"\n", solved_errors);
942 if(instance[i].running) {
943 log_add_verbose(1, "validating RUNNING... for [%d] : %s... ", i, instance[i].xpath);
945 int solved_instance_errors = 1;
946 int solved_errors = 0;
947 bool success = false;
948 while(instance[i].running && solved_instance_errors) {
949 solved_instance_errors = 0;
950 rc = lyd_validate_modules(&instance[i].running, instance[i].modules, instance[i].mod_count, LYD_OPT_CONFIG, 0);
952 log_add(1, LOG_COLOR_BOLD_GREEN"success (%d)\n"LOG_COLOR_RESET, solved_errors);
959 struct ly_err_item *err = ly_err_first(session_context);
961 if((err->vecode == LYVE_NOWHEN) || (err->vecode == LYVE_NOMUST) || (err->vecode == LYVE_NOCONSTR) || (err->vecode == LYVE_NOLEAFREF) || (err->vecode == LYVE_NOMIN) || (err->vecode == LYVE_INVAL)) {
962 struct ly_set *set = lyd_find_path(instance[i].running, err->path);
963 if(set && set->number) {
964 log_add_verbose(2, "running error code %d on path %s with msg %s\n", err->vecode, err->path, err->msg);
965 log_add_verbose(2, LOG_COLOR_BOLD_RED" [WHEN-DELETE R]"LOG_COLOR_RESET" %s ... ", err->path);
967 bool mandatory = false;
968 if((set->set.d[0]->schema->flags & LYS_MAND_TRUE) != 0) {
972 if((set->set.d[0]->schema->parent) && (set->set.d[0]->schema->parent->nodetype == LYS_CASE)) {
973 if((set->set.d[0]->schema->parent->flags & LYS_MAND_TRUE) != 0) {
978 if((set->set.d[0]->dflt != 0) || (lys_is_key((const struct lys_node_leaf *)set->set.d[0]->schema, 0)) || (mandatory) || (err->vecode == LYVE_NOMIN)) {
979 //delete whole parent
980 log_add(2, "deleted parent : %s\n", lyd_path(set->set.d[0]->parent));
981 struct lyd_node *p = set->set.d[0]->parent;
982 lyd_free_withsiblings(set->set.d[0]);
985 if(p == instance[i].running) {
986 log_add_verbose(1, "instance became empty "LOG_COLOR_BOLD_GREEN"success\n"LOG_COLOR_RESET);
988 instance[i].running = 0;
993 //delete THIS node only
994 lyd_free(set->set.d[0]);
995 log_add(2, "deleted\n");
996 if(set->set.d[0] == instance[i].running) {
997 log_add_verbose(1, "instance became empty "LOG_COLOR_BOLD_GREEN"success\n"LOG_COLOR_RESET);
999 instance[i].running = 0;
1003 solved_instance_errors++;
1008 else if((err->vecode != 0) && (err->vecode != 29)) {
1009 log_add_verbose(2, "running error code %d on path %s with msg %s\n", err->vecode, err->path, err->msg);
1014 ly_err_clean(session_context, 0);
1017 solved_errors += solved_instance_errors;
1021 if(!solved_errors) {
1022 log_add(1, LOG_COLOR_BOLD_YELLOW"failed"LOG_COLOR_RESET"\n%s\n", ly_errmsg(session_context));
1025 log_add(1, LOG_COLOR_BOLD_YELLOW"partially solved (%d)"LOG_COLOR_RESET"\n", solved_errors);
1034 static int generate_export_data(generate_job_t *job, const char *running_filename, const char *operational_filename) {
1037 if(job->operational) {
1038 if(lyd_print_path(operational_filename, job->operational, LYD_JSON, LYP_FORMAT | LYP_WITHSIBLINGS) != 0) {
1039 log_error("lyd_print_path failed for operational\n");
1040 return NTS_ERR_FAILED;
1045 if(lyd_print_path(running_filename, job->running, LYD_JSON, LYP_FORMAT | LYP_WITHSIBLINGS) != 0) {
1046 log_error("lyd_print_path failed for running\n");
1047 return NTS_ERR_FAILED;
1054 static int instance_add_module(generate_instance_t *instance, const struct lys_module *module) {
1058 for(int i = 0; i < instance->mod_count; i++) {
1059 if(instance->modules[i] == module) {
1064 instance->modules = (const struct lys_module **)realloc(instance->modules, sizeof(const struct lys_module *) * (instance->mod_count + 1));
1065 if(!instance->modules) {
1066 log_error("bad realloc\n");
1067 return NTS_ERR_FAILED;
1069 instance->modules[instance->mod_count] = module;
1070 instance->mod_count++;
1075 static int generate_late_resolve_add_leaf(generate_job_t *job, generate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r) {
1079 job->late_resolve_schema = (struct lys_node **)realloc(job->late_resolve_schema, (job->late_resolve_count + 1) * sizeof(struct lys_node *));
1080 if(!job->late_resolve_schema) {
1081 log_error("bad realloc\n");
1082 return NTS_ERR_FAILED;
1084 job->late_resolve_schema[job->late_resolve_count] = schema;
1086 job->late_resolve_parent_o = (struct lyd_node **)realloc(job->late_resolve_parent_o, (job->late_resolve_count + 1) * sizeof(struct lyd_node *));
1087 if(!job->late_resolve_parent_o) {
1088 log_error("bad realloc\n");
1089 return NTS_ERR_FAILED;
1091 job->late_resolve_parent_o[job->late_resolve_count] = parent_o;
1093 job->late_resolve_parent_r = (struct lyd_node **)realloc(job->late_resolve_parent_r, (job->late_resolve_count + 1) * sizeof(struct lyd_node *));
1094 if(!job->late_resolve_parent_r) {
1095 log_error("bad realloc\n");
1096 return NTS_ERR_FAILED;
1098 job->late_resolve_parent_r[job->late_resolve_count] = parent_r;
1100 job->late_resolve_instance = (generate_instance_t **)realloc(job->late_resolve_instance, (job->late_resolve_count + 1) * sizeof(generate_instance_t *));
1101 if(!job->late_resolve_instance) {
1102 log_error("bad realloc\n");
1103 return NTS_ERR_FAILED;
1105 job->late_resolve_instance[job->late_resolve_count] = instance;
1107 job->late_resolve_count++;
1112 static const char* leafref_test_val(int index) {
1123 return "Fd:4D:63:A5:21:C5";
1147 return "best-effort";
1151 return "yes-fault:o-ran-sc-alarm-type";
1159 log_error("index out of bounds\n");
1165 static int generate_get_instance_count(const char *path) {
1168 for(int i = 0; i < framework_config.datastore_generate.custom_list_instances_count; i++) {
1169 if(strcmp(path, framework_config.datastore_generate.custom_list_instances[i].path) == 0) {
1170 return framework_config.datastore_generate.custom_list_instances[i].count;
1173 return framework_config.datastore_generate.default_list_instances;
1176 static char *generate_get_restrict_schema(const char *path) {
1180 for(int i = 0; i < framework_config.datastore_generate.restrict_schema_count; i++) {
1181 if(strcmp(path, framework_config.datastore_generate.restrict_schema[i].path) == 0) {
1182 ret = strdup(framework_config.datastore_generate.restrict_schema[i].values[framework_config.datastore_generate.restrict_schema[i].index]);
1183 framework_config.datastore_generate.restrict_schema[i].index++;
1184 if(framework_config.datastore_generate.restrict_schema[i].index >= framework_config.datastore_generate.restrict_schema[i].values_count) {
1185 framework_config.datastore_generate.restrict_schema[i].index = 0;