c24146883b62a87a5f9c1a92713103b2e89e791e
[sim/o1-interface.git] / ntsimulator / ntsim-ng / core / framework.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 "framework.h"
21 #include <string.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <unistd.h>
25 #include <limits.h>
26 #include <assert.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <cjson/cJSON.h>
30
31 #include "utils/sys_utils.h"
32 #include "utils/log_utils.h"
33 #include "utils/rand_utils.h"
34
35 framework_arguments_t framework_arguments;
36 framework_config_t framework_config;
37 framework_environment_t framework_environment;
38
39 const char *argp_program_version = "ntsim-ng v1.0.6";
40 const char *argp_program_bug_address = "<alexandru.stancu@highstreet-technologies.com> / <adrian.lita@highstreet-technologies.com>";
41 static char doc[] = "ntsim - new generation";
42
43 static struct argp_option options[] = {
44     // docker init functionality, independent from rest of the app
45     { "docker-init", 'i', 0, 0, "Runs initialization tasks for the Docker container that's being built. Do not run manually." },
46
47     // daemon modes (choose only one)
48     { "manager", 'm', 0, 0, "Run the daemon as manager." },
49     { "network-function", 'f', 0, 0, "Run the daemon as network function." },
50
51     // global settings, can be combined
52     { "operational-only", 'o', 0, 0, "When this is set, the RUNNING datastore is actually the OPERATIONAL one." },
53     { "fixed-rand", 'r', "SEED", 0, "Initialize RAND seed to a fixed value (for debugging purposes)." },
54     { "verbose", 'v', "LEVEL", 0, "Verbosity level for printing to stdout (logs will still save everything). LEVEL is: 0=errors only, 1=requested info(default), 2=info" },
55     { "workspace", 'w', "PATH", 0, "Initialize workspace to a different one than the current working directory." },
56
57     // test modes (choose only one)
58     { "test-mode", 't', 0, 0, "Test mode to be deleted after." },
59     { "exhaustive-test", '0', 0, 0, "Do an automated test on the whole delpoy." },
60
61     // functions, can be combined
62     { "ls", '1', 0, 0, "Print all available root paths." },
63     { "schema", '2', "XPATH", 0, "Print schema for XPATH." },
64     { "populate", '3', 0, 0, "Populate everything." },
65     { "enable-features", '4', 0, 0, "Enables features. Usually works combined with populate." },
66
67     // function settings, can be combined with functions as well
68     { "nc-server-init", 'n', 0, 0, "Sets netconf server configuration." },
69     { "loop", 'l', 0, 0, "After doing the job, don't exit until CTRL+C is pressed." },
70     { 0 } 
71 };
72
73 volatile sig_atomic_t framework_sigint;
74 static void framework_signal_handler(int signo);
75
76 static error_t parse_opt(int key, char *arg, struct argp_state *state);
77
78 void framework_init(int argc, char **argv) {
79     //initialize app arguments
80     framework_arguments.container_init = false;
81     framework_arguments.nc_server_init = false;
82
83     framework_arguments.manager = false;
84     framework_arguments.network_function = false;
85     
86     framework_arguments.no_rand = false;
87     framework_arguments.fixed_seed = 0;
88     framework_arguments.operational_only = false;
89     framework_arguments.verbosity_level = 1;
90     framework_arguments.loop = false;
91     framework_arguments.test_mode = false;
92     
93     framework_arguments.exhaustive_test = false;
94     framework_arguments.print_root_paths = false;
95     framework_arguments.print_structure_xpath = 0;
96     framework_arguments.populate_all = false;
97     framework_arguments.enable_features = false;
98
99     framework_sigint = 0;
100     signal(SIGINT, framework_signal_handler);
101     signal(SIGTERM, framework_signal_handler);
102     signal(SIGKILL, framework_signal_handler);
103     signal(SIGQUIT, framework_signal_handler);
104
105     //parse provided command line arguments
106     struct argp argp = { options, parse_opt, 0, doc, 0, 0, 0 };
107     argp_parse(&argp, argc, argv, 0, 0, &framework_arguments);
108
109     //disable buffering for stdout
110     setbuf(stdout, NULL);
111
112     int status = 0;
113
114     //test whether log and config folders are ok
115     if(!dir_exists("config")) {
116         status |= 1;
117         mkdir("config", 0777);
118     }
119
120     if(!dir_exists("log")) {
121         status |= 2;
122         mkdir("log", 0777);
123     }
124
125     //init logging subsystem
126     log_init("log/log.txt");
127     log_message(2, "app was called: ");
128     for(int i = 0; i < argc; i++) {
129         log_message(2, "%s ", argv[i]);
130     }
131     log_message(2, "\n");
132
133     char cwd[PATH_MAX];
134     getcwd(cwd, sizeof(cwd));
135     log_message(2, "current working dir is: %s\n", cwd);
136
137     if(status & 1) {
138         log_message(2, "config folder wasn't found, and was created.\n");
139     }
140
141     if(status & 2) {
142         log_message(2, "log folder wasn't found, and was created.\n");
143     }
144
145     if(!file_exists("config/config.json")) {
146         log_message(2, "config.json file missing. created.\n");
147         file_touch("config/config.json", "{}");
148     }
149
150     //init rand generator if needed
151     if(framework_arguments.no_rand == false) {
152         rand_init();
153     }
154     else {
155         rand_init_fixed(framework_arguments.fixed_seed);
156     }
157
158     //init app config
159     framework_config.docker_excluded_modules = 0;
160     framework_config.docker_excluded_modules_count = 0;
161     framework_config.docker_excluded_features = 0;
162     framework_config.docker_excluded_features_count = 0;
163     framework_config.debug_max_string_size = 0;
164     framework_config.populate_excluded_modules = 0;
165     framework_config.populate_excluded_modules_count = 0;
166     framework_config.default_list_instances = 1;
167     framework_config.custom_list_instances_count = 0;
168     framework_config.custom_list_instances = 0;
169     framework_config.restrict_schema_count = 0;
170     framework_config.restrict_schema = 0;
171
172     log_message(2, "starting parsing config.json\n");
173     char *config_contents = file_read_content("config/config.json");
174     cJSON *json = cJSON_Parse(config_contents);
175     free(config_contents);
176     if(!json) {
177         log_error("config.json :%s", cJSON_GetErrorPtr());
178     }
179     else {
180         cJSON *main_node;
181         cJSON *node;
182
183         main_node = cJSON_GetObjectItem(json, "docker-rules");
184         if(main_node) {
185             node = cJSON_GetObjectItem(main_node, "excluded-modules");
186             if(node) {
187                 if(cJSON_IsArray(node)) {
188                     cJSON *element;
189                     cJSON_ArrayForEach(element, node) {
190                         if(cJSON_IsString(element)) {
191                             log_message(2, "adding docker-rules/exclude-modules: %s\n", element->valuestring);
192                             framework_config.docker_excluded_modules = (char **)realloc(framework_config.docker_excluded_modules, sizeof(char*) * (framework_config.docker_excluded_modules_count + 1));
193                             if(!framework_config.docker_excluded_modules) {
194                                 log_error("bad realloc");
195                             }
196                             framework_config.docker_excluded_modules[framework_config.docker_excluded_modules_count] = (char *)malloc(sizeof(char) * (strlen(element->valuestring) + 1));
197                             if(!framework_config.docker_excluded_modules[framework_config.docker_excluded_modules_count]) {
198                                 log_error("bad malloc");
199                             }
200                             strcpy(framework_config.docker_excluded_modules[framework_config.docker_excluded_modules_count], element->valuestring);
201                             framework_config.docker_excluded_modules_count++;
202                         }
203                     }
204                 }
205             }
206
207             node = cJSON_GetObjectItem(main_node, "excluded-features");
208             if(node) {
209                 if(cJSON_IsArray(node)) {
210                     cJSON *element;
211                     cJSON_ArrayForEach(element, node) {
212                         if(cJSON_IsString(element)) {
213                             log_message(2, "adding docker-rules/excluded-features: %s\n", element->valuestring);
214                             framework_config.docker_excluded_features = (char **)realloc(framework_config.docker_excluded_features, sizeof(char*) * (framework_config.docker_excluded_features_count + 1));
215                             if(!framework_config.docker_excluded_features) {
216                                 log_error("bad realloc");
217                             }
218                             framework_config.docker_excluded_features[framework_config.docker_excluded_features_count] = (char *)malloc(sizeof(char) * (strlen(element->valuestring) + 1));
219                             if(!framework_config.docker_excluded_features[framework_config.docker_excluded_features_count]) {
220                                 log_error("bad malloc");
221                             }
222                             strcpy(framework_config.docker_excluded_features[framework_config.docker_excluded_features_count], element->valuestring);
223                             framework_config.docker_excluded_features_count++;
224                         }
225                     }
226                 }
227             }
228         }
229
230         main_node = cJSON_GetObjectItem(json, "debug-max-string-size");
231         if(main_node) {
232             framework_config.debug_max_string_size = main_node->valueint;
233             log_message(2, "setting debug-max-string-sizes: %d\n", framework_config.debug_max_string_size);
234         }
235
236         main_node = cJSON_GetObjectItem(json, "populate-rules");
237         if(main_node) {
238             node = cJSON_GetObjectItem(main_node, "excluded-modules");
239             if(node) {
240                 if(cJSON_IsArray(node)) {
241                     cJSON *element;
242                     cJSON_ArrayForEach(element, node) {
243                         if(cJSON_IsString(element)) {
244                             log_message(2, "adding populate-rules/excluded-modules: %s\n", element->valuestring);
245                             framework_config.populate_excluded_modules = (char **)realloc(framework_config.populate_excluded_modules, sizeof(char*) * (framework_config.populate_excluded_modules_count + 1));
246                             if(!framework_config.populate_excluded_modules) {
247                                 log_error("bad realloc");
248                             }
249                             framework_config.populate_excluded_modules[framework_config.populate_excluded_modules_count] = (char *)malloc(sizeof(char) * (strlen(element->valuestring) + 1));
250                             if(!framework_config.populate_excluded_modules[framework_config.populate_excluded_modules_count]) {
251                                 log_error("bad malloc");
252                             }
253                             strcpy(framework_config.populate_excluded_modules[framework_config.populate_excluded_modules_count], element->valuestring);
254                             framework_config.populate_excluded_modules_count++;
255                         }
256                     }
257                 }
258             }
259
260             node = cJSON_GetObjectItem(main_node, "default-list-instances");
261             if(node) {
262                 if(cJSON_IsNumber(node)) {
263                     framework_config.default_list_instances = node->valueint;
264                     log_message(2, "found populate-rules/default-list-instances to be: %d\n", framework_config.default_list_instances);
265                 }
266             }
267
268             node = cJSON_GetObjectItem(main_node, "custom-list-instances");
269             if(node) {
270                 if(cJSON_IsArray(node)) {
271                     cJSON *element;
272                     cJSON_ArrayForEach(element, node) {
273                         if(cJSON_IsObject(element)) {
274                             cJSON *object;
275                             cJSON_ArrayForEach(object, element) {
276                                 char *path = object->string;
277                                 int count = object->valueint;
278                                 log_message(2, "adding populate-rules/custom-list-instances %s - %d\n", path, count);
279                                 framework_config.custom_list_instances = (custom_list_instances_t *)realloc(framework_config.custom_list_instances, sizeof(custom_list_instances_t) * (framework_config.custom_list_instances_count + 1));
280                                 if(!framework_config.custom_list_instances) {
281                                     log_error("bad realloc");
282                                 }
283                                 
284                                 framework_config.custom_list_instances[framework_config.custom_list_instances_count].path = (char *)malloc(sizeof(char) * (strlen(path) + 1));
285                                 if(!framework_config.custom_list_instances[framework_config.custom_list_instances_count].path) {
286                                     log_error("bad malloc");
287                                 }
288                                 strcpy(framework_config.custom_list_instances[framework_config.custom_list_instances_count].path, path);
289                                 framework_config.custom_list_instances[framework_config.custom_list_instances_count].count = count;
290                                 framework_config.custom_list_instances_count++;
291                             }
292                         }
293                     }
294                 }
295             }
296
297             node = cJSON_GetObjectItem(main_node, "restrict-schema");
298             if(node) {
299                 if(cJSON_IsArray(node)) {
300                     cJSON *element;
301                     cJSON_ArrayForEach(element, node) {
302                         if(cJSON_IsObject(element)) {
303                             cJSON *object;
304                             cJSON_ArrayForEach(object, element) {
305                                 char *path = object->string;
306
307                                 log_message(2, "adding populate-rules/restrict-schema: %s with values:", path);
308                                 framework_config.restrict_schema = (restrict_schema_t *)realloc(framework_config.restrict_schema, sizeof(restrict_schema_t) * (framework_config.restrict_schema_count + 1));
309                                 if(!framework_config.restrict_schema) {
310                                     log_error("bad realloc");
311                                 }
312                                 
313                                 framework_config.restrict_schema[framework_config.restrict_schema_count].path = (char *)malloc(sizeof(char) * (strlen(path) + 1));
314                                 if(!framework_config.restrict_schema[framework_config.restrict_schema_count].path) {
315                                     log_error("bad malloc");
316                                 }
317                                 strcpy(framework_config.restrict_schema[framework_config.restrict_schema_count].path, path);
318
319
320                                 framework_config.restrict_schema[framework_config.restrict_schema_count].values_count = 0;
321                                 framework_config.restrict_schema[framework_config.restrict_schema_count].values = 0;
322                                 framework_config.restrict_schema[framework_config.restrict_schema_count].index = 0;
323                                 cJSON *value;
324                                 cJSON_ArrayForEach(value, object) {
325                                     if(cJSON_IsString(value)) {
326                                         framework_config.restrict_schema[framework_config.restrict_schema_count].values = (char **)realloc(framework_config.restrict_schema[framework_config.restrict_schema_count].values, sizeof(char*) * (framework_config.restrict_schema[framework_config.restrict_schema_count].values_count + 1));
327                                         if(!framework_config.restrict_schema[framework_config.restrict_schema_count].values) {
328                                             log_error("bad realloc");
329                                         }
330                                         framework_config.restrict_schema[framework_config.restrict_schema_count].values[framework_config.restrict_schema[framework_config.restrict_schema_count].values_count] = (char *)malloc(sizeof(char) * (strlen(value->valuestring) + 1));
331                                         if(!framework_config.restrict_schema[framework_config.restrict_schema_count].values[framework_config.restrict_schema[framework_config.restrict_schema_count].values_count]) {
332                                             log_error("bad malloc");
333                                         }
334                                         strcpy(framework_config.restrict_schema[framework_config.restrict_schema_count].values[framework_config.restrict_schema[framework_config.restrict_schema_count].values_count], value->valuestring);
335                                         framework_config.restrict_schema[framework_config.restrict_schema_count].values_count++;
336
337                                         log_message(2, " %s", value->valuestring);
338                                     }
339                                 }
340                                 log_message(2, "\n");
341
342                                 framework_config.restrict_schema_count++;
343                             }
344                         }
345                     }
346                 }
347             }
348         }
349
350         cJSON_free(json);
351         
352     }
353     log_message(2, "finished parsing config.json\n");
354
355     //environment vars
356     bool ip_ok = get_local_ips("eth0", &framework_environment.ip_v4, &framework_environment.ip_v6);
357     if(!ip_ok) {
358         log_error("could not get local IP addresses");
359     }
360
361     char *ipv6_env_var = getenv(ENV_VAR_IPV6ENABLED);
362     if(ipv6_env_var == 0) {
363         log_error("could not get the IPv6 Enabled env variable");
364     }
365     framework_environment.ip_v6_enabled = (strcmp(ipv6_env_var, "true") == 0) ? true : false;
366
367
368     framework_environment.docker_engine_version = getenv(ENV_VAR_DOCKER_ENGINE_VERSION) ? strdup(getenv(ENV_VAR_DOCKER_ENGINE_VERSION)) : strdup("1.40");
369     framework_environment.hostname = getenv(ENV_VAR_HOSTNAME) ? strdup(getenv(ENV_VAR_HOSTNAME)) : strdup("localhost");
370     framework_environment.host_ip = getenv(ENV_VAR_HOST_IP) ? strdup(getenv(ENV_VAR_HOST_IP)) : strdup("127.0.0.1");
371     framework_environment.host_base_port = get_int_from_string_with_default(getenv(ENV_VAR_HOST_BASE_PORT), 1000);
372     framework_environment.ssh_connections = get_int_from_string_with_default(getenv(ENV_VAR_SSH_CONNECTIONS), 1);
373     framework_environment.tls_connections = get_int_from_string_with_default(getenv(ENV_VAR_TLS_CONNECTIONS), 0);
374     framework_environment.ftp_connections = 1;
375     framework_environment.sftp_connections = 1;
376
377     framework_environment.sdn_controller_ip = getenv(ENV_VAR_SDN_CONTROLLER_IP) ? strdup(getenv(ENV_VAR_SDN_CONTROLLER_IP)) : strdup("127.0.0.1");
378     framework_environment.sdn_controller_port = get_int_from_string_with_default(getenv(ENV_VAR_SDN_CONTROLLER_PORT), 8181);
379     framework_environment.sdn_controller_callhome_port = get_int_from_string_with_default(getenv(ENV_VAR_SDN_CONTROLLER_CALLHOME_PORT), 6666);
380     framework_environment.sdn_controller_username = getenv(ENV_VAR_SDN_CONTROLLER_USERNAME) ? strdup(getenv(ENV_VAR_SDN_CONTROLLER_USERNAME)) : strdup("admin");
381     framework_environment.sdn_controller_password = getenv(ENV_VAR_SDN_CONTROLLER_PASSWORD) ? strdup(getenv(ENV_VAR_SDN_CONTROLLER_PASSWORD)) : strdup("admin");
382
383     framework_environment.ves_endpoint_protocol = getenv(ENV_VAR_VES_ENDPOINT_PROTOCOL) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_PROTOCOL)) : strdup("https");
384     framework_environment.ves_endpoint_ip = getenv(ENV_VAR_VES_ENDPOINT_IP) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_IP)) : strdup("127.0.0.1");
385     framework_environment.ves_endpoint_port = get_int_from_string_with_default(getenv(ENV_VAR_VES_ENDPOINT_PORT), 1234);
386     framework_environment.ves_endpoint_auth_method = getenv(ENV_VAR_VES_ENDPOINT_AUTH_METHOD) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_AUTH_METHOD)) : strdup("no-auth");
387     framework_environment.ves_endpoint_username = getenv(ENV_VAR_VES_ENDPOINT_USERNAME) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_USERNAME)) : strdup("admin");
388     framework_environment.ves_endpoint_password = getenv(ENV_VAR_VES_ENDPOINT_PASSWORD) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_PASSWORD)) : strdup("admin");
389     framework_environment.ves_endpoint_certificate = getenv(ENV_VAR_VES_ENDPOINT_CERTIFICATE) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_CERTIFICATE)) : strdup("");
390
391     log_message(2, "[env] ip_v6_enabled = %s\n", framework_environment.ip_v6_enabled ? "true" : "false");
392     log_message(2, "[env] ip_v4 = %s\n", framework_environment.ip_v4);
393     log_message(2, "[env] ip_v6 = %s\n", framework_environment.ip_v6);
394     log_message(2, "[env] docker_engine_version = %s\n", framework_environment.docker_engine_version);
395     log_message(2, "[env] hostname = %s\n", framework_environment.hostname);
396     log_message(2, "[env] host_ip = %s\n", framework_environment.host_ip);
397     log_message(2, "[env] host_base_port = %d\n", framework_environment.host_base_port);
398     log_message(2, "[env] ssh_connections = %d\n", framework_environment.ssh_connections);
399     log_message(2, "[env] tls_connections = %d\n", framework_environment.tls_connections);
400     log_message(2, "[env] ftp_connections = %d\n", framework_environment.ftp_connections);
401     log_message(2, "[env] sftp_connections = %d\n", framework_environment.sftp_connections);
402
403     log_message(2, "[env] sdn_controller_ip = %s\n", framework_environment.sdn_controller_ip);
404     log_message(2, "[env] sdn_controller_port = %d\n", framework_environment.sdn_controller_port);
405     log_message(2, "[env] sdn_controller_callhome_port = %d\n", framework_environment.sdn_controller_callhome_port);
406     log_message(2, "[env] sdn_controller_username = %s\n", framework_environment.sdn_controller_username);
407     log_message(2, "[env] sdn_controller_password = %s\n", framework_environment.sdn_controller_password);
408
409     log_message(2, "[env] ves_endpoint_protocol = %s\n", framework_environment.ves_endpoint_protocol);
410     log_message(2, "[env] ves_endpoint_ip = %s\n", framework_environment.ves_endpoint_ip);
411     log_message(2, "[env] ves_endpoint_port = %d\n", framework_environment.ves_endpoint_port);
412     log_message(2, "[env] ves_endpoint_auth_method = %s\n", framework_environment.ves_endpoint_auth_method);
413     log_message(2, "[env] ves_endpoint_username = %s\n", framework_environment.ves_endpoint_username);
414     log_message(2, "[env] ves_endpoint_password = %s\n", framework_environment.ves_endpoint_password);
415     log_message(2, "[env] ves_endpoint_certificate = %s\n", framework_environment.ves_endpoint_certificate);
416
417     log_message(2, "finished environment vars\n");
418 }
419
420 void framework_free(void) {
421     log_message(2, "framework_free()... ");
422
423     free(framework_environment.ip_v4);
424     free(framework_environment.ip_v6);
425     free(framework_environment.docker_engine_version);
426     free(framework_environment.hostname);
427     free(framework_environment.host_ip);
428     free(framework_environment.sdn_controller_ip);
429     free(framework_environment.sdn_controller_username);
430     free(framework_environment.sdn_controller_password);
431     free(framework_environment.ves_endpoint_protocol);
432     free(framework_environment.ves_endpoint_ip);
433     free(framework_environment.ves_endpoint_auth_method);
434     free(framework_environment.ves_endpoint_username);
435     free(framework_environment.ves_endpoint_password);
436     free(framework_environment.ves_endpoint_certificate);
437
438     if(framework_arguments.print_structure_xpath) {
439         free(framework_arguments.print_structure_xpath);
440         framework_arguments.print_structure_xpath = 0;
441     }
442
443     if(framework_config.docker_excluded_modules_count) {
444         for(int i = 0; i < framework_config.docker_excluded_modules_count; i++) {
445             free(framework_config.docker_excluded_modules[i]);
446         }
447         free(framework_config.docker_excluded_modules);
448     }
449
450     if(framework_config.docker_excluded_features_count) {
451         for(int i = 0; i < framework_config.docker_excluded_features_count; i++) {
452             free(framework_config.docker_excluded_features[i]);
453         }
454         free(framework_config.docker_excluded_features);
455     }
456
457     if(framework_config.populate_excluded_modules_count) {
458         for(int i = 0; i < framework_config.populate_excluded_modules_count; i++) {
459             free(framework_config.populate_excluded_modules[i]);
460         }
461         free(framework_config.populate_excluded_modules);
462     }
463
464     for(int i = 0; i < framework_config.custom_list_instances_count; i++) {
465         free(framework_config.custom_list_instances[i].path);
466         
467     }
468     free(framework_config.custom_list_instances);
469
470     for(int i = 0; i < framework_config.restrict_schema_count; i++) {
471         free(framework_config.restrict_schema[i].path);
472         for(int j = 0; j < framework_config.restrict_schema[i].values_count; j++) {
473             free(framework_config.restrict_schema[i].values[j]);
474         }
475         free(framework_config.restrict_schema[i].values);
476     }
477     free(framework_config.restrict_schema);
478
479     log_message(2, "done\n");
480     log_close();
481     if(framework_arguments.container_init) {
482         rename("log/log.txt", "log/install_log.txt");
483     }
484 }
485
486 bool framework_is_docker_excluded_module(const char *module) {
487     assert(module);
488
489     for(int i = 0; i < framework_config.docker_excluded_modules_count; i++) {
490         if(strstr(module, framework_config.docker_excluded_modules[i]) != 0) {
491             return true;
492         }
493     }
494     
495     return false;
496 }
497
498 bool framework_is_docker_excluded_feature(const char *feature) {
499     assert(feature);
500
501     for(int i = 0; i < framework_config.docker_excluded_features_count; i++) {
502         if(strstr(feature, framework_config.docker_excluded_features[i]) != 0) {
503             return true;
504         }
505     }
506     
507     return false;
508 }
509
510 bool framework_is_populate_excluded_module(const char *module) {
511     assert(module);
512
513     for(int i = 0; i < framework_config.populate_excluded_modules_count; i++) {
514         if(strstr(module, framework_config.populate_excluded_modules[i]) != 0) {
515             return true;
516         }
517     }
518     
519     return false;
520 }
521
522 int framework_populate_get_instance_count(const char *path) {
523     assert(path);
524
525     for(int i = 0; i < framework_config.custom_list_instances_count; i++) {
526         if(strcmp(path, framework_config.custom_list_instances[i].path) == 0) {
527             return framework_config.custom_list_instances[i].count;
528         }
529     }
530     return framework_config.default_list_instances;
531 }
532
533 char *framework_populate_get_restrict_schema(const char *path) {
534     assert(path);
535     char *ret = 0;
536
537     for(int i = 0; i < framework_config.restrict_schema_count; i++) {
538         if(strcmp(path, framework_config.restrict_schema[i].path) == 0) {
539             ret = strdup(framework_config.restrict_schema[i].values[framework_config.restrict_schema[i].index]);
540             framework_config.restrict_schema[i].index++;
541             if(framework_config.restrict_schema[i].index >= framework_config.restrict_schema[i].values_count) {
542                 framework_config.restrict_schema[i].index = 0;
543             }
544             break;
545         }
546     }
547
548     return ret;
549 }
550
551 static void framework_signal_handler(int signo) {
552     framework_sigint = 1;
553 }
554
555 static error_t parse_opt(int key, char *arg, struct argp_state *state) {
556     framework_arguments_t *iter_arguments = state->input;
557     switch (key) {
558         case 'i':
559             iter_arguments->container_init = true;
560             break;
561
562         case 'n':
563             iter_arguments->nc_server_init = true;
564             break;
565
566         case 'm':
567             iter_arguments->manager = true;
568             break;
569
570         case 'f':
571             iter_arguments->network_function = true;
572             break;
573
574
575         case 'l':
576             iter_arguments->loop = true;
577             break;
578
579         case 'r':
580             iter_arguments->no_rand = true;
581             framework_arguments.fixed_seed = 0;
582             int i = 0;
583             while(arg[i]) {
584                 framework_arguments.fixed_seed *= 10;
585                 framework_arguments.fixed_seed += arg[i] - '0';
586                 i++;
587             }
588             break;
589
590         case 'o':
591             iter_arguments->operational_only = true;
592             break;
593
594         case 't':
595             iter_arguments->test_mode = true;
596             break;
597
598         case 'v':
599             iter_arguments->verbosity_level = arg[0] - '0';
600             break;
601
602         case 'w':
603             chdir(arg);
604             break;
605
606         case '0':
607             iter_arguments->exhaustive_test = true;
608             break;
609
610         case '1':
611             iter_arguments->print_root_paths = true;
612             break;
613
614         case '2':
615             iter_arguments->print_structure_xpath = (char *)malloc(sizeof(char) * (strlen(arg) + 1));
616             if(!iter_arguments->print_structure_xpath) {
617                 log_error("very bad malloc failure here");
618                 return 1;
619             }
620             strcpy(iter_arguments->print_structure_xpath, arg);
621             if(arg[strlen(arg) - 1] == '/') {
622                 iter_arguments->print_structure_xpath[strlen(arg) - 1] = 0;
623             }
624             break;
625
626         case '3':
627             iter_arguments->populate_all = true;
628             break;
629
630         case '4':
631             iter_arguments->enable_features = true;
632             break;
633
634         case ARGP_KEY_ARG:
635             if (state->arg_num >= 2) {
636                 argp_usage(state);
637             }
638             break;
639
640         case ARGP_KEY_END:
641
642             break;
643
644         default:
645             return ARGP_ERR_UNKNOWN;
646     }
647     
648     return 0;
649 }