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 ***************************************************************************/
20 #include "container.h"
21 #include "utils/log_utils.h"
22 #include "utils/sys_utils.h"
23 #include "utils/http_client.h"
24 #include "core/framework.h"
25 #include "core/session.h"
26 #include "core/context.h"
31 struct installable_module {
39 static int get_installable_modules(struct installable_module **modules); //list available modules for install
40 static void list_yangs(const char *path, struct installable_module **modules, int *total);
41 static bool container_rules_is_excluded_module(const char *module);
42 static bool container_rules_is_excluded_feature(const char *feature);
44 bool container_self_init(void) {
47 sr_log_stderr(SR_LL_NONE);
48 log_add_verbose(1, "Entering container-init mode...\n");
51 rc = sr_connect(0, &session_connection);
53 log_error("sr_connect failed\n");
58 session_context = (struct ly_ctx *)sr_get_context(session_connection);
59 if(session_context == 0) {
60 log_error("sr_get_context failed\n");
64 /* install yang files */
65 log_add_verbose(1, "Installing yang files...\n");
66 struct installable_module *modules;
67 int total_modules = get_installable_modules(&modules);
68 log_add_verbose(1, "Found total modules: %d\n", total_modules);
70 int old_failed_installations = 1;
71 int failed_installations = 0;
72 int install_round = 0;
73 while(failed_installations != old_failed_installations) {
74 old_failed_installations = failed_installations;
75 failed_installations = 0;
77 for(int i = 0; i < total_modules; i++) {
78 if(!modules[i].installed) {
79 modules[i].submodule = context_yang_is_module(modules[i].fullpath);
80 if(!modules[i].submodule) {
81 if(!container_rules_is_excluded_module(modules[i].name)) {
82 log_add_verbose(1, "[round %d] trying to install module %s from %s... ", install_round, modules[i].name, modules[i].fullpath);
83 if(!context_module_install(modules[i].name, modules[i].fullpath)) {
84 failed_installations++;
85 log_add(1, LOG_COLOR_BOLD_YELLOW"failed"LOG_COLOR_RESET"\n");
88 log_add(1, LOG_COLOR_BOLD_GREEN"done"LOG_COLOR_RESET"\n");
89 modules[i].installed = true;
93 log_add_verbose(1, "[round %d] not installing module %s as it's excluded in config.\n", install_round, modules[i].name);
94 modules[i].installed = true;
98 log_add_verbose(1, "[round %d] %s is a submodule... "LOG_COLOR_BOLD_YELLOW"skipping"LOG_COLOR_RESET"\n", install_round, modules[i].name);
99 modules[i].installed = true;
105 if(failed_installations != 0) {
106 log_error("failed to install all modules in %d rounds...\n", install_round);
110 log_add_verbose(1, LOG_COLOR_BOLD_GREEN"successfully"LOG_COLOR_RESET" installed "LOG_COLOR_BOLD_GREEN"ALL"LOG_COLOR_RESET" modules in "LOG_COLOR_BOLD_YELLOW"%d"LOG_COLOR_RESET" rounds\n", (install_round - 1));
113 //set access for all installed modules
114 log_add_verbose(1, "Setting access configuration for installed modules... ");
115 for(int i = 0; i < total_modules; i++) {
116 if((!container_rules_is_excluded_module(modules[i].name)) && (!modules[i].submodule)) {
117 if(!context_module_set_access(modules[i].name)) {
118 log_error("failed to set access to module %s...\n", modules[i].name);
123 log_add(1, LOG_COLOR_BOLD_GREEN"done"LOG_COLOR_RESET"\n");
125 //cleanup module-install used memory
126 for(int i = 0; i < total_modules; i++) {
127 free(modules[i].name);
128 free(modules[i].fullpath);
133 session_context = (struct ly_ctx *)sr_get_context(session_connection);
134 if(session_context == 0) {
135 log_error("sr_get_context failed\n");
139 //init context so we can see all the available modules, features, etc
140 rc = context_init(session_context);
142 log_error("context_init() failed\n");
146 /* enable features */
147 log_add_verbose(1, "Enabling yang features...\n");
148 char **available_features;
149 int total_available_features;
150 total_available_features = context_get_features(&available_features);
151 log_add_verbose(1, "Found total features: %d\n", total_available_features);
152 for(int i = 0; i < total_available_features; i++) {
153 log_add_verbose(1, "feature %s: ", available_features[i]);
155 if(!context_get_feature_enabled(available_features[i])) {
156 if(!container_rules_is_excluded_feature(available_features[i])) {
157 if(context_feature_enable(available_features[i])) {
158 log_add(1, "enabling... "LOG_COLOR_BOLD_GREEN"done"LOG_COLOR_RESET"\n");
161 log_error("enabling... failed\n");
165 log_add(1, "excluded in config, skipping\n");
169 log_add(1, "already "LOG_COLOR_BOLD_GREEN"enabled"LOG_COLOR_RESET", skipping.\n");
172 for(int i = 0; i < total_available_features; i++) {
173 free(available_features[i]);
175 free(available_features);
177 sr_disconnect(session_connection);
180 log_add_verbose(1, LOG_COLOR_BOLD_GREEN"ntsim successfully initialized Docker container"LOG_COLOR_RESET"\n");
184 static int get_installable_modules(struct installable_module **modules) {
187 list_yangs("/opt/dev/deploy/yang", modules, &total);
191 static void list_yangs(const char *path, struct installable_module **modules, int *total) {
196 while((dir = readdir(d)) != NULL) {
197 if(dir->d_type == DT_DIR) {
198 if(strcmp(dir->d_name, ".") != 0 && strcmp(dir->d_name, "..") != 0)
201 snprintf(new_path, sizeof(new_path), "%s/%s", path, dir->d_name);
202 list_yangs(new_path, modules, total);
205 if(strstr(dir->d_name, ".yang") != 0) {
206 *modules = (struct installable_module *)realloc(*modules, sizeof(struct installable_module) * (*total + 1));
208 log_error("allocation failed\n");
212 (*modules)[*total].name = (char*)malloc(sizeof(char) * (strlen(dir->d_name) + 1));
213 if(!(*modules)[*total].name) {
214 log_error("allocation failed\n");
217 strcpy((*modules)[*total].name, dir->d_name);
218 (*modules)[*total].name[strlen(dir->d_name) - 5] = 0; //extract ".yang"
219 char *rev = strstr((*modules)[*total].name, "@");
220 if(rev) { //extract revision, if exists
224 (*modules)[*total].fullpath = (char*)malloc(sizeof(char) * (strlen(path) + 1 + strlen(dir->d_name) + 1));
225 if(!(*modules)[*total].fullpath) {
226 log_error("allocation failed\n");
229 sprintf((*modules)[*total].fullpath, "%s/%s", path, dir->d_name);
231 (*modules)[*total].installed = false;
232 (*modules)[*total].submodule = false;
242 static bool container_rules_is_excluded_module(const char *module) {
245 for(int i = 0; i < framework_config.docker.excluded_modules_count; i++) {
246 if(strstr(module, framework_config.docker.excluded_modules[i]) != 0) {
254 static bool container_rules_is_excluded_feature(const char *feature) {
257 for(int i = 0; i < framework_config.docker.excluded_features_count; i++) {
258 if(strstr(feature, framework_config.docker.excluded_features[i]) != 0) {