Add supoprt for D release use-case.
[sim/o1-interface.git] / ntsimulator / ntsim-ng / core / app / manager_context.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 "manager.h"
21 #include "utils/log_utils.h"
22 #include "utils/sys_utils.h"
23 #include "utils/nts_utils.h"
24 #include <stdio.h>
25 #include <assert.h>
26
27 #include <sysrepo.h>
28 #include <sysrepo/values.h>
29
30 #include "core/framework.h"
31 #include "core/session.h"
32 #include "core/context.h"
33
34 #define NTS_AVAILABLE_IMAGES_SCHEMA_XPATH           "/nts-manager:simulation/available-images"
35
36
37 manager_context_t *manager_context = 0;
38 docker_context_t *docker_context = 0;
39 int docker_context_count = 0;
40
41 static int manager_populate_sysrepo_network_function_list(void);
42 static int manager_populate_available_simulations(void);
43
44 int manager_context_init(void) {
45
46     //get installed function types
47     struct lys_node_leaf *elem = (struct lys_node_leaf *)ly_ctx_get_node(session_context, 0, NTS_FUNCTION_LIST_SCHEMA_XPATH"/function-type", 0);
48     if(elem == 0) {
49         log_error("ly_ctx_get_node failed for xpath: %s\n", NTS_FUNCTION_LIST_SCHEMA_XPATH"/function-type");
50         return NTS_ERR_FAILED;
51     }
52
53     struct lys_ident **function_types = 0;
54     docker_context_count = context_get_identity_leafs_of_type(elem->type.info.ident.ref[0], &function_types);
55     if(!docker_context_count) {
56         log_error("context_get_identity_leafs_of_type() error\n");
57         return NTS_ERR_FAILED;
58     }
59
60     docker_context_count = docker_context_count;
61
62     const char **docker_filter = malloc(sizeof(char *) * docker_context_count);
63     if(docker_filter == 0) {
64         log_error("bad malloc\n");
65         free(function_types);
66         return NTS_ERR_FAILED;
67     }
68
69     for(int i = 0; i < docker_context_count; i++) {
70         docker_filter[i] = function_types[i]->ref;
71     }
72
73     int rc = docker_init(docker_filter, docker_context_count, "1.2.0", &docker_context);
74     free(docker_filter);
75     if(rc != NTS_ERR_OK) {
76         log_error("docker_init() failed\n");
77         free(function_types);
78         return NTS_ERR_FAILED;
79     }
80
81
82     //remove non-present network functions
83     int new_context_count = 0;
84     docker_context_t *new_context = malloc(sizeof(docker_context_t) * docker_context_count);
85     struct lys_ident **new_function_types = (struct lys_ident **)malloc(sizeof(struct lys_ident *) * docker_context_count);
86     for(int i = 0; i < docker_context_count; i++) {
87         if(docker_context[i].available_images_count) {
88             new_context[new_context_count].image = docker_context[i].image;
89             new_context[new_context_count].available_images = docker_context[i].available_images;
90             new_context[new_context_count].available_images_count = docker_context[i].available_images_count;
91             new_function_types[new_context_count] = function_types[i];
92             
93             new_context_count++;
94
95         }
96         else {
97             free(docker_context[i].image);
98         }
99     }
100
101     free(function_types);
102     function_types = new_function_types;
103
104     free(docker_context);
105     docker_context = new_context;
106     docker_context_count = new_context_count;
107
108     //initial list population
109     manager_context = (manager_context_t *)malloc(sizeof(manager_context_t) * docker_context_count);
110     if(manager_context == 0) {
111         log_error("malloc failed\n");
112         free(function_types);
113         return NTS_ERR_FAILED;
114     }
115
116     for(int i = 0; i < docker_context_count; i++) {
117         manager_context[i].ft = function_types[i];
118
119         asprintf(&manager_context[i].function_type, "%s:%s", manager_context[i].ft->module->name, manager_context[i].ft->name);
120         manager_context[i].instance = 0;
121         manager_context[i].docker = &docker_context[i];
122
123         manager_context[i].started_instances = 0;
124         manager_context[i].mounted_instances = 0;
125         manager_context[i].mount_point_addressing_method = strdup("docker-mapping");
126         
127         if(docker_context[i].available_images_count) {
128             manager_context[i].docker_instance_name = strdup(strstr(manager_context[i].function_type, ":") + 1);
129             manager_context[i].docker_version_tag = strdup(docker_context[i].available_images[0].tag);
130             manager_context[i].docker_repository = strdup(docker_context[i].available_images[0].repo);
131         }
132         else {
133             manager_context[i].docker_instance_name = strdup("no-image-installed");
134             manager_context[i].docker_version_tag = strdup("no-image-installed");
135             manager_context[i].docker_repository = strdup("no-image-installed");
136         }
137     }
138     free(function_types);
139
140     //do initial sysrepo list population
141     rc = manager_populate_sysrepo_network_function_list();
142     if(rc != NTS_ERR_OK) {
143         log_error("manager_populate_sysrepo_network_function_list failed\n");
144         return NTS_ERR_FAILED;
145     }
146
147     rc = manager_populate_available_simulations();
148     if(rc != NTS_ERR_OK) {
149         log_error("manager_populate_available_simulations failed\n");
150         return NTS_ERR_FAILED;
151     }
152
153     rc = nts_utils_populate_info(session_running, framework_environment.nts.function_type);
154     if(rc != NTS_ERR_OK) {
155         log_error("nts_utils_populate_info failed\n");
156         return NTS_ERR_FAILED;
157     }
158
159     return NTS_ERR_OK;
160 }
161
162 void manager_context_free(void) {
163     for(int i = 0; i < docker_context_count; i++) {
164         free(manager_context[i].docker_instance_name);
165         free(manager_context[i].docker_version_tag);
166         free(manager_context[i].docker_repository);
167         free(manager_context[i].function_type);
168     }
169
170     free(manager_context);
171 }
172
173 static int manager_populate_sysrepo_network_function_list(void) {
174     //check whether everything is already populated, read and update (if previously ran)
175     sr_val_t *values = 0;
176     size_t value_count = 0;
177     int rc = sr_get_items(session_running, NTS_FUNCTION_LIST_SCHEMA_XPATH, 0, 0, &values, &value_count);
178     if(rc != SR_ERR_OK) {
179         log_error("get items failed\n");
180         return NTS_ERR_FAILED;
181     }
182
183     //either get values, or if data inconclusive, delete everything
184     if(value_count) {
185         log_add_verbose(2, "nts-manager instances found (%d). cleaning up for fresh start...\n", value_count);
186
187         for(int i = 0; i < value_count; i++) {           
188             rc = sr_delete_item(session_running, values[i].xpath, 0);
189             if(rc != SR_ERR_OK) {
190                 log_error("sr_delete_item failed\n");
191                 return NTS_ERR_FAILED;
192             }
193         }
194         rc = sr_apply_changes(session_running, 0, 0);
195         if(rc != SR_ERR_OK) {
196             log_error("sr_apply_changes failed\n");
197             return NTS_ERR_FAILED;
198         }
199     }
200
201     //populate everything if needed
202     for(int i = 0; i < docker_context_count; i++) {
203         char *xpath = 0;
204
205         asprintf(&xpath, "%s[function-type='%s']/function-type", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type);
206         rc = sr_set_item_str(session_running, xpath, (const char *)manager_context[i].function_type, 0, 0);
207         if(rc != SR_ERR_OK) {
208             log_error("sr_set_item_str failed\n");
209             return NTS_ERR_FAILED;
210         }
211         free(xpath);
212
213         asprintf(&xpath, "%s[function-type='%s']/started-instances", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type);
214         rc = sr_set_item_str(session_running, xpath, "0", 0, 0);
215         if(rc != SR_ERR_OK) {
216             log_error("sr_set_item_str failed\n");
217             return NTS_ERR_FAILED;
218         }
219         free(xpath);
220
221         asprintf(&xpath, "%s[function-type='%s']/mounted-instances", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type);
222         rc = sr_set_item_str(session_running, xpath, "0", 0, 0);
223         if(rc != SR_ERR_OK) {
224             log_error("sr_set_item_str failed\n");
225             return NTS_ERR_FAILED;
226         }
227         free(xpath);
228
229         asprintf(&xpath, "%s[function-type='%s']/docker-instance-name", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type);
230         rc = sr_set_item_str(session_running, xpath, (const char*)manager_context[i].docker_instance_name, 0, 0);
231         if(rc != SR_ERR_OK) {
232             log_error("sr_set_item_str failed\n");
233             return NTS_ERR_FAILED;
234         }
235         free(xpath);
236
237         asprintf(&xpath, "%s[function-type='%s']/docker-version-tag", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type);
238         rc = sr_set_item_str(session_running, xpath, (const char*)manager_context[i].docker_version_tag, 0, 0);
239         if(rc != SR_ERR_OK) {
240             log_error("sr_set_item_str failed\n");
241             return NTS_ERR_FAILED;
242         }
243         free(xpath);
244
245         asprintf(&xpath, "%s[function-type='%s']/docker-repository", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type);
246         rc = sr_set_item_str(session_running, xpath, (const char*)manager_context[i].docker_repository, 0, 0);
247         if(rc != SR_ERR_OK) {
248             log_error("sr_set_item_str failed\n");
249             return NTS_ERR_FAILED;
250         }
251         free(xpath);
252
253         asprintf(&xpath, "%s[function-type='%s']/mount-point-addressing-method", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type);
254         rc = sr_set_item_str(session_running, xpath, (const char *)manager_context[i].mount_point_addressing_method, 0, 0);
255         if(rc != SR_ERR_OK) {
256             log_error("sr_set_item_str failed\n");
257             return NTS_ERR_FAILED;
258         }
259         free(xpath);
260
261         //presence containers
262         asprintf(&xpath, "%s[function-type='%s']/fault-generation", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type);
263         rc = sr_set_item_str(session_running, xpath, 0, 0, 0);
264         if(rc != SR_ERR_OK) {
265             log_error("sr_set_item_str failed\n");
266             return NTS_ERR_FAILED;
267         }
268         free(xpath);
269
270         asprintf(&xpath, "%s[function-type='%s']/netconf", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type);
271         rc = sr_set_item_str(session_running, xpath, 0, 0, 0);
272         if(rc != SR_ERR_OK) {
273             log_error("sr_set_item_str failed\n");
274             return NTS_ERR_FAILED;
275         }
276         free(xpath);
277
278         asprintf(&xpath, "%s[function-type='%s']/ves", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type);
279         rc = sr_set_item_str(session_running, xpath, 0, 0, 0);
280         if(rc != SR_ERR_OK) {
281             log_error("sr_set_item_str failed\n");
282             return NTS_ERR_FAILED;
283         }
284         free(xpath);
285     }
286
287     //apply all changes
288     rc = sr_apply_changes(session_running, 0, 0);
289     if(rc != SR_ERR_OK) {
290         log_error("sr_apply_changes failed: %s\n", sr_strerror(rc));
291         return NTS_ERR_FAILED;
292     }
293
294     return NTS_ERR_OK;
295 }
296
297 static int manager_populate_available_simulations(void) {
298     assert_session();
299
300     struct lyd_node *container = lyd_new_path(0, session_context, NTS_AVAILABLE_IMAGES_SCHEMA_XPATH, 0, LYD_ANYDATA_CONSTSTRING, LYD_PATH_OPT_NOPARENTRET);
301     if(container == 0) {
302         log_error("lyd_new_path failed\n");
303         return NTS_ERR_FAILED;
304     }
305
306     for(int i = 0; i < docker_context_count; i++) {
307         for(int j = 0; j < docker_context[i].available_images_count; j++) {
308             struct lyd_node *list = lyd_new(container, container->schema->module, "network-function-image");
309             if(!list) {
310                 log_error("lyd_new failed\n");
311                 return NTS_ERR_FAILED;
312             }
313
314             struct lyd_node *rc = lyd_new_leaf(list, list->schema->module, "function-type", (const char *)manager_context[i].function_type);
315             if(rc == 0) {
316                 log_error("lyd_new_leaf failed\n");
317                 return NTS_ERR_FAILED;
318             }
319
320             rc = lyd_new_leaf(list, list->schema->module, "docker-image-name", docker_context[i].image);
321             if(rc == 0) {
322                 log_error("lyd_new_leaf failed\n");
323                 return NTS_ERR_FAILED;
324             }
325
326             rc = lyd_new_leaf(list, list->schema->module, "docker-version-tag", docker_context[i].available_images[j].tag);
327             if(rc == 0) {
328                 log_error("lyd_new_leaf failed\n");
329                 return NTS_ERR_FAILED;
330             }
331
332             rc = lyd_new_leaf(list, list->schema->module, "docker-repository", docker_context[i].available_images[j].repo);
333             if(rc == 0) {
334                 log_error("lyd_new_leaf failed\n");
335                 return NTS_ERR_FAILED;
336             }
337
338         }
339     }
340
341     //find top level container
342     struct lyd_node *root = container;
343     while(root->parent) {
344         root = root->parent;
345     }
346
347     int rc = sr_edit_batch(session_operational, root, "replace");
348     if(rc != SR_ERR_OK) {
349         log_error("sr_edit_batch failed\n");
350         return NTS_ERR_FAILED;
351     }
352
353     //apply all changes
354     rc = sr_apply_changes(session_operational, 0, 0);
355     if(rc != SR_ERR_OK) {
356         log_error("sr_apply_changes failed: %s\n", sr_strerror(rc));
357         return NTS_ERR_FAILED;
358     }
359
360     return NTS_ERR_OK;
361 }