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/sys_utils.h"
23 #include "utils/nts_utils.h"
28 #include <sysrepo/values.h>
30 #include "core/framework.h"
31 #include "core/session.h"
32 #include "core/context.h"
34 #define NTS_AVAILABLE_IMAGES_SCHEMA_XPATH "/nts-manager:simulation/available-images"
37 manager_context_t *manager_context = 0;
38 docker_context_t *docker_context = 0;
39 int docker_context_count = 0;
41 static int manager_populate_sysrepo_network_function_list(void);
42 static int manager_populate_available_simulations(void);
44 int manager_context_init(void) {
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);
49 log_error("ly_ctx_get_node failed for xpath: %s\n", NTS_FUNCTION_LIST_SCHEMA_XPATH"/function-type");
50 return NTS_ERR_FAILED;
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;
60 docker_context_count = docker_context_count;
62 const char **docker_filter = malloc(sizeof(char *) * docker_context_count);
63 if(docker_filter == 0) {
64 log_error("bad malloc\n");
66 return NTS_ERR_FAILED;
69 for(int i = 0; i < docker_context_count; i++) {
70 docker_filter[i] = function_types[i]->ref;
73 int rc = docker_init(docker_filter, docker_context_count, "1.2.0", &docker_context);
75 if(rc != NTS_ERR_OK) {
76 log_error("docker_init() failed\n");
78 return NTS_ERR_FAILED;
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];
97 free(docker_context[i].image);
101 free(function_types);
102 function_types = new_function_types;
104 free(docker_context);
105 docker_context = new_context;
106 docker_context_count = new_context_count;
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;
116 for(int i = 0; i < docker_context_count; i++) {
117 manager_context[i].ft = function_types[i];
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];
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");
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);
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");
138 free(function_types);
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;
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;
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;
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);
170 free(manager_context);
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;
183 //either get values, or if data inconclusive, delete everything
185 log_add_verbose(2, "nts-manager instances found (%d). cleaning up for fresh start...\n", value_count);
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;
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;
201 //populate everything if needed
202 for(int i = 0; i < docker_context_count; i++) {
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
297 static int manager_populate_available_simulations(void) {
300 struct lyd_node *container = lyd_new_path(0, session_context, NTS_AVAILABLE_IMAGES_SCHEMA_XPATH, 0, LYD_ANYDATA_CONSTSTRING, LYD_PATH_OPT_NOPARENTRET);
302 log_error("lyd_new_path failed\n");
303 return NTS_ERR_FAILED;
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");
310 log_error("lyd_new failed\n");
311 return NTS_ERR_FAILED;
314 struct lyd_node *rc = lyd_new_leaf(list, list->schema->module, "function-type", (const char *)manager_context[i].function_type);
316 log_error("lyd_new_leaf failed\n");
317 return NTS_ERR_FAILED;
320 rc = lyd_new_leaf(list, list->schema->module, "docker-image-name", docker_context[i].image);
322 log_error("lyd_new_leaf failed\n");
323 return NTS_ERR_FAILED;
326 rc = lyd_new_leaf(list, list->schema->module, "docker-version-tag", docker_context[i].available_images[j].tag);
328 log_error("lyd_new_leaf failed\n");
329 return NTS_ERR_FAILED;
332 rc = lyd_new_leaf(list, list->schema->module, "docker-repository", docker_context[i].available_images[j].repo);
334 log_error("lyd_new_leaf failed\n");
335 return NTS_ERR_FAILED;
341 //find top level container
342 struct lyd_node *root = container;
343 while(root->parent) {
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;
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;