Add VES stndDefined PM and subscription for O-DU.
[sim/o1-interface.git] / ntsimulator / ntsim-ng / core / datastore / schema.c
1 /*************************************************************************
2 *
3 * Copyright 2020 highstreet technologies GmbH and others
4 *
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
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
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 ***************************************************************************/
17
18 #define _GNU_SOURCE
19
20 #include "utils/log_utils.h"
21 #include "utils/type_utils.h"
22 #include <stdio.h>
23 #include <time.h>
24 #include <inttypes.h>
25 #include <assert.h>
26
27 #include <libyang/libyang.h>
28 #include "core/session.h"
29 #include "core/framework.h"
30
31 static int schema_print_recursive(struct lys_node *root);
32 static bool generate_is_excluded_module(const char *module);
33
34 int datastore_schema_get_xpaths(char ***root_xpath) {
35     assert_session();
36     assert(root_xpath);
37
38     const struct lys_module *module;
39     const struct lys_node *root;
40     uint32_t idx = 0;
41     char **list = 0;
42     int total = 0;
43
44     while((module = ly_ctx_get_module_iter(session_context, &idx)) != 0) {
45         if(!generate_is_excluded_module(module->name) && (module->implemented)) {
46             LY_TREE_FOR(module->data, root) {
47                 if(((root->nodetype == LYS_CONTAINER) || (root->nodetype == LYS_LIST)) && ((root->flags & LYS_STATUS_DEPRC) == 0)) {
48                     list = (char **)realloc(list, sizeof(char *) * (total + 1));
49                     if(!list) {
50                         log_error("bad realloc\n");
51                         return NTS_ERR_FAILED;
52                     }
53                     asprintf(&list[total], "/%s:%s", module->name, root->name);
54                     if(!list[total]) {
55                         log_error("bad asprintf\n");
56                         return NTS_ERR_FAILED;
57                     }
58                     total++; 
59                 }
60                 else if(root->nodetype == LYS_USES) {
61                     struct lys_node *chd;
62                     LY_TREE_FOR(root->child, chd) {
63                         if(((chd->nodetype == LYS_CONTAINER) || (chd->nodetype == LYS_LIST)) && ((chd->flags & LYS_STATUS_DEPRC) == 0)) {
64                             list = (char **)realloc(list, sizeof(char *) * (total + 1));
65                             if(!list) {
66                                 log_error("bad realloc\n");
67                                 return NTS_ERR_FAILED;
68                             }
69                             asprintf(&list[total], "/%s:%s", module->name, chd->name);                            
70                             if(!list[total]) {
71                                 log_error("bad asprintf\n");
72                                 return NTS_ERR_FAILED;
73                             }
74                             total++;
75                         }
76                     }
77                 }
78             }
79         }
80     }
81
82     *root_xpath = list;
83     return total;
84 }
85
86 int datastore_schema_get_running_xpaths(char ***root_xpath, char ***modules) {
87     assert_session();
88     assert(root_xpath);
89     assert(modules);
90
91     const struct lys_module *module;
92     const struct lys_node *root;
93     uint32_t idx = 0;
94     char **xpath_list = 0;
95     char **mod_list = 0;
96     int total = 0;
97
98     while((module = ly_ctx_get_module_iter(session_context, &idx)) != 0) {
99         if(!generate_is_excluded_module(module->name) && (module->implemented)) {
100             LY_TREE_FOR(module->data, root) {
101                 if(((root->nodetype == LYS_CONTAINER) || (root->nodetype == LYS_LIST)) && ((root->flags & LYS_STATUS_DEPRC) == 0) && ((root->flags & LYS_CONFIG_W) == 1)) {
102                     xpath_list = (char **)realloc(xpath_list, sizeof(char *) * (total + 1));
103                     if(!xpath_list) {
104                         log_error("bad realloc\n");
105                         return NTS_ERR_FAILED;
106                     }
107                     asprintf(&xpath_list[total], "/%s:%s", module->name, root->name);
108                     if(!xpath_list[total]) {
109                         log_error("bad asprintf\n");
110                         return NTS_ERR_FAILED;
111                     }
112
113                     mod_list = (char **)realloc(mod_list, sizeof(char *) * (total + 1));
114                     if(!mod_list) {
115                         log_error("bad realloc\n");
116                         return NTS_ERR_FAILED;
117                     }
118                     asprintf(&mod_list[total], "%s", module->name);
119                     if(!mod_list[total]) {
120                         log_error("bad asprintf\n");
121                         return NTS_ERR_FAILED;
122                     }
123                     total++; 
124                 }
125                 else if(root->nodetype == LYS_USES) {
126                     struct lys_node *chd;
127                     LY_TREE_FOR(root->child, chd) {
128                         if(((chd->nodetype == LYS_CONTAINER) || (chd->nodetype == LYS_LIST)) && ((chd->flags & LYS_STATUS_DEPRC) == 0) && ((root->flags & LYS_CONFIG_W) == 1)) {
129                             xpath_list = (char **)realloc(xpath_list, sizeof(char *) * (total + 1));
130                             if(!xpath_list) {
131                                 log_error("bad realloc\n");
132                                 return NTS_ERR_FAILED;
133                             }
134                             asprintf(&xpath_list[total], "/%s:%s", module->name, chd->name);                            
135                             if(!xpath_list[total]) {
136                                 log_error("bad asprintf\n");
137                                 return NTS_ERR_FAILED;
138                             }
139
140                             mod_list = (char **)realloc(mod_list, sizeof(char *) * (total + 1));
141                             if(!mod_list) {
142                                 log_error("bad realloc\n");
143                                 return NTS_ERR_FAILED;
144                             }
145                             asprintf(&mod_list[total], "%s", module->name);
146                             if(!mod_list[total]) {
147                                 log_error("bad asprintf\n");
148                                 return NTS_ERR_FAILED;
149                             }
150                             total++;
151                         }
152                     }
153                 }
154             }
155         }
156     }
157
158     *root_xpath = xpath_list;
159     *modules = mod_list;
160     return total;
161 }
162
163 int datastore_schema_print_root_paths(void) {
164     assert_session();
165
166     struct lys_module *module;
167     struct lys_node *root;
168     uint32_t idx = 0;
169
170     while((module = (struct lys_module *)ly_ctx_get_module_iter(session_context, &idx)) != 0) {
171         log_add_verbose(2, "looking into module "LOG_COLOR_BOLD_MAGENTA"%s"LOG_COLOR_RESET"\n", module->name);
172
173         char flags[10];
174         strcpy(flags, "[     ]");
175         flags[1] = (module->implemented == 0) ? 'i' : ' ';
176         flags[3] = generate_is_excluded_module(module->name) ? 'E' : ' ';
177
178         LY_TREE_FOR(module->data, root) {
179             log_add_verbose(2, "   found "LOG_COLOR_CYAN"%s"LOG_COLOR_RESET" with name "LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET"\n", typeutils_yang_nodetype_to_str(root->nodetype), root->name);
180             if((root->nodetype == LYS_CONTAINER) || (root->nodetype == LYS_LIST)) {
181                 flags[2] = ((root->flags & LYS_STATUS_DEPRC) != 0) ? 'D' : ' ';
182                 flags[4] = ((root->flags & LYS_CONFIG_W) == 0) ? 'O' : 'R';
183                 flags[5] = (root->nodetype == LYS_CONTAINER) ? 'C' : 'L';
184                 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_CYAN" /%s:%s\n"LOG_COLOR_RESET, flags, module->name, root->name);
185             }
186             else if(root->nodetype == LYS_USES) {
187                 struct lys_node *chd;
188                 LY_TREE_FOR(root->child, chd) {
189                     log_add_verbose(2, "   - found "LOG_COLOR_CYAN"%s"LOG_COLOR_RESET" with name "LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET"\n", typeutils_yang_nodetype_to_str(chd->nodetype), chd->name);
190                     if((chd->nodetype == LYS_CONTAINER) || (chd->nodetype == LYS_LIST)) {
191                         flags[2] = ((chd->flags & LYS_STATUS_DEPRC) != 0) ? 'D' : ' ';
192                         flags[4] = ((chd->flags & LYS_CONFIG_W) == 0) ? 'O' : 'R';
193                         flags[5] = (chd->nodetype == LYS_CONTAINER) ? 'C' : 'L';
194                         log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_CYAN" /%s:%s\n"LOG_COLOR_RESET, flags, module->name, chd->name);
195                     }
196                 }
197             }
198         }
199     }
200
201     log_add_verbose(1, "\n   "LOG_COLOR_BOLD_YELLOW"i"LOG_COLOR_RESET" - not implemented | "LOG_COLOR_BOLD_YELLOW"D"LOG_COLOR_RESET" - deprecated | "LOG_COLOR_BOLD_YELLOW"E"LOG_COLOR_RESET" - excluded by config | "LOG_COLOR_BOLD_YELLOW"O"LOG_COLOR_RESET" - operational datastore | "LOG_COLOR_BOLD_YELLOW"R"LOG_COLOR_RESET" - running datastore | "LOG_COLOR_BOLD_YELLOW"C"LOG_COLOR_RESET" - container | "LOG_COLOR_BOLD_YELLOW"L"LOG_COLOR_RESET" - list\n\n");
202     return NTS_ERR_OK;
203 }
204
205 int datastore_schema_print_xpath(const char *xpath) {
206     assert_session();
207     assert(xpath);
208
209     if(xpath == 0) {
210         log_error("xpath is null\n");
211         return NTS_ERR_FAILED;
212     }
213     log_add_verbose(1, "printing out data structure for xpath: "LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET"\n", xpath);
214     
215     struct lys_node *elem = (struct lys_node *)ly_ctx_get_node(session_context, 0, xpath, 0);
216     if(elem == 0) {
217         log_error("ly_ctx_get_node failed for xpath: %s\n", xpath);
218         return NTS_ERR_FAILED;
219     }
220
221     struct lys_module *module = lys_node_module(elem);
222     if(module == 0) {
223         log_error("lys_node_module failed for xpath: %s\n", xpath);
224         return NTS_ERR_FAILED;
225     }
226
227
228     log_add_verbose(2, "module is %s @ revision %s\n", module->name, module->rev[0].date);
229
230     int rc = schema_print_recursive(elem);
231     if(rc != NTS_ERR_OK) {
232         log_error("schema_print_recursive failed for xpath: %s\n", xpath);
233         return NTS_ERR_FAILED;
234     }
235
236     log_add_verbose(1, "\n   "LOG_COLOR_BOLD_YELLOW"O"LOG_COLOR_RESET" - operational datastore | "LOG_COLOR_BOLD_YELLOW"R"LOG_COLOR_RESET" - running datastore | "LOG_COLOR_BOLD_YELLOW"*"LOG_COLOR_RESET" - key | "LOG_COLOR_BOLD_YELLOW"M"LOG_COLOR_RESET" - mandatory | "LOG_COLOR_BOLD_YELLOW"D"LOG_COLOR_RESET" - deprecated | "LOG_COLOR_BOLD_YELLOW"S"LOG_COLOR_RESET" - obsolete\n\n");
237     log_add_verbose(2, "schema_print() finished\n");
238
239     return NTS_ERR_OK;
240
241 }
242
243 static int schema_print_recursive(struct lys_node *root) {
244     assert(root);
245
246     char my_status[] = "[    ]";
247     my_status[1] = ((root->flags & LYS_CONFIG_W) == 0) ? 'O' : 'R';
248     my_status[2] = ((root->flags & LYS_MAND_TRUE) != 0) ? 'M' : ' ';
249     my_status[3] = ((root->flags & LYS_STATUS_DEPRC) != 0) ? 'D' : ' ';
250     my_status[4] = ((root->flags & LYS_STATUS_OBSLT) != 0) ? 'S' : ' ';
251
252     if(((root->parent) && (root->parent->nodetype == LYS_CASE)) && ((root->parent->flags & LYS_MAND_TRUE) != 0)) {
253         my_status[2] = 'M';
254     }
255
256     char *path = lys_data_path(root);
257     if((root->nodetype != LYS_CHOICE) && (root->nodetype != LYS_CASE)) {
258         log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET" %-100s ", my_status, path);
259
260         if(root->nodetype == LYS_LIST) {
261             struct lys_node_list *list = (struct lys_node_list *)root;
262             log_add(1, LOG_COLOR_CYAN"%s "LOG_COLOR_MAGENTA"(m: %d M: %d)"LOG_COLOR_RESET, 4 + typeutils_yang_nodetype_to_str(root->nodetype), list->min, list->max); //+4 to skip "LYS_"
263         }
264         else if(root->nodetype == LYS_LEAFLIST) {
265             struct lys_node_leaflist *list = (struct lys_node_leaflist *)root;
266             log_add(1, LOG_COLOR_CYAN"%s "LOG_COLOR_MAGENTA"(m: %d M: %d)"LOG_COLOR_RESET, 4 + typeutils_yang_nodetype_to_str(root->nodetype), list->min, list->max); //+4 to skip "LYS_"
267         }
268         else {
269             log_add(1, LOG_COLOR_CYAN"%-20s"LOG_COLOR_RESET, 4 + typeutils_yang_nodetype_to_str(root->nodetype)); //+4 to skip "LYS_"
270         }
271     }
272     free(path);
273
274     switch(root->nodetype) {
275         case LYS_LEAF:
276         case LYS_LEAFLIST: {            
277             struct lys_type *type = &((struct lys_node_leaf *)root)->type;
278             if(lys_is_key((const struct lys_node_leaf *)root, 0) != 0) {
279                 log_add(1, LOG_COLOR_BOLD_YELLOW"[*]"LOG_COLOR_RESET);
280             }
281             else {
282                 log_add(1, "   ");
283             }
284
285             char *typestr = typeutils_type_to_str(type);
286             log_add(1, "[%s]", typestr);
287             free(typestr);
288             
289             if(root->parent) {
290                 if(root->parent->nodetype == LYS_CASE) {
291                     log_add(1, " is a "LOG_COLOR_BLUE"CASE"LOG_COLOR_RESET" of "LOG_COLOR_CYAN"%s"LOG_COLOR_RESET, root->parent->parent->name);
292                 }
293             }
294             
295             if(type->base == LY_TYPE_LEAFREF) {
296                 log_add(1, " path: "LOG_COLOR_GREEN"%s"LOG_COLOR_RESET" ", type->info.lref.path);
297             }
298             else if(type->base == LY_TYPE_UNION) {
299                 if((type->info.uni.count == 0) && (type->der != 0)) {
300                     type = &type->der->type;
301                 }
302
303                 log_add(1, " available union types (%d):"LOG_COLOR_GREEN, type->info.uni.count);
304                 for(int i = 0; i < type->info.uni.count; i++) {
305                     char *typestr = typeutils_type_to_str(&type->info.uni.types[i]);
306                     log_add(1, " %s", typestr);
307                     free(typestr);
308                 }
309                 log_add(1, LOG_COLOR_RESET);
310             }
311         } break;
312
313         default:
314             break;
315     }
316   
317     if((root->nodetype != LYS_CHOICE) && (root->nodetype != LYS_CASE)) {
318         log_add(1, "\n");
319     }
320
321     struct lys_node *child = 0;
322     LY_TREE_FOR(root->child, child) {
323         int rc = schema_print_recursive(child);
324         if(rc != NTS_ERR_OK) {
325             return rc;
326         }
327     }
328
329     return NTS_ERR_OK;
330 }
331
332 static bool generate_is_excluded_module(const char *module) {
333     assert(module);
334
335     for(int i = 0; i < framework_config.datastore_generate.excluded_modules_count; i++) {
336         if(strstr(module, framework_config.datastore_generate.excluded_modules[i]) != 0) {
337             return true;
338         }
339     }
340     
341     return false;
342 }