1 /*************************************************************************
3 * Copyright 2019 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 ***************************************************************************/
28 #include "sysrepo/values.h"
31 #include "simulator-operations.h"
33 volatile int exit_application = 0;
35 volatile unsigned int simulated_devices_config = 0;
36 volatile unsigned int mounted_devices_config = 0;
39 static device_stack_t *device_list = NULL;
41 controller_t controller_details;
43 #define XPATH_MAX_LEN 500
44 #define CONTROLLER_LIST_MAX_LEN 1
47 print_current_config(sr_session_ctx_t *session, const char *module_name)
49 sr_val_t *values = NULL;
52 char xpath[XPATH_MAX_LEN] = {0};
53 snprintf(xpath, XPATH_MAX_LEN, "/%s:*//.", module_name);
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;
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));
65 for (size_t i = 0; i < count; i++){
67 sr_print_val(&values[i]);
69 if (sr_xpath_node_name_eq(values[i].xpath, "controller-ip"))
71 rc = sr_dup_val(&values[i], &odl_ip);
73 else if (sr_xpath_node_name_eq(values[i].xpath, "controller-port"))
75 rc = sr_dup_val(&values[i], &odl_port);
77 else if (sr_xpath_node_name_eq(values[i].xpath, "controller-username"))
79 rc = sr_dup_val(&values[i], &odl_username);
81 else if (sr_xpath_node_name_eq(values[i].xpath, "controller-password"))
83 rc = sr_dup_val(&values[i], &odl_password);
87 //URL used for mounting/unmounting a device; the device name needs to be appended
88 char url[URL_AND_CREDENTIALS_MAX_LEN];
89 sprintf(url, "http://%s:%d/restconf/config/network-topology:network-topology/topology/"
90 "topology-netconf/node/",
91 odl_ip->data.string_val, odl_port->data.uint32_val);
93 char credentials[URL_AND_CREDENTIALS_MAX_LEN];
94 sprintf(credentials, "%s:%s", odl_username->data.string_val, odl_password->data.string_val);
96 //URLs used for adding key pair to ODL, for TLS connections
97 char url_for_keystore_add[URL_AND_CREDENTIALS_MAX_LEN];
98 sprintf(url_for_keystore_add, "http://%s:%d/restconf/operations/netconf-keystore:add-keystore-entry",
99 odl_ip->data.string_val, odl_port->data.uint32_val);
101 char url_for_private_key_add[URL_AND_CREDENTIALS_MAX_LEN];
102 sprintf(url_for_private_key_add, "http://%s:%d/restconf/operations/netconf-keystore:add-private-key",
103 odl_ip->data.string_val, odl_port->data.uint32_val);
105 char url_for_trusted_ca_add[URL_AND_CREDENTIALS_MAX_LEN];
106 sprintf(url_for_trusted_ca_add, "http://%s:%d/restconf/operations/netconf-keystore:add-trusted-certificate",
107 odl_ip->data.string_val, odl_port->data.uint32_val);
109 strcpy(controller_details.url, url);
110 strcpy(controller_details.credentials, credentials);
111 strcpy(controller_details.url_for_keystore_add, url_for_keystore_add);
112 strcpy(controller_details.url_for_private_key_add, url_for_private_key_add);
113 strcpy(controller_details.url_for_trusted_ca_add, url_for_trusted_ca_add);
116 sr_free_val(odl_port);
117 sr_free_val(odl_username);
118 sr_free_val(odl_password);
120 sr_free_values(values, count);
123 static void clean_current_docker_configuration(void);
125 static int simulated_devices_changed(int new_value)
129 if (simulated_devices_config > new_value)
131 //we are configuring less elements that currently
132 for (int i = 0; i < simulated_devices_config - new_value; ++i)
134 rc = stop_device(device_list);
137 else if (simulated_devices_config < new_value)
139 //we are configuring more elements that currently
140 for (int i = 0; i < new_value - simulated_devices_config; ++i)
142 rc = start_device(device_list);
146 simulated_devices_config = new_value;
151 int mounted_devices_changed(sr_session_ctx_t *session, int new_value)
155 if (mounted_devices_config > new_value)
157 //we need have less mounted elements
158 for (int i = 0; i < mounted_devices_config - new_value; ++i)
160 printf("Sending unmount device...\n");
161 rc = unmount_device(device_list, controller_details);
164 else if (mounted_devices_config < new_value)
166 //we are configuring more elements that currently
167 for (int i = 0; i < new_value - mounted_devices_config; ++i)
169 printf("Sending mount device...\n");
170 rc = mount_device(device_list, controller_details);
174 mounted_devices_config = new_value;
180 simulator_config_change_cb(sr_session_ctx_t *session, const char *module_name, sr_notif_event_t event, void *private_ctx)
184 printf("\n\n ========== CONFIG HAS CHANGED, CURRENT RUNNING CONFIG %s: ==========\n\n", module_name);
185 print_current_config(session, module_name);
187 sr_val_t *val = NULL;
189 /* get the value from sysrepo, we do not care if the value did not change in our case */
190 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/simulated-devices", &val);
191 if (rc != SR_ERR_OK) {
195 rc = simulated_devices_changed(val->data.uint32_val);
196 if (rc != SR_ERR_OK) {
203 /* get the value from sysrepo, we do not care if the value did not change in our case */
204 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/mounted-devices", &val);
205 if (rc != SR_ERR_OK) {
209 if (mounted_devices_config != val->data.uint32_val)
211 if (val->data.uint32_val > simulated_devices_config)
213 printf("Cannot set mount value greater than number of simulated devices.\n");
219 rc = mounted_devices_changed(session, val->data.uint32_val);
220 if (rc != SR_ERR_OK) {
230 /* get the value from sysrepo, we do not care if the value did not change in our case */
231 rc = sr_get_items(session, "/network-topology-simulator:simulator-config/notification-config/fault-notification-delay-period", &val, &count);
232 if (rc != SR_ERR_OK) {
236 rc = notification_delay_period_changed(val, count);
237 if (rc != SR_ERR_OK) {
240 sr_free_values(val, count);
243 /* get the value from sysrepo, we do not care if the value did not change in our case */
244 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/ves-heartbeat-period", &val);
245 if (rc != SR_ERR_OK) {
249 rc = ves_heartbeat_period_changed(val->data.uint32_val);
250 if (rc != SR_ERR_OK) {
257 /* get the value from sysrepo, we do not care if the value did not change in our case */
258 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-ip", &val);
259 if (rc != SR_ERR_OK) {
263 rc = ves_ip_changed(val->data.string_val);
264 if (rc != SR_ERR_OK) {
271 /* get the value from sysrepo, we do not care if the value did not change in our case */
272 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-port", &val);
273 if (rc != SR_ERR_OK) {
277 rc = ves_port_changed(val->data.uint16_val);
278 if (rc != SR_ERR_OK) {
285 /* get the value from sysrepo, we do not care if the value did not change in our case */
286 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-registration", &val);
287 if (rc != SR_ERR_OK) {
291 rc = ves_registration_changed(val->data.bool_val);
292 if (rc != SR_ERR_OK) {
299 /* get the value from sysrepo, we do not care if the value did not change in our case */
300 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/is-netconf-available", &val);
301 if (rc != SR_ERR_OK) {
305 rc = is_netconf_available_changed(val->data.bool_val);
306 if (rc != SR_ERR_OK) {
313 /* get the value from sysrepo, we do not care if the value did not change in our case */
314 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/is-ves-available", &val);
315 if (rc != SR_ERR_OK) {
319 rc = is_ves_available_changed(val->data.bool_val);
320 if (rc != SR_ERR_OK) {
330 printf("NTSimulator config change callback failed: %s.", sr_strerror(rc));
340 simulator_status_cb(const char *xpath, sr_val_t **values, size_t *values_cnt,
341 uint64_t request_id, const char *original_xpath, void *private_ctx)
345 // printf("\n\n ========== Called simulator_status_cb for xpath: %s ==========\n\n", xpath);
347 counterAlarms ves_counter, netconf_counter;
348 rc = compute_notifications_count(&ves_counter, &netconf_counter);
351 printf("Could not compute the total number of notification count.\n");
354 if (sr_xpath_node_name_eq(xpath, "simulated-devices-list")) {
356 size_t current_num_of_values= 0;
358 if (simulated_devices_config == 0) //nothing to return if no devices are running
366 rc = get_docker_containers_operational_state_curl(device_list);
369 printf("Could not get the operational state for the devices simulated.\n");
370 return SR_ERR_OPERATION_FAILED;
373 device_t *current_device = device_list->head;
375 while (current_device != NULL)
377 counterAlarms vesCount, netconfCount;
378 rc = getDeviceCounters(current_device->device_id, &vesCount, &netconfCount);
381 printf("Could not get Notification Counters for device with uuid=\"%s\"", current_device->device_id);
384 CREATE_NEW_VALUE(rc, v, current_num_of_values);
386 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "device-ip");
387 v[current_num_of_values - 1].type = SR_STRING_T;
388 v[current_num_of_values - 1].data.string_val = getenv("NTS_IP");
390 for (int i = 0; i < NETCONF_CONNECTIONS_PER_DEVICE; ++i)
392 CREATE_NEW_VALUE(rc, v, current_num_of_values);
394 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "device-port");
395 v[current_num_of_values - 1].type = SR_UINT32_T;
396 v[current_num_of_values - 1].data.uint32_val = current_device->netconf_port + i;
399 CREATE_NEW_VALUE(rc, v, current_num_of_values);
401 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "is-mounted");
402 v[current_num_of_values - 1].type = SR_BOOL_T;
403 v[current_num_of_values - 1].data.bool_val = current_device->is_mounted;
405 char *operational_state = get_docker_container_operational_state(device_list, current_device->device_id);
407 CREATE_NEW_VALUE(rc, v, current_num_of_values);
409 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "operational-state");
410 sr_val_build_str_data(&v[current_num_of_values - 1], SR_ENUM_T, "%s", operational_state);
412 CREATE_NEW_VALUE(rc, v, current_num_of_values);
414 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "normal");
415 v[current_num_of_values - 1].type = SR_UINT32_T;
416 v[current_num_of_values - 1].data.uint32_val = vesCount.normal;
418 CREATE_NEW_VALUE(rc, v, current_num_of_values);
420 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "warning");
421 v[current_num_of_values - 1].type = SR_UINT32_T;
422 v[current_num_of_values - 1].data.uint32_val = vesCount.warning;
424 CREATE_NEW_VALUE(rc, v, current_num_of_values);
426 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "minor");
427 v[current_num_of_values - 1].type = SR_UINT32_T;
428 v[current_num_of_values - 1].data.uint32_val = vesCount.minor;
430 CREATE_NEW_VALUE(rc, v, current_num_of_values);
432 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "major");
433 v[current_num_of_values - 1].type = SR_UINT32_T;
434 v[current_num_of_values - 1].data.uint32_val = vesCount.major;
436 CREATE_NEW_VALUE(rc, v, current_num_of_values);
438 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "critical");
439 v[current_num_of_values - 1].type = SR_UINT32_T;
440 v[current_num_of_values - 1].data.uint32_val = vesCount.critical;
442 CREATE_NEW_VALUE(rc, v, current_num_of_values);
444 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "normal");
445 v[current_num_of_values - 1].type = SR_UINT32_T;
446 v[current_num_of_values - 1].data.uint32_val = netconfCount.normal;
448 CREATE_NEW_VALUE(rc, v, current_num_of_values);
450 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "warning");
451 v[current_num_of_values - 1].type = SR_UINT32_T;
452 v[current_num_of_values - 1].data.uint32_val = netconfCount.warning;
454 CREATE_NEW_VALUE(rc, v, current_num_of_values);
456 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "minor");
457 v[current_num_of_values - 1].type = SR_UINT32_T;
458 v[current_num_of_values - 1].data.uint32_val = netconfCount.minor;
460 CREATE_NEW_VALUE(rc, v, current_num_of_values);
462 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "major");
463 v[current_num_of_values - 1].type = SR_UINT32_T;
464 v[current_num_of_values - 1].data.uint32_val = netconfCount.major;
466 CREATE_NEW_VALUE(rc, v, current_num_of_values);
468 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "critical");
469 v[current_num_of_values - 1].type = SR_UINT32_T;
470 v[current_num_of_values - 1].data.uint32_val = netconfCount.critical;
472 current_device = current_device->next;
475 //return the values that we have just created
477 *values_cnt = current_num_of_values;
479 else if (sr_xpath_node_name_eq(xpath, "simulation-usage-details"))
481 float cpu_usage = 0.0, mem_usage = 0.0;
483 char *resource_usage_from_script = get_docker_container_resource_stats();
485 if (resource_usage_from_script != NULL)
487 printf("Received line: %s\n", resource_usage_from_script);
488 sscanf(resource_usage_from_script, "CPU=%f%%;RAM=%fMiB", &cpu_usage, &mem_usage);
489 printf("Read cpu=\"%f\" and mem=\"%f\"\n", cpu_usage, mem_usage);
490 free(resource_usage_from_script);
494 /* convenient functions such as this can be found in sysrepo/values.h */
495 size_t current_num_of_values= 0;
497 CREATE_NEW_VALUE(rc, v, current_num_of_values);
499 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "running-simulated-devices");
500 v[current_num_of_values - 1].type = SR_UINT32_T;
501 v[current_num_of_values - 1].data.uint32_val = get_current_number_of_devices(device_list);
503 CREATE_NEW_VALUE(rc, v, current_num_of_values);
505 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "running-mounted-devices");
506 v[current_num_of_values - 1].type = SR_UINT32_T;
507 v[current_num_of_values - 1].data.uint32_val = get_current_number_of_mounted_devices(device_list);
509 CREATE_NEW_VALUE(rc, v, current_num_of_values);
511 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "base-netconf-port");
512 v[current_num_of_values - 1].type = SR_UINT32_T;
513 v[current_num_of_values - 1].data.uint32_val = get_netconf_port_base();
515 CREATE_NEW_VALUE(rc, v, current_num_of_values);
517 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "cpu-usage");
518 v[current_num_of_values - 1].type = SR_DECIMAL64_T;
519 v[current_num_of_values - 1].data.decimal64_val = cpu_usage;
521 CREATE_NEW_VALUE(rc, v, current_num_of_values);
523 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "mem-usage");
524 v[current_num_of_values - 1].type = SR_UINT32_T;
525 v[current_num_of_values - 1].data.uint32_val = (int)mem_usage;
527 //return the values that we have just created
529 *values_cnt = current_num_of_values;
531 else if (sr_xpath_node_name_eq(xpath, "total-ves-notifications"))
534 /* convenient functions such as this can be found in sysrepo/values.h */
535 size_t current_num_of_values= 0;
537 CREATE_NEW_VALUE(rc, v, current_num_of_values);
539 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "normal");
540 v[current_num_of_values - 1].type = SR_UINT32_T;
541 v[current_num_of_values - 1].data.uint32_val = ves_counter.normal;
543 CREATE_NEW_VALUE(rc, v, current_num_of_values);
545 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "warning");
546 v[current_num_of_values - 1].type = SR_UINT32_T;
547 v[current_num_of_values - 1].data.uint32_val = ves_counter.warning;
549 CREATE_NEW_VALUE(rc, v, current_num_of_values);
551 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "minor");
552 v[current_num_of_values - 1].type = SR_UINT32_T;
553 v[current_num_of_values - 1].data.uint32_val = ves_counter.minor;
555 CREATE_NEW_VALUE(rc, v, current_num_of_values);
557 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "major");
558 v[current_num_of_values - 1].type = SR_UINT32_T;
559 v[current_num_of_values - 1].data.uint32_val = ves_counter.major;
561 CREATE_NEW_VALUE(rc, v, current_num_of_values);
563 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "critical");
564 v[current_num_of_values - 1].type = SR_UINT32_T;
565 v[current_num_of_values - 1].data.uint32_val = ves_counter.critical;
567 //return the values that we have just created
569 *values_cnt = current_num_of_values;
571 else if (sr_xpath_node_name_eq(xpath, "total-netconf-notifications"))
574 /* convenient functions such as this can be found in sysrepo/values.h */
575 size_t current_num_of_values= 0;
577 CREATE_NEW_VALUE(rc, v, current_num_of_values);
579 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "normal");
580 v[current_num_of_values - 1].type = SR_UINT32_T;
581 v[current_num_of_values - 1].data.uint32_val = netconf_counter.normal;
583 CREATE_NEW_VALUE(rc, v, current_num_of_values);
585 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "warning");
586 v[current_num_of_values - 1].type = SR_UINT32_T;
587 v[current_num_of_values - 1].data.uint32_val = netconf_counter.warning;
589 CREATE_NEW_VALUE(rc, v, current_num_of_values);
591 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "minor");
592 v[current_num_of_values - 1].type = SR_UINT32_T;
593 v[current_num_of_values - 1].data.uint32_val = netconf_counter.minor;
595 CREATE_NEW_VALUE(rc, v, current_num_of_values);
597 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "major");
598 v[current_num_of_values - 1].type = SR_UINT32_T;
599 v[current_num_of_values - 1].data.uint32_val = netconf_counter.major;
601 CREATE_NEW_VALUE(rc, v, current_num_of_values);
603 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "critical");
604 v[current_num_of_values - 1].type = SR_UINT32_T;
605 v[current_num_of_values - 1].data.uint32_val = netconf_counter.critical;
607 //return the values that we have just created
609 *values_cnt = current_num_of_values;
615 int odl_add_key_pair_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
616 sr_val_t **output, size_t *output_cnt, void *private_ctx)
619 controller_t controller_list[CONTROLLER_LIST_MAX_LEN];
620 int controller_list_size = 0;
622 controller_list[0] = controller_details;
623 controller_list_size++;
625 for (int i = 0; i < controller_list_size; ++i)
627 printf("%d iteration: Got back url=%s and credentials=%s\n", i, controller_list[i].url, controller_list[i].credentials);
630 rc = add_key_pair_to_odl(controller_list, controller_list_size);
633 printf("Failed to add key pair to ODL.\n");
634 return SR_ERR_OPERATION_FAILED;
642 sigint_handler(int signum)
644 exit_application = 1;
648 main(int argc, char **argv)
650 sr_conn_ctx_t *connection = NULL;
651 sr_session_ctx_t *session = NULL;
652 sr_subscription_ctx_t *subscription = NULL;
655 setbuf(stdout, NULL);
657 device_list = new_device_stack();
661 fprintf(stderr, "Could not initialize cURL: %s\n", sr_strerror(rc));
664 /* connect to sysrepo */
665 rc = sr_connect("network-topology-simulator", SR_CONN_DEFAULT, &connection);
666 if (SR_ERR_OK != rc) {
667 fprintf(stderr, "Error by sr_connect: %s\n", sr_strerror(rc));
672 rc = sr_session_start(connection, SR_DS_STARTUP, SR_SESS_DEFAULT, &session);
673 if (SR_ERR_OK != rc) {
674 fprintf(stderr, "Error by sr_session_start: %s\n", sr_strerror(rc));
678 /* read startup config */
679 printf("\n\n ========== READING STARTUP CONFIG network-topology-simulator: ==========\n\n");
680 print_current_config(session, "network-topology-simulator");
682 /* subscribe for changes in running config */
683 rc = sr_module_change_subscribe(session, "network-topology-simulator", simulator_config_change_cb, NULL,
684 0, SR_SUBSCR_DEFAULT | SR_SUBSCR_APPLY_ONLY, &subscription);
685 if (SR_ERR_OK != rc) {
686 fprintf(stderr, "Error by sr_module_change_subscribe: %s\n", sr_strerror(rc));
690 /* subscribe as state data provider for the ntsimulator state data */
691 rc = sr_dp_get_items_subscribe(session, "/network-topology-simulator:simulator-status", simulator_status_cb, NULL,
692 SR_SUBSCR_CTX_REUSE, &subscription);
693 if (rc != SR_ERR_OK) {
697 rc = notification_delay_period_changed(NULL, 0);
698 if (rc != SR_ERR_OK) {
699 printf("Could not write the delay period to file!\n");
703 rc = _init_curl_odl();
706 fprintf(stderr, "Could not initialize cURL for ODL connection: %s\n", sr_strerror(rc));
709 rc = sr_rpc_subscribe(session, "/network-topology-simulator:add-key-pair-to-odl", odl_add_key_pair_cb, (void *)session,
710 SR_SUBSCR_CTX_REUSE, &subscription);
712 printf("\n\n ========== STARTUP CONFIG network-topology-simulator APPLIED AS RUNNING ==========\n\n");
714 rc = writeSkeletonStatusFile();
717 fprintf(stderr, "Could not initialize status JSON file: %s\n", sr_strerror(rc));
720 /* loop until ctrl-c is pressed / SIGINT is received */
721 signal(SIGINT, sigint_handler);
722 signal(SIGTERM, sigint_handler);
723 signal(SIGPIPE, SIG_IGN);
725 while (!exit_application) {
727 sleep(1); /* or do some more useful work... */
730 printf("Application exit requested, exiting.\n");
733 if (NULL != subscription) {
734 sr_unsubscribe(session, subscription);
736 if (NULL != session) {
737 sr_session_stop(session);
739 if (NULL != connection) {
740 sr_disconnect(connection);
743 clean_current_docker_configuration();
745 rc = cleanup_curl_odl();
750 static void clean_current_docker_configuration(void)
752 printf("Cleaning docker containers...\n");
754 if (device_list == NULL)
759 for (int i = 0; i < simulated_devices_config; ++i)
761 stop_device(device_list);
764 printf("Cleaning completed!\n");