3571ab4667638cd1e84e93ea18c999b8c9859468
[sim/o1-interface.git] / ntsimulator / src / ntsimulator-manager / ntsimulator-manager.c
1 /*************************************************************************
2 *
3 * Copyright 2019 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
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <signal.h>
23 #include <inttypes.h>
24 #include <limits.h>
25 #include <string.h>
26
27 #include "sysrepo.h"
28 #include "sysrepo/values.h"
29
30 #include "utils.h"
31 #include "simulator-operations.h"
32
33 volatile int exit_application = 0;
34
35 volatile unsigned int simulated_devices_config = 0;
36 volatile unsigned int mounted_devices_config = 0;
37
38
39 static device_stack_t *device_list = NULL;
40
41 controller_t controller_details;
42
43 #define XPATH_MAX_LEN 500
44 #define CONTROLLER_LIST_MAX_LEN 1
45
46 static void
47 print_current_config(sr_session_ctx_t *session, const char *module_name)
48 {
49     sr_val_t *values = NULL;
50     size_t count = 0;
51     int rc = SR_ERR_OK;
52     char xpath[XPATH_MAX_LEN] = {0};
53     snprintf(xpath, XPATH_MAX_LEN, "/%s:*//.", module_name);
54
55     sr_val_t *odl_ip = NULL;
56     sr_val_t *odl_port = NULL;
57     sr_val_t *odl_username = NULL;
58     sr_val_t *odl_password = NULL;
59
60     rc = sr_get_items(session, xpath, &values, &count);
61     if (SR_ERR_OK != rc) {
62         printf("Error by sr_get_items: %s\n", sr_strerror(rc));
63         return;
64     }
65     for (size_t i = 0; i < count; i++){
66
67         sr_print_val(&values[i]);
68
69         if (sr_xpath_node_name_eq(values[i].xpath, "controller-ip"))
70         {
71                 rc = sr_dup_val(&values[i], &odl_ip);
72         }
73         else if (sr_xpath_node_name_eq(values[i].xpath, "controller-port"))
74         {
75                 rc = sr_dup_val(&values[i], &odl_port);
76         }
77         else if (sr_xpath_node_name_eq(values[i].xpath, "controller-username"))
78         {
79                 rc = sr_dup_val(&values[i], &odl_username);
80         }
81         else if (sr_xpath_node_name_eq(values[i].xpath, "controller-password"))
82         {
83                 rc = sr_dup_val(&values[i], &odl_password);
84         }
85     }
86
87     char *ipv6 = strchr(odl_ip->data.string_val, ':');
88     char odl_ip_string[URL_AND_CREDENTIALS_MAX_LEN];
89     if (ipv6 != NULL)
90     {
91         sprintf(odl_ip_string, "[%s]", odl_ip->data.string_val);
92     }
93     else
94     {
95         sprintf(odl_ip_string, "%s", odl_ip->data.string_val);
96     }
97
98
99     //URL used for mounting/unmounting a device; the device name needs to be appended
100    char url[URL_AND_CREDENTIALS_MAX_LEN];
101    sprintf(url, "http://%s:%d/restconf/config/network-topology:network-topology/topology/"
102                  "topology-netconf/node/",
103                  odl_ip_string, odl_port->data.uint32_val);
104
105    char credentials[URL_AND_CREDENTIALS_MAX_LEN];
106    sprintf(credentials, "%s:%s", odl_username->data.string_val, odl_password->data.string_val);
107
108    //URLs used for adding key pair to ODL, for TLS connections
109    char url_for_keystore_add[URL_AND_CREDENTIALS_MAX_LEN];
110    sprintf(url_for_keystore_add, "http://%s:%d/restconf/operations/netconf-keystore:add-keystore-entry",
111                          odl_ip_string, odl_port->data.uint32_val);
112
113    char url_for_private_key_add[URL_AND_CREDENTIALS_MAX_LEN];
114    sprintf(url_for_private_key_add, "http://%s:%d/restconf/operations/netconf-keystore:add-private-key",
115                          odl_ip_string, odl_port->data.uint32_val);
116
117    char url_for_trusted_ca_add[URL_AND_CREDENTIALS_MAX_LEN];
118    sprintf(url_for_trusted_ca_add, "http://%s:%d/restconf/operations/netconf-keystore:add-trusted-certificate",
119                          odl_ip_string, odl_port->data.uint32_val);
120
121    strcpy(controller_details.url, url);
122    strcpy(controller_details.credentials, credentials);
123    strcpy(controller_details.url_for_keystore_add, url_for_keystore_add);
124    strcpy(controller_details.url_for_private_key_add, url_for_private_key_add);
125    strcpy(controller_details.url_for_trusted_ca_add, url_for_trusted_ca_add);
126
127    sr_free_val(odl_ip);
128    sr_free_val(odl_port);
129    sr_free_val(odl_username);
130    sr_free_val(odl_password);
131
132    sr_free_values(values, count);
133 }
134
135 static void clean_current_docker_configuration(void);
136
137 static int simulated_devices_changed(int new_value)
138 {
139         int rc = SR_ERR_OK;
140
141     if (strcmp(getenv("K8S_DEPLOYMENT"), "true") == 0)
142     {
143         if (new_value != simulated_devices_config)
144         {
145             simulated_devices_config = new_value;
146             rc = send_k8s_scale(new_value);
147             if (rc != SR_ERR_OK)
148             {
149                 printf("Could not send new_scale=%d to k8s cluster.\n", new_value);
150             }
151         }
152         return SR_ERR_OK;
153     }
154
155     if (simulated_devices_config > new_value)
156     {
157         //we are configuring less elements that currently
158         for (int i = 0; i < simulated_devices_config - new_value; ++i)
159         {
160                 rc = stop_device(device_list);
161         }
162     }
163     else if (simulated_devices_config < new_value)
164     {
165         //we are configuring more elements that currently
166         for (int i = 0; i < new_value - simulated_devices_config; ++i)
167         {
168                 rc = start_device(device_list);
169             if (rc != SR_ERR_OK)
170             {
171                 printf("ERROR: Could not start simulated device. Ignoring, trying with the next simulated device, if any...\n");
172             }
173         }
174     }
175
176     simulated_devices_config = new_value;
177
178     return rc;
179 }
180
181 int mounted_devices_changed(sr_session_ctx_t *session, int new_value)
182 {
183         int rc = SR_ERR_OK;
184
185         if (mounted_devices_config > new_value)
186         {
187           //we need have less mounted elements
188           for (int i = 0; i < mounted_devices_config - new_value; ++i)
189           {
190                   printf("Sending unmount device...\n");
191                   rc = unmount_device(device_list, controller_details);
192           }
193         }
194         else if (mounted_devices_config < new_value)
195         {
196           //we are configuring more elements that currently
197           for (int i = 0; i < new_value - mounted_devices_config; ++i)
198           {
199                   printf("Sending mount device...\n");
200                   rc = mount_device(device_list, controller_details);
201           }
202         }
203
204         mounted_devices_config = new_value;
205
206     return rc;
207 }
208
209 static int
210 simulator_config_change_cb(sr_session_ctx_t *session, const char *module_name, sr_notif_event_t event, void *private_ctx)
211 {
212         int rc;
213
214     printf("\n\n ========== CONFIG HAS CHANGED, CURRENT RUNNING CONFIG %s: ==========\n\n", module_name);
215     print_current_config(session, module_name);
216
217     sr_val_t *val = NULL;
218
219     /* get the value from sysrepo, we do not care if the value did not change in our case */
220     rc = sr_get_item(session, "/network-topology-simulator:simulator-config/simulated-devices", &val);
221     if (rc != SR_ERR_OK) {
222         goto sr_error;
223     }
224
225     rc = simulated_devices_changed(val->data.uint32_val);
226     if (rc != SR_ERR_OK) {
227         goto sr_error;
228     }
229
230     sr_free_val(val);
231         val = NULL;
232
233     /* get the value from sysrepo, we do not care if the value did not change in our case */
234     rc = sr_get_item(session, "/network-topology-simulator:simulator-config/mounted-devices", &val);
235     if (rc != SR_ERR_OK) {
236         goto sr_error;
237     }
238
239     if (mounted_devices_config != val->data.uint32_val)
240     {
241         if (val->data.uint32_val > simulated_devices_config)
242         {
243                 printf("Cannot set mount value greater than number of simulated devices.\n");
244                 sr_free_val(val);
245                         val = NULL;
246                 return SR_ERR_OK;
247         }
248
249                 rc = mounted_devices_changed(session, val->data.uint32_val);
250                 if (rc != SR_ERR_OK) {
251                         goto sr_error;
252                 }
253     }
254
255     sr_free_val(val);
256         val = NULL;
257
258     size_t count = 0;
259
260     /* get the value from sysrepo, we do not care if the value did not change in our case */
261     rc = sr_get_items(session, "/network-topology-simulator:simulator-config/notification-config/fault-notification-delay-period", &val, &count);
262     if (rc != SR_ERR_OK) {
263         goto sr_error;
264     }
265
266     rc = notification_delay_period_changed(val, count);
267     if (rc != SR_ERR_OK) {
268         goto sr_error;
269     }
270     sr_free_values(val, count);
271         val = NULL;
272
273     /* get the value from sysrepo, we do not care if the value did not change in our case */
274         rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/ves-heartbeat-period", &val);
275         if (rc != SR_ERR_OK) {
276                 goto sr_error;
277         }
278
279         rc = ves_heartbeat_period_changed(val->data.uint32_val);
280         if (rc != SR_ERR_OK) {
281                 goto sr_error;
282         }
283
284         sr_free_val(val);
285         val = NULL;
286
287     /* get the value from sysrepo, we do not care if the value did not change in our case */
288     rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-ip", &val);
289     if (rc != SR_ERR_OK) {
290         goto sr_error;
291     }
292
293     rc = ves_ip_changed(val->data.string_val);
294     if (rc != SR_ERR_OK) {
295         goto sr_error;
296     }
297
298     sr_free_val(val);
299     val = NULL;
300
301     /* get the value from sysrepo, we do not care if the value did not change in our case */
302     rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-auth-method", &val);
303     if (rc != SR_ERR_OK) {
304         goto sr_error;
305     }
306
307     rc = ves_auth_method_changed(val->data.enum_val);
308     if (rc != SR_ERR_OK) {
309         goto sr_error;
310     }
311
312     if (strcmp(val->data.enum_val, "basic-auth") == 0)
313     {
314         sr_free_val(val);
315         val = NULL;
316
317         /* get the value from sysrepo, we do not care if the value did not change in our case */
318         rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-username", &val);
319         if (rc != SR_ERR_OK) {
320             goto sr_error;
321         }
322
323         rc = ves_username_changed(val->data.string_val);
324         if (rc != SR_ERR_OK) {
325             goto sr_error;
326         }
327
328         sr_free_val(val);
329         val = NULL;
330
331         /* get the value from sysrepo, we do not care if the value did not change in our case */
332         rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-password", &val);
333         if (rc != SR_ERR_OK) {
334             goto sr_error;
335         }
336
337         rc = ves_password_changed(val->data.string_val);
338         if (rc != SR_ERR_OK) {
339             goto sr_error;
340         }
341
342         sr_free_val(val);
343         val = NULL;
344     }
345     else 
346     {
347         sr_free_val(val);
348         val = NULL;
349     }
350
351         /* get the value from sysrepo, we do not care if the value did not change in our case */
352         rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-port", &val);
353         if (rc != SR_ERR_OK) {
354                 goto sr_error;
355         }
356
357         rc = ves_port_changed(val->data.uint16_val);
358         if (rc != SR_ERR_OK) {
359                 goto sr_error;
360         }
361
362         sr_free_val(val);
363         val = NULL;
364
365         /* get the value from sysrepo, we do not care if the value did not change in our case */
366         rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-registration", &val);
367         if (rc != SR_ERR_OK) {
368                 goto sr_error;
369         }
370
371         rc = ves_registration_changed(val->data.bool_val);
372         if (rc != SR_ERR_OK) {
373                 goto sr_error;
374         }
375
376         sr_free_val(val);
377         val = NULL;
378
379         /* get the value from sysrepo, we do not care if the value did not change in our case */
380         rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/is-netconf-available", &val);
381         if (rc != SR_ERR_OK) {
382                 goto sr_error;
383         }
384
385         rc = is_netconf_available_changed(val->data.bool_val);
386         if (rc != SR_ERR_OK) {
387                 goto sr_error;
388         }
389
390         sr_free_val(val);
391         val = NULL;
392
393     /* get the value from sysrepo, we do not care if the value did not change in our case */
394     rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/is-ves-available", &val);
395     if (rc != SR_ERR_OK) {
396         goto sr_error;
397     }
398
399     rc = is_ves_available_changed(val->data.bool_val);
400     if (rc != SR_ERR_OK) {
401         goto sr_error;
402     }
403
404     sr_free_val(val);
405     val = NULL;
406
407     /* get the value from sysrepo, we do not care if the value did not change in our case */
408     rc = sr_get_item(session, "/network-topology-simulator:simulator-config/netconf-call-home", &val);
409     if (rc != SR_ERR_OK) {
410         goto sr_error;
411     }
412
413     rc = netconf_call_home_changed(val->data.bool_val);
414     if (rc != SR_ERR_OK) {
415         goto sr_error;
416     }
417
418     sr_free_val(val);
419     val = NULL;
420
421     /* get the value from sysrepo, we do not care if the value did not change in our case */
422     rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-ip", &val);
423     if (rc != SR_ERR_OK) {
424         goto sr_error;
425     }
426
427     rc = controller_ip_changed(val->data.string_val);
428     if (rc != SR_ERR_OK) {
429         goto sr_error;
430     }
431
432     sr_free_val(val);
433     val = NULL;
434
435     /* get the value from sysrepo, we do not care if the value did not change in our case */
436     rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-port", &val);
437     if (rc != SR_ERR_OK) {
438         goto sr_error;
439     }
440
441     rc = controller_port_changed(val->data.uint16_val);
442     if (rc != SR_ERR_OK) {
443         goto sr_error;
444     }
445
446     sr_free_val(val);
447     val = NULL;
448
449     /* get the value from sysrepo, we do not care if the value did not change in our case */
450     rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/netconf-call-home-port", &val);
451     if (rc != SR_ERR_OK) {
452         goto sr_error;
453     }
454
455     rc = controller_netconf_call_home_port_changed(val->data.uint16_val);
456     if (rc != SR_ERR_OK) {
457         goto sr_error;
458     }
459
460     sr_free_val(val);
461     val = NULL;
462
463     /* get the value from sysrepo, we do not care if the value did not change in our case */
464     rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-username", &val);
465     if (rc != SR_ERR_OK) {
466         goto sr_error;
467     }
468
469     rc = controller_username_changed(val->data.string_val);
470     if (rc != SR_ERR_OK) {
471         goto sr_error;
472     }
473
474     sr_free_val(val);
475     val = NULL;
476
477     /* get the value from sysrepo, we do not care if the value did not change in our case */
478     rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-password", &val);
479     if (rc != SR_ERR_OK) {
480         goto sr_error;
481     }
482
483     rc = controller_password_changed(val->data.string_val);
484     if (rc != SR_ERR_OK) {
485         goto sr_error;
486     }
487
488     sr_free_val(val);
489     val = NULL;
490
491     return SR_ERR_OK;
492
493 sr_error:
494         printf("NTSimulator config change callback failed: %s.", sr_strerror(rc));
495         if (val != NULL)
496         {
497                 sr_free_val(val);
498                 val = NULL;
499         }
500         return rc;
501 }
502
503 static int
504 simulator_status_cb(const char *xpath, sr_val_t **values, size_t *values_cnt,
505         uint64_t request_id, const char *original_xpath, void *private_ctx)
506 {
507         int rc;
508
509         // printf("\n\n ========== Called simulator_status_cb for xpath: %s ==========\n\n", xpath);
510
511     counterAlarms ves_counter, netconf_counter;
512     rc = compute_notifications_count(&ves_counter, &netconf_counter);
513     if (rc != SR_ERR_OK)
514     {
515         printf("Could not compute the total number of notification count.\n");
516     }
517
518         if (sr_xpath_node_name_eq(xpath, "simulated-devices-list")) 
519     {
520                 sr_val_t *v;
521                 size_t current_num_of_values= 0;
522
523                 if (simulated_devices_config == 0) //nothing to return if no devices are running
524                 {
525                         *values = NULL;
526                         *values_cnt = 0;
527
528                         return SR_ERR_OK;
529                 }
530
531         rc = get_docker_containers_operational_state_curl(device_list);
532         if (rc != SR_ERR_OK)
533         {
534             printf("Could not get the operational state for the devices simulated.\n");
535             return SR_ERR_OPERATION_FAILED;
536         }
537
538                 device_t *current_device = device_list->head;
539
540                 while (current_device != NULL)
541                 {
542             counterAlarms vesCount, netconfCount;
543             rc = getDeviceCounters(current_device->device_id, &vesCount, &netconfCount);
544             if (rc != SR_ERR_OK)
545             {
546                 printf("Could not get Notification Counters for device with uuid=\"%s\"", current_device->device_id);
547             }
548
549             char device_name[200];
550             sprintf(device_name, "%s-%d", getenv("CONTAINER_NAME"), current_device->device_number);            
551
552                         CREATE_NEW_VALUE(rc, v, current_num_of_values);
553
554                         sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, device_name, "device-ip");
555                         v[current_num_of_values - 1].type = SR_STRING_T;
556                         v[current_num_of_values - 1].data.string_val = getenv("NTS_IP");
557
558                         for (int i = 0; i < NETCONF_CONNECTIONS_PER_DEVICE; ++i)
559                         {
560                                 CREATE_NEW_VALUE(rc, v, current_num_of_values);
561
562                                 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, device_name, "device-port");
563                                 v[current_num_of_values - 1].type = SR_UINT32_T;
564                                 v[current_num_of_values - 1].data.uint32_val = current_device->netconf_port + i;
565                         }
566
567                         CREATE_NEW_VALUE(rc, v, current_num_of_values);
568
569                         sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, device_name, "is-mounted");
570                         v[current_num_of_values - 1].type = SR_BOOL_T;
571                         v[current_num_of_values - 1].data.bool_val = current_device->is_mounted;
572
573                         char *operational_state = get_docker_container_operational_state(device_list, current_device->device_id);
574
575                         CREATE_NEW_VALUE(rc, v, current_num_of_values);
576
577                         sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, device_name, "operational-state");
578                         sr_val_build_str_data(&v[current_num_of_values - 1], SR_ENUM_T, "%s", operational_state);
579
580             CREATE_NEW_VALUE(rc, v, current_num_of_values);
581
582             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "normal");
583             v[current_num_of_values - 1].type = SR_UINT32_T;
584             v[current_num_of_values - 1].data.uint32_val = vesCount.normal;
585
586             CREATE_NEW_VALUE(rc, v, current_num_of_values);
587
588             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "warning");
589             v[current_num_of_values - 1].type = SR_UINT32_T;
590             v[current_num_of_values - 1].data.uint32_val = vesCount.warning;
591
592             CREATE_NEW_VALUE(rc, v, current_num_of_values);
593
594             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "minor");
595             v[current_num_of_values - 1].type = SR_UINT32_T;
596             v[current_num_of_values - 1].data.uint32_val = vesCount.minor;
597
598             CREATE_NEW_VALUE(rc, v, current_num_of_values);
599
600             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "major");
601             v[current_num_of_values - 1].type = SR_UINT32_T;
602             v[current_num_of_values - 1].data.uint32_val = vesCount.major;
603
604             CREATE_NEW_VALUE(rc, v, current_num_of_values);
605
606             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "critical");
607             v[current_num_of_values - 1].type = SR_UINT32_T;
608             v[current_num_of_values - 1].data.uint32_val = vesCount.critical;
609
610             CREATE_NEW_VALUE(rc, v, current_num_of_values);
611
612             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "normal");
613             v[current_num_of_values - 1].type = SR_UINT32_T;
614             v[current_num_of_values - 1].data.uint32_val = netconfCount.normal;
615
616             CREATE_NEW_VALUE(rc, v, current_num_of_values);
617
618             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "warning");
619             v[current_num_of_values - 1].type = SR_UINT32_T;
620             v[current_num_of_values - 1].data.uint32_val = netconfCount.warning;
621
622             CREATE_NEW_VALUE(rc, v, current_num_of_values);
623
624             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "minor");
625             v[current_num_of_values - 1].type = SR_UINT32_T;
626             v[current_num_of_values - 1].data.uint32_val = netconfCount.minor;
627
628             CREATE_NEW_VALUE(rc, v, current_num_of_values);
629
630             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "major");
631             v[current_num_of_values - 1].type = SR_UINT32_T;
632             v[current_num_of_values - 1].data.uint32_val = netconfCount.major;
633
634             CREATE_NEW_VALUE(rc, v, current_num_of_values);
635
636             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "critical");
637             v[current_num_of_values - 1].type = SR_UINT32_T;
638             v[current_num_of_values - 1].data.uint32_val = netconfCount.critical;
639
640                         current_device = current_device->next;
641                 }
642
643                 //return the values that we have just created
644                 *values = v;
645                 *values_cnt = current_num_of_values;
646          }
647          else if (sr_xpath_node_name_eq(xpath, "simulation-usage-details"))
648          {
649                 float cpu_usage = 0.0, mem_usage = 0.0;
650
651                 char *resource_usage_from_script = get_docker_container_resource_stats();
652
653                 if (resource_usage_from_script != NULL)
654                 {
655                         printf("Received line: %s\n", resource_usage_from_script);
656                         sscanf(resource_usage_from_script, "CPU=%f%%;RAM=%fMiB", &cpu_usage, &mem_usage);
657                         printf("Read cpu=\"%f\" and mem=\"%f\"\n", cpu_usage, mem_usage);
658                         free(resource_usage_from_script);
659                 }
660
661                 sr_val_t *v;
662                 /* convenient functions such as this can be found in sysrepo/values.h */
663                 size_t current_num_of_values= 0;
664
665                 CREATE_NEW_VALUE(rc, v, current_num_of_values);
666
667                 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "running-simulated-devices");
668                 v[current_num_of_values - 1].type = SR_UINT32_T;
669                 v[current_num_of_values - 1].data.uint32_val = get_current_number_of_devices(device_list);
670
671                 CREATE_NEW_VALUE(rc, v, current_num_of_values);
672
673                 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "running-mounted-devices");
674                 v[current_num_of_values - 1].type = SR_UINT32_T;
675                 v[current_num_of_values - 1].data.uint32_val = get_current_number_of_mounted_devices(device_list);
676
677                 CREATE_NEW_VALUE(rc, v, current_num_of_values);
678
679                 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "base-netconf-port");
680                 v[current_num_of_values - 1].type = SR_UINT32_T;
681                 v[current_num_of_values - 1].data.uint32_val = get_netconf_port_base();
682
683                 CREATE_NEW_VALUE(rc, v, current_num_of_values);
684
685                 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "cpu-usage");
686                 v[current_num_of_values - 1].type = SR_DECIMAL64_T;
687                 v[current_num_of_values - 1].data.decimal64_val = cpu_usage;
688
689                 CREATE_NEW_VALUE(rc, v, current_num_of_values);
690
691                 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "mem-usage");
692                 v[current_num_of_values - 1].type = SR_UINT32_T;
693                 v[current_num_of_values - 1].data.uint32_val = (int)mem_usage;
694
695         CREATE_NEW_VALUE(rc, v, current_num_of_values);
696
697         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "ssh-connections");
698         v[current_num_of_values - 1].type = SR_UINT32_T;
699         v[current_num_of_values - 1].data.uint32_val = getSshConnectionsFromConfigJson();
700
701         CREATE_NEW_VALUE(rc, v, current_num_of_values);
702
703         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "tls-connections");
704         v[current_num_of_values - 1].type = SR_UINT32_T;
705         v[current_num_of_values - 1].data.uint32_val = getTlsConnectionsFromConfigJson();
706
707                 //return the values that we have just created
708                 *values = v;
709                 *values_cnt = current_num_of_values;
710          }
711      else if (sr_xpath_node_name_eq(xpath, "total-ves-notifications"))
712      {
713         sr_val_t *v;
714         /* convenient functions such as this can be found in sysrepo/values.h */
715         size_t current_num_of_values= 0;
716
717         CREATE_NEW_VALUE(rc, v, current_num_of_values);
718
719         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "normal");
720         v[current_num_of_values - 1].type = SR_UINT32_T;
721         v[current_num_of_values - 1].data.uint32_val = ves_counter.normal;
722
723         CREATE_NEW_VALUE(rc, v, current_num_of_values);
724
725         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "warning");
726         v[current_num_of_values - 1].type = SR_UINT32_T;
727         v[current_num_of_values - 1].data.uint32_val = ves_counter.warning;
728
729         CREATE_NEW_VALUE(rc, v, current_num_of_values);
730
731         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "minor");
732         v[current_num_of_values - 1].type = SR_UINT32_T;
733         v[current_num_of_values - 1].data.uint32_val = ves_counter.minor;
734
735         CREATE_NEW_VALUE(rc, v, current_num_of_values);
736
737         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "major");
738         v[current_num_of_values - 1].type = SR_UINT32_T;
739         v[current_num_of_values - 1].data.uint32_val = ves_counter.major;
740
741         CREATE_NEW_VALUE(rc, v, current_num_of_values);
742
743         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "critical");
744         v[current_num_of_values - 1].type = SR_UINT32_T;
745         v[current_num_of_values - 1].data.uint32_val = ves_counter.critical;
746
747         //return the values that we have just created
748         *values = v;
749         *values_cnt = current_num_of_values;
750      }
751      else if (sr_xpath_node_name_eq(xpath, "total-netconf-notifications"))
752      {
753         sr_val_t *v;
754         /* convenient functions such as this can be found in sysrepo/values.h */
755         size_t current_num_of_values= 0;
756
757         CREATE_NEW_VALUE(rc, v, current_num_of_values);
758
759         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "normal");
760         v[current_num_of_values - 1].type = SR_UINT32_T;
761         v[current_num_of_values - 1].data.uint32_val = netconf_counter.normal;
762
763         CREATE_NEW_VALUE(rc, v, current_num_of_values);
764
765         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "warning");
766         v[current_num_of_values - 1].type = SR_UINT32_T;
767         v[current_num_of_values - 1].data.uint32_val = netconf_counter.warning;
768
769         CREATE_NEW_VALUE(rc, v, current_num_of_values);
770
771         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "minor");
772         v[current_num_of_values - 1].type = SR_UINT32_T;
773         v[current_num_of_values - 1].data.uint32_val = netconf_counter.minor;
774
775         CREATE_NEW_VALUE(rc, v, current_num_of_values);
776
777         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "major");
778         v[current_num_of_values - 1].type = SR_UINT32_T;
779         v[current_num_of_values - 1].data.uint32_val = netconf_counter.major;
780
781         CREATE_NEW_VALUE(rc, v, current_num_of_values);
782
783         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "critical");
784         v[current_num_of_values - 1].type = SR_UINT32_T;
785         v[current_num_of_values - 1].data.uint32_val = netconf_counter.critical;
786
787         //return the values that we have just created
788         *values = v;
789         *values_cnt = current_num_of_values;
790      }
791
792     return SR_ERR_OK;
793 }
794
795 static int odl_add_key_pair_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
796       sr_val_t **output, size_t *output_cnt, void *private_ctx)
797 {
798     int rc = SR_ERR_OK;
799     controller_t controller_list[CONTROLLER_LIST_MAX_LEN];
800     int controller_list_size = 0;
801
802     controller_list[0] = controller_details;
803     controller_list_size++;
804
805     for (int i = 0; i < controller_list_size; ++i)
806     {
807         printf("%d iteration: Got back url=%s and credentials=%s\n", i, controller_list[i].url, controller_list[i].credentials);
808     }
809
810     rc = add_key_pair_to_odl(controller_list, controller_list_size);
811     if (rc != SR_ERR_OK)
812     {
813         printf("Failed to add key pair to ODL.\n");
814         return SR_ERR_OPERATION_FAILED;
815     }
816
817     return rc;
818 }
819
820 static int invoke_notification_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
821       sr_val_t **output, size_t *output_cnt, void *private_ctx)
822 {
823     int rc = SR_ERR_OK;
824
825     char *device_name = NULL, *module_name = NULL, *notification_object = NULL;
826     
827     /* print input values */
828     printf("\n\n ========== RECEIVED RPC REQUEST ==========\n\n");
829     printf(">>> RPC Input:\n\n");
830     
831     device_name = strdup(input[0].data.string_val);
832     module_name = strdup(input[1].data.string_val);
833     notification_object = strdup(input[2].data.string_val);
834
835     rc = sr_new_values(1, output);
836     if (SR_ERR_OK != rc) {
837         return rc;
838     }
839
840     /* set 'output/step-count' leaf */
841     rc = sr_val_set_xpath(&(*output)[0], "/network-topology-simulator:invoke-notification/status");
842     if (SR_ERR_OK != rc) {
843         return rc;
844     }
845
846     rc = invoke_device_notification(device_name, module_name, notification_object);
847     
848     if (rc != SR_ERR_OK)
849     {
850         sr_val_build_str_data(&(*output)[0], SR_ENUM_T, "%s", "ERROR");
851     }
852     else
853     {
854         sr_val_build_str_data(&(*output)[0], SR_ENUM_T, "%s", "SUCCESS");
855     }
856     *output_cnt = 1;
857
858     return SR_ERR_OK;
859 }
860
861
862 static void
863 sigint_handler(int signum)
864 {
865     exit_application = 1;
866 }
867
868 int
869 main(int argc, char **argv)
870 {
871     sr_conn_ctx_t *connection = NULL;
872     sr_session_ctx_t *session = NULL;
873     sr_subscription_ctx_t *subscription = NULL;
874     int rc = SR_ERR_OK;
875
876     setbuf(stdout, NULL);
877
878     rc = _init_curl_k8s();
879     if (rc != SR_ERR_OK)
880     {
881         fprintf(stderr, "Could not initialize cURL for K8S connection: %s\n", sr_strerror(rc));
882     }
883
884     device_list = new_device_stack();
885     rc = _init_curl();
886     if (rc != SR_ERR_OK)
887     {
888         fprintf(stderr, "Could not initialize cURL: %s\n", sr_strerror(rc));
889     }
890
891     rc = writeSkeletonConfigFile();
892     if (rc != SR_ERR_OK)
893     {
894         fprintf(stderr, "Could not initialize configuration JSON file: %s\n", sr_strerror(rc));
895     }
896
897     /* connect to sysrepo */
898     rc = sr_connect("network-topology-simulator", SR_CONN_DEFAULT, &connection);
899     if (SR_ERR_OK != rc) {
900         fprintf(stderr, "Error by sr_connect: %s\n", sr_strerror(rc));
901         goto cleanup;
902     }
903
904     /* start session */
905     rc = sr_session_start(connection, SR_DS_STARTUP, SR_SESS_DEFAULT, &session);
906     if (SR_ERR_OK != rc) {
907         fprintf(stderr, "Error by sr_session_start: %s\n", sr_strerror(rc));
908         goto cleanup;
909     }
910
911     // setting the values that come in an ENV variable as defaults - ves-heartbeat-period
912     int vesHeartbeatPeriod = getIntFromString(getenv("VesHeartbeatPeriod"), 0);
913
914     sr_val_t value = { 0 };
915     value.type = SR_UINT32_T;
916     value.data.uint32_val = vesHeartbeatPeriod;
917     rc = sr_set_item(session, "/network-topology-simulator:simulator-config/notification-config/ves-heartbeat-period", 
918             &value, SR_EDIT_DEFAULT);
919     if (SR_ERR_OK != rc) {
920         printf("Error by sr_set_item: %s\n", sr_strerror(rc));
921         goto cleanup;
922     }
923
924     rc = ves_heartbeat_period_changed(vesHeartbeatPeriod);
925     if (SR_ERR_OK != rc) {
926         printf("Error by ves_heartbeat_period_changed: %s\n", sr_strerror(rc));
927         goto cleanup;
928     }
929
930     // setting the values that come in an ENV variable as defaults - is-netconf-available
931
932     int isNetconfAvailable = 1;
933
934     char *isNetconfAvailablString = getenv("IsNetconfAvailable");
935     if (isNetconfAvailablString != NULL)
936     {
937         if (strcmp(isNetconfAvailablString, "false") == 0)
938         {
939             isNetconfAvailable = 0;
940         }
941     }
942
943     value = (const sr_val_t) { 0 };
944     value.type = SR_BOOL_T;
945     value.data.bool_val = isNetconfAvailable;
946     rc = sr_set_item(session, "/network-topology-simulator:simulator-config/notification-config/is-netconf-available", 
947             &value, SR_EDIT_DEFAULT);
948     if (SR_ERR_OK != rc) {
949         printf("Error by sr_set_item: %s\n", sr_strerror(rc));
950         goto cleanup;
951     }
952
953     rc = is_netconf_available_changed(isNetconfAvailable);
954     if (SR_ERR_OK != rc) {
955         printf("Error by is_netconf_available_changed: %s\n", sr_strerror(rc));
956         goto cleanup;
957     }
958
959     // setting the values that come in an ENV variable as defaults - is-ves-available
960
961     int isVesAvailable = 1;
962
963     char *isVesAvailablString = getenv("IsVesAvailable");
964     if (isVesAvailablString != NULL)
965     {
966         if (strcmp(isVesAvailablString, "false") == 0)
967         {
968             isVesAvailable = 0;
969         }
970     }
971
972     value = (const sr_val_t) { 0 };
973     value.type = SR_BOOL_T;
974     value.data.bool_val = isVesAvailable;
975     rc = sr_set_item(session, "/network-topology-simulator:simulator-config/notification-config/is-ves-available", 
976             &value, SR_EDIT_DEFAULT);
977     if (SR_ERR_OK != rc) {
978         printf("Error by sr_set_item: %s\n", sr_strerror(rc));
979         goto cleanup;
980     }
981
982     rc = is_ves_available_changed(isVesAvailable);
983     if (SR_ERR_OK != rc) {
984         printf("Error by is_ves_available_changed: %s\n", sr_strerror(rc));
985         goto cleanup;
986     }
987
988     // setting the values that come in an ENV variable as defaults - ves-endpoint-port
989
990     int vesEndpointPort = getIntFromString(getenv("VesEndpointPort"), 8080);
991
992     value = (const sr_val_t) { 0 };
993     value.type = SR_UINT16_T;
994     value.data.uint16_val = vesEndpointPort;
995     rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-port", 
996             &value, SR_EDIT_DEFAULT);
997     if (SR_ERR_OK != rc) {
998         printf("Error by sr_set_item: %s\n", sr_strerror(rc));
999         goto cleanup;
1000     }
1001
1002     rc = ves_port_changed(vesEndpointPort);
1003     if (SR_ERR_OK != rc) {
1004         printf("Error by ves_port_changed: %s\n", sr_strerror(rc));
1005         goto cleanup;
1006     }
1007
1008     // setting the values that come in an ENV variable as defaults - ves-endpoint-ip
1009
1010     value = (const sr_val_t) { 0 };
1011     value.type = SR_STRING_T;
1012     value.data.string_val = getenv("VesEndpointIp");
1013     rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-ip", 
1014             &value, SR_EDIT_DEFAULT);
1015     if (SR_ERR_OK != rc) {
1016         printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1017         goto cleanup;
1018     }
1019
1020     rc = ves_ip_changed(getenv("VesEndpointIp"));
1021     if (SR_ERR_OK != rc) {
1022         printf("Error by ves_ip_changed: %s\n", sr_strerror(rc));
1023         goto cleanup;
1024     }
1025
1026     // setting the values that come in an ENV variable as defaults - ves-endpoint-auth-method
1027
1028     value = (const sr_val_t) { 0 };
1029     value.type = SR_ENUM_T;
1030     value.data.enum_val = getenv("VesEndpointAuthMethod");
1031     rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-auth-method", 
1032             &value, SR_EDIT_DEFAULT);
1033     if (SR_ERR_OK != rc) {
1034         printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1035         goto cleanup;
1036     }
1037
1038     rc = ves_auth_method_changed(getenv("VesEndpointAuthMethod"));
1039     if (SR_ERR_OK != rc) {
1040         printf("Error by ves_auth_method_changed: %s\n", sr_strerror(rc));
1041         goto cleanup;
1042     }
1043
1044     //TODO only basic-auth implemented vor VES
1045     if (strcmp(getenv("VesEndpointAuthMethod"), "basic-auth")  == 0)
1046     {
1047         // setting the values that come in an ENV variable as defaults - ves-endpoint-usename
1048
1049         value = (const sr_val_t) { 0 };
1050         value.type = SR_STRING_T;
1051         value.data.string_val = getenv("VesEndpointUsername");
1052         rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-username",
1053                 &value, SR_EDIT_DEFAULT);
1054         if (SR_ERR_OK != rc) {
1055             printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1056             goto cleanup;
1057         }
1058
1059         rc = ves_username_changed(getenv("VesEndpointUsername"));
1060         if (SR_ERR_OK != rc) {
1061             printf("Error by ves_username_changed: %s\n", sr_strerror(rc));
1062             goto cleanup;
1063         }
1064
1065         // setting the values that come in an ENV variable as defaults - ves-endpoint-password
1066
1067         value = (const sr_val_t) { 0 };
1068         value.type = SR_STRING_T;
1069         value.data.string_val = getenv("VesEndpointPassword");
1070         rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-password",
1071                 &value, SR_EDIT_DEFAULT);
1072         if (SR_ERR_OK != rc) {
1073             printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1074             goto cleanup;
1075         }
1076
1077         rc = ves_password_changed(getenv("VesEndpointPassword"));
1078         if (SR_ERR_OK != rc) {
1079             printf("Error by ves_password_changed: %s\n", sr_strerror(rc));
1080             goto cleanup;
1081         }
1082     }
1083
1084     // setting the values that come in an ENV variable as defaults - ves-registration
1085
1086     int vesRegistration = 1;
1087
1088     char *vesRegistrationString = getenv("VesRegistration");
1089     if (vesRegistrationString != NULL)
1090     {
1091         if (strcmp(vesRegistrationString, "false") == 0)
1092         {
1093             vesRegistration = 0;
1094         }
1095     }
1096
1097     value = (const sr_val_t) { 0 };
1098     value.type = SR_BOOL_T;
1099     value.data.bool_val = vesRegistration;
1100     rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-registration",
1101             &value, SR_EDIT_DEFAULT);
1102     if (SR_ERR_OK != rc) {
1103         printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1104         goto cleanup;
1105     }
1106
1107     rc = ves_registration_changed(vesRegistration);
1108     if (SR_ERR_OK != rc) {
1109         printf("Error by ves_registration_changed: %s\n", sr_strerror(rc));
1110         goto cleanup;
1111     }
1112
1113     // setting the values that come in an ENV variable as defaults - ssh-connections
1114
1115     int sshConnections = getIntFromString(getenv("SshConnections"), 1);
1116
1117     rc = ssh_connections_changed(sshConnections);
1118     if (SR_ERR_OK != rc) {
1119         printf("Error by ssh_connections_changed: %s\n", sr_strerror(rc));
1120         goto cleanup;
1121     }
1122
1123     // setting the values that come in an ENV variable as defaults - tls-connections
1124
1125     int tlsConnections = getIntFromString(getenv("TlsConnections"), 0);
1126
1127     rc = tls_connections_changed(tlsConnections);
1128     if (SR_ERR_OK != rc) {
1129         printf("Error by tls_connections_changed: %s\n", sr_strerror(rc));
1130         goto cleanup;
1131     }
1132
1133     if (strcmp(getenv("K8S_DEPLOYMENT"), "true") == 0)
1134     {
1135         rc = send_k8s_extend_port();
1136         if (rc != SR_ERR_OK)
1137         {
1138             printf("Could not send the number of ports to k8s cluster\n");
1139         }
1140     }
1141
1142     // setting the values that come in an ENV variable as defaults - controller-ip
1143
1144     value = (const sr_val_t) { 0 };
1145     value.type = SR_STRING_T;
1146     value.data.string_val = getenv("ControllerIp");
1147     rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-ip", 
1148             &value, SR_EDIT_DEFAULT);
1149     if (SR_ERR_OK != rc) {
1150         printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1151         goto cleanup;
1152     }
1153
1154     rc = controller_ip_changed(getenv("ControllerIp"));
1155     if (SR_ERR_OK != rc) {
1156         printf("Error by controller_ip_changed: %s\n", sr_strerror(rc));
1157         goto cleanup;
1158     }
1159
1160     // setting the values that come in an ENV variable as defaults - controller-port
1161
1162     int controllerPort = getIntFromString(getenv("ControllerPort"), 8181);
1163
1164     value = (const sr_val_t) { 0 };
1165     value.type = SR_UINT16_T;
1166     value.data.uint16_val = controllerPort;
1167     rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-port", 
1168             &value, SR_EDIT_DEFAULT);
1169     if (SR_ERR_OK != rc) {
1170         printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1171         goto cleanup;
1172     }
1173
1174     rc = controller_port_changed(controllerPort);
1175     if (SR_ERR_OK != rc) {
1176         printf("Error by controller_port_changed: %s\n", sr_strerror(rc));
1177         goto cleanup;
1178     }
1179
1180     // setting the values that come in an ENV variable as defaults - netconf-call-home-port
1181
1182     int netconfCallHomePort = getIntFromString(getenv("NetconfCallHomePort"), 6666);
1183
1184     value = (const sr_val_t) { 0 };
1185     value.type = SR_UINT16_T;
1186     value.data.uint16_val = netconfCallHomePort;
1187     rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/netconf-call-home-port", 
1188             &value, SR_EDIT_DEFAULT);
1189     if (SR_ERR_OK != rc) {
1190         printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1191         goto cleanup;
1192     }
1193
1194     rc = controller_netconf_call_home_port_changed(netconfCallHomePort);
1195     if (SR_ERR_OK != rc) {
1196         printf("Error by controller_netconf_call_home_port_changed: %s\n", sr_strerror(rc));
1197         goto cleanup;
1198     }
1199
1200     // setting the values that come in an ENV variable as defaults - controller-username
1201
1202     value = (const sr_val_t) { 0 };
1203     value.type = SR_STRING_T;
1204     value.data.string_val = getenv("ControllerUsername");
1205     rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-username", 
1206             &value, SR_EDIT_DEFAULT);
1207     if (SR_ERR_OK != rc) {
1208         printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1209         goto cleanup;
1210     }
1211
1212     rc = controller_username_changed(getenv("ControllerUsername"));
1213     if (SR_ERR_OK != rc) {
1214         printf("Error by controller_username_changed: %s\n", sr_strerror(rc));
1215         goto cleanup;
1216     }
1217
1218     // setting the values that come in an ENV variable as defaults - controller-password
1219
1220     value = (const sr_val_t) { 0 };
1221     value.type = SR_STRING_T;
1222     value.data.string_val = getenv("ControllerPassword");
1223     rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-password", 
1224             &value, SR_EDIT_DEFAULT);
1225     if (SR_ERR_OK != rc) {
1226         printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1227         goto cleanup;
1228     }
1229
1230     rc = controller_password_changed(getenv("ControllerPassword"));
1231     if (SR_ERR_OK != rc) {
1232         printf("Error by controller_password_changed: %s\n", sr_strerror(rc));
1233         goto cleanup;
1234     }
1235
1236     // setting the values that come in an ENV variable as defaults - netconf-call-home
1237
1238     int netconfCallHome = 1;
1239
1240     char *netconfCallHomeString = getenv("NetconfCallHome");
1241     if (netconfCallHomeString != NULL)
1242     {
1243         if (strcmp(netconfCallHomeString, "false") == 0)
1244         {
1245             netconfCallHome = 0;
1246         }
1247     }
1248
1249     value = (const sr_val_t) { 0 };
1250     value.type = SR_BOOL_T;
1251     value.data.bool_val = netconfCallHome;
1252     rc = sr_set_item(session, "/network-topology-simulator:simulator-config/netconf-call-home", 
1253             &value, SR_EDIT_DEFAULT);
1254     if (SR_ERR_OK != rc) {
1255         printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1256         goto cleanup;
1257     }
1258
1259     rc = netconf_call_home_changed(netconfCallHome);
1260     if (SR_ERR_OK != rc) {
1261         printf("Error by netconf_call_home_changed: %s\n", sr_strerror(rc));
1262         goto cleanup;
1263     }
1264
1265     //commit the changes that we have done until now
1266     rc = sr_commit(session);
1267     if (SR_ERR_OK != rc) {
1268         printf("Error by sr_commit: %s\n", sr_strerror(rc));
1269         goto cleanup;
1270     }
1271
1272         /* read startup config */
1273         printf("\n\n ========== READING STARTUP CONFIG network-topology-simulator: ==========\n\n");
1274         print_current_config(session, "network-topology-simulator");
1275
1276         /* subscribe for changes in running config */
1277         rc = sr_module_change_subscribe(session, "network-topology-simulator", simulator_config_change_cb, NULL,
1278                         0, SR_SUBSCR_DEFAULT | SR_SUBSCR_APPLY_ONLY, &subscription);
1279         if (SR_ERR_OK != rc) {
1280                 fprintf(stderr, "Error by sr_module_change_subscribe: %s\n", sr_strerror(rc));
1281                 goto cleanup;
1282         }
1283
1284     /* subscribe as state data provider for the ntsimulator state data */
1285     rc = sr_dp_get_items_subscribe(session, "/network-topology-simulator:simulator-status", simulator_status_cb, NULL,
1286                 SR_SUBSCR_CTX_REUSE, &subscription);
1287     if (rc != SR_ERR_OK) {
1288         goto cleanup;
1289     }
1290
1291     rc = notification_delay_period_changed(NULL, 0);
1292     if (rc != SR_ERR_OK) {
1293         printf("Could not write the delay period to file!\n");
1294         goto cleanup;
1295     }
1296
1297     rc = _init_curl_odl();
1298     if (rc != SR_ERR_OK)
1299     {
1300         fprintf(stderr, "Could not initialize cURL for ODL connection: %s\n", sr_strerror(rc));
1301     }
1302
1303     rc = sr_rpc_subscribe(session, "/network-topology-simulator:add-key-pair-to-odl", odl_add_key_pair_cb, (void *)session,
1304                 SR_SUBSCR_CTX_REUSE, &subscription);
1305
1306         printf("\n\n ========== STARTUP CONFIG network-topology-simulator APPLIED AS RUNNING ==========\n\n");
1307
1308     rc = writeSkeletonStatusFile();
1309     if (rc != SR_ERR_OK)
1310     {
1311         fprintf(stderr, "Could not initialize status JSON file: %s\n", sr_strerror(rc));
1312     }
1313
1314     rc = sr_rpc_subscribe(session, "/network-topology-simulator:invoke-notification", invoke_notification_cb,
1315             (void *)session, SR_SUBSCR_DEFAULT, &subscription);
1316     if (SR_ERR_OK != rc) {
1317         fprintf(stderr, "Error by sr_rpc_subscribe: %s\n", sr_strerror(rc));
1318         goto cleanup;
1319     }
1320
1321     rc = pull_docker_image_of_simulated_device();
1322
1323     /* loop until ctrl-c is pressed / SIGINT is received */
1324     signal(SIGINT, sigint_handler);
1325     signal(SIGTERM, sigint_handler);
1326     signal(SIGPIPE, SIG_IGN);
1327
1328     while (!exit_application) {
1329
1330                 sleep(1);  /* or do some more useful work... */
1331     }
1332
1333     printf("Application exit requested, exiting.\n");
1334
1335 cleanup:
1336     if (NULL != subscription) {
1337         sr_unsubscribe(session, subscription);
1338     }
1339     if (NULL != session) {
1340         sr_session_stop(session);
1341     }
1342     if (NULL != connection) {
1343         sr_disconnect(connection);
1344     }
1345
1346     clean_current_docker_configuration();
1347     rc = cleanup_curl();
1348     rc = cleanup_curl_odl();
1349     rc = cleanup_curl_k8s();
1350
1351     return rc;
1352 }
1353
1354 static void clean_current_docker_configuration(void)
1355 {
1356     if (strcmp(getenv("K8S_DEPLOYMENT"), "true"))
1357     {
1358         return;
1359     }
1360
1361         printf("Cleaning docker containers...\n");
1362
1363         if (device_list == NULL)
1364         {
1365                 return;
1366         }
1367
1368         for (int i = 0; i < simulated_devices_config; ++i)
1369         {
1370                 stop_device(device_list);
1371         }
1372
1373         printf("Cleaning completed!\n");
1374 }