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 char *ipv6 = strchr(odl_ip->data.string_val, ':');
88 char odl_ip_string[URL_AND_CREDENTIALS_MAX_LEN];
91 sprintf(odl_ip_string, "[%s]", odl_ip->data.string_val);
95 sprintf(odl_ip_string, "%s", odl_ip->data.string_val);
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);
105 char credentials[URL_AND_CREDENTIALS_MAX_LEN];
106 sprintf(credentials, "%s:%s", odl_username->data.string_val, odl_password->data.string_val);
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);
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);
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);
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);
128 sr_free_val(odl_port);
129 sr_free_val(odl_username);
130 sr_free_val(odl_password);
132 sr_free_values(values, count);
135 static void clean_current_docker_configuration(void);
137 static int simulated_devices_changed(int new_value)
141 if (strcmp(getenv("K8S_DEPLOYMENT"), "true") == 0)
143 if (new_value != simulated_devices_config)
145 simulated_devices_config = new_value;
146 rc = send_k8s_scale(new_value);
149 printf("Could not send new_scale=%d to k8s cluster.\n", new_value);
155 if (simulated_devices_config > new_value)
157 //we are configuring less elements that currently
158 for (int i = 0; i < simulated_devices_config - new_value; ++i)
160 rc = stop_device(device_list);
163 else if (simulated_devices_config < new_value)
165 //we are configuring more elements that currently
166 for (int i = 0; i < new_value - simulated_devices_config; ++i)
168 rc = start_device(device_list);
171 printf("ERROR: Could not start simulated device. Ignoring, trying with the next simulated device, if any...\n");
176 simulated_devices_config = new_value;
181 int mounted_devices_changed(sr_session_ctx_t *session, int new_value)
185 if (mounted_devices_config > new_value)
187 //we need have less mounted elements
188 for (int i = 0; i < mounted_devices_config - new_value; ++i)
190 printf("Sending unmount device...\n");
191 rc = unmount_device(device_list, controller_details);
194 else if (mounted_devices_config < new_value)
196 //we are configuring more elements that currently
197 for (int i = 0; i < new_value - mounted_devices_config; ++i)
199 printf("Sending mount device...\n");
200 rc = mount_device(device_list, controller_details);
204 mounted_devices_config = new_value;
210 simulator_config_change_cb(sr_session_ctx_t *session, const char *module_name, sr_notif_event_t event, void *private_ctx)
214 printf("\n\n ========== CONFIG HAS CHANGED, CURRENT RUNNING CONFIG %s: ==========\n\n", module_name);
215 print_current_config(session, module_name);
217 sr_val_t *val = NULL;
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) {
225 rc = simulated_devices_changed(val->data.uint32_val);
226 if (rc != SR_ERR_OK) {
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) {
239 if (mounted_devices_config != val->data.uint32_val)
241 if (val->data.uint32_val > simulated_devices_config)
243 printf("Cannot set mount value greater than number of simulated devices.\n");
249 rc = mounted_devices_changed(session, val->data.uint32_val);
250 if (rc != SR_ERR_OK) {
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) {
266 rc = notification_delay_period_changed(val, count);
267 if (rc != SR_ERR_OK) {
270 sr_free_values(val, count);
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) {
279 rc = ves_heartbeat_period_changed(val->data.uint32_val);
280 if (rc != SR_ERR_OK) {
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) {
293 rc = ves_ip_changed(val->data.string_val);
294 if (rc != SR_ERR_OK) {
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-port", &val);
303 if (rc != SR_ERR_OK) {
307 rc = ves_port_changed(val->data.uint16_val);
308 if (rc != SR_ERR_OK) {
315 /* get the value from sysrepo, we do not care if the value did not change in our case */
316 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-registration", &val);
317 if (rc != SR_ERR_OK) {
321 rc = ves_registration_changed(val->data.bool_val);
322 if (rc != SR_ERR_OK) {
329 /* get the value from sysrepo, we do not care if the value did not change in our case */
330 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/is-netconf-available", &val);
331 if (rc != SR_ERR_OK) {
335 rc = is_netconf_available_changed(val->data.bool_val);
336 if (rc != SR_ERR_OK) {
343 /* get the value from sysrepo, we do not care if the value did not change in our case */
344 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/is-ves-available", &val);
345 if (rc != SR_ERR_OK) {
349 rc = is_ves_available_changed(val->data.bool_val);
350 if (rc != SR_ERR_OK) {
357 /* get the value from sysrepo, we do not care if the value did not change in our case */
358 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ssh-connections", &val);
359 if (rc != SR_ERR_OK) {
360 printf("NTS Manager /network-topology-simulator:simulator-config/ssh-connections object not available, ignoring..");
364 rc = ssh_connections_changed(val->data.uint32_val);
365 if (rc != SR_ERR_OK) {
369 if (strcmp(getenv("K8S_DEPLOYMENT"), "true") == 0)
371 rc = send_k8s_extend_port();
374 printf("Could not send the extended port to k8s cluster.\n");
382 /* get the value from sysrepo, we do not care if the value did not change in our case */
383 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/tls-connections", &val);
384 if (rc != SR_ERR_OK) {
385 printf("NTS Manager /network-topology-simulator:simulator-config/tls-connections object not available, ignoring..");
389 rc = tls_connections_changed(val->data.uint32_val);
390 if (rc != SR_ERR_OK) {
394 if (strcmp(getenv("K8S_DEPLOYMENT"), "true") == 0)
396 rc = send_k8s_extend_port();
399 printf("Could not send the extended port to k8s cluster.\n");
410 printf("NTSimulator config change callback failed: %s.", sr_strerror(rc));
420 simulator_status_cb(const char *xpath, sr_val_t **values, size_t *values_cnt,
421 uint64_t request_id, const char *original_xpath, void *private_ctx)
425 // printf("\n\n ========== Called simulator_status_cb for xpath: %s ==========\n\n", xpath);
427 counterAlarms ves_counter, netconf_counter;
428 rc = compute_notifications_count(&ves_counter, &netconf_counter);
431 printf("Could not compute the total number of notification count.\n");
434 if (sr_xpath_node_name_eq(xpath, "simulated-devices-list"))
437 size_t current_num_of_values= 0;
439 if (simulated_devices_config == 0) //nothing to return if no devices are running
447 rc = get_docker_containers_operational_state_curl(device_list);
450 printf("Could not get the operational state for the devices simulated.\n");
451 return SR_ERR_OPERATION_FAILED;
454 device_t *current_device = device_list->head;
456 while (current_device != NULL)
458 counterAlarms vesCount, netconfCount;
459 rc = getDeviceCounters(current_device->device_id, &vesCount, &netconfCount);
462 printf("Could not get Notification Counters for device with uuid=\"%s\"", current_device->device_id);
465 CREATE_NEW_VALUE(rc, v, current_num_of_values);
467 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "device-ip");
468 v[current_num_of_values - 1].type = SR_STRING_T;
469 v[current_num_of_values - 1].data.string_val = getenv("NTS_IP");
471 for (int i = 0; i < NETCONF_CONNECTIONS_PER_DEVICE; ++i)
473 CREATE_NEW_VALUE(rc, v, current_num_of_values);
475 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "device-port");
476 v[current_num_of_values - 1].type = SR_UINT32_T;
477 v[current_num_of_values - 1].data.uint32_val = current_device->netconf_port + i;
480 CREATE_NEW_VALUE(rc, v, current_num_of_values);
482 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "is-mounted");
483 v[current_num_of_values - 1].type = SR_BOOL_T;
484 v[current_num_of_values - 1].data.bool_val = current_device->is_mounted;
486 char *operational_state = get_docker_container_operational_state(device_list, current_device->device_id);
488 CREATE_NEW_VALUE(rc, v, current_num_of_values);
490 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "operational-state");
491 sr_val_build_str_data(&v[current_num_of_values - 1], SR_ENUM_T, "%s", operational_state);
493 CREATE_NEW_VALUE(rc, v, current_num_of_values);
495 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "normal");
496 v[current_num_of_values - 1].type = SR_UINT32_T;
497 v[current_num_of_values - 1].data.uint32_val = vesCount.normal;
499 CREATE_NEW_VALUE(rc, v, current_num_of_values);
501 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "warning");
502 v[current_num_of_values - 1].type = SR_UINT32_T;
503 v[current_num_of_values - 1].data.uint32_val = vesCount.warning;
505 CREATE_NEW_VALUE(rc, v, current_num_of_values);
507 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "minor");
508 v[current_num_of_values - 1].type = SR_UINT32_T;
509 v[current_num_of_values - 1].data.uint32_val = vesCount.minor;
511 CREATE_NEW_VALUE(rc, v, current_num_of_values);
513 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "major");
514 v[current_num_of_values - 1].type = SR_UINT32_T;
515 v[current_num_of_values - 1].data.uint32_val = vesCount.major;
517 CREATE_NEW_VALUE(rc, v, current_num_of_values);
519 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "critical");
520 v[current_num_of_values - 1].type = SR_UINT32_T;
521 v[current_num_of_values - 1].data.uint32_val = vesCount.critical;
523 CREATE_NEW_VALUE(rc, v, current_num_of_values);
525 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "normal");
526 v[current_num_of_values - 1].type = SR_UINT32_T;
527 v[current_num_of_values - 1].data.uint32_val = netconfCount.normal;
529 CREATE_NEW_VALUE(rc, v, current_num_of_values);
531 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "warning");
532 v[current_num_of_values - 1].type = SR_UINT32_T;
533 v[current_num_of_values - 1].data.uint32_val = netconfCount.warning;
535 CREATE_NEW_VALUE(rc, v, current_num_of_values);
537 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "minor");
538 v[current_num_of_values - 1].type = SR_UINT32_T;
539 v[current_num_of_values - 1].data.uint32_val = netconfCount.minor;
541 CREATE_NEW_VALUE(rc, v, current_num_of_values);
543 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "major");
544 v[current_num_of_values - 1].type = SR_UINT32_T;
545 v[current_num_of_values - 1].data.uint32_val = netconfCount.major;
547 CREATE_NEW_VALUE(rc, v, current_num_of_values);
549 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "critical");
550 v[current_num_of_values - 1].type = SR_UINT32_T;
551 v[current_num_of_values - 1].data.uint32_val = netconfCount.critical;
553 current_device = current_device->next;
556 //return the values that we have just created
558 *values_cnt = current_num_of_values;
560 else if (sr_xpath_node_name_eq(xpath, "simulation-usage-details"))
562 float cpu_usage = 0.0, mem_usage = 0.0;
564 char *resource_usage_from_script = get_docker_container_resource_stats();
566 if (resource_usage_from_script != NULL)
568 printf("Received line: %s\n", resource_usage_from_script);
569 sscanf(resource_usage_from_script, "CPU=%f%%;RAM=%fMiB", &cpu_usage, &mem_usage);
570 printf("Read cpu=\"%f\" and mem=\"%f\"\n", cpu_usage, mem_usage);
571 free(resource_usage_from_script);
575 /* convenient functions such as this can be found in sysrepo/values.h */
576 size_t current_num_of_values= 0;
578 CREATE_NEW_VALUE(rc, v, current_num_of_values);
580 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "running-simulated-devices");
581 v[current_num_of_values - 1].type = SR_UINT32_T;
582 v[current_num_of_values - 1].data.uint32_val = get_current_number_of_devices(device_list);
584 CREATE_NEW_VALUE(rc, v, current_num_of_values);
586 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "running-mounted-devices");
587 v[current_num_of_values - 1].type = SR_UINT32_T;
588 v[current_num_of_values - 1].data.uint32_val = get_current_number_of_mounted_devices(device_list);
590 CREATE_NEW_VALUE(rc, v, current_num_of_values);
592 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "base-netconf-port");
593 v[current_num_of_values - 1].type = SR_UINT32_T;
594 v[current_num_of_values - 1].data.uint32_val = get_netconf_port_base();
596 CREATE_NEW_VALUE(rc, v, current_num_of_values);
598 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "cpu-usage");
599 v[current_num_of_values - 1].type = SR_DECIMAL64_T;
600 v[current_num_of_values - 1].data.decimal64_val = cpu_usage;
602 CREATE_NEW_VALUE(rc, v, current_num_of_values);
604 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "mem-usage");
605 v[current_num_of_values - 1].type = SR_UINT32_T;
606 v[current_num_of_values - 1].data.uint32_val = (int)mem_usage;
608 //return the values that we have just created
610 *values_cnt = current_num_of_values;
612 else if (sr_xpath_node_name_eq(xpath, "total-ves-notifications"))
615 /* convenient functions such as this can be found in sysrepo/values.h */
616 size_t current_num_of_values= 0;
618 CREATE_NEW_VALUE(rc, v, current_num_of_values);
620 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "normal");
621 v[current_num_of_values - 1].type = SR_UINT32_T;
622 v[current_num_of_values - 1].data.uint32_val = ves_counter.normal;
624 CREATE_NEW_VALUE(rc, v, current_num_of_values);
626 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "warning");
627 v[current_num_of_values - 1].type = SR_UINT32_T;
628 v[current_num_of_values - 1].data.uint32_val = ves_counter.warning;
630 CREATE_NEW_VALUE(rc, v, current_num_of_values);
632 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "minor");
633 v[current_num_of_values - 1].type = SR_UINT32_T;
634 v[current_num_of_values - 1].data.uint32_val = ves_counter.minor;
636 CREATE_NEW_VALUE(rc, v, current_num_of_values);
638 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "major");
639 v[current_num_of_values - 1].type = SR_UINT32_T;
640 v[current_num_of_values - 1].data.uint32_val = ves_counter.major;
642 CREATE_NEW_VALUE(rc, v, current_num_of_values);
644 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "critical");
645 v[current_num_of_values - 1].type = SR_UINT32_T;
646 v[current_num_of_values - 1].data.uint32_val = ves_counter.critical;
648 //return the values that we have just created
650 *values_cnt = current_num_of_values;
652 else if (sr_xpath_node_name_eq(xpath, "total-netconf-notifications"))
655 /* convenient functions such as this can be found in sysrepo/values.h */
656 size_t current_num_of_values= 0;
658 CREATE_NEW_VALUE(rc, v, current_num_of_values);
660 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "normal");
661 v[current_num_of_values - 1].type = SR_UINT32_T;
662 v[current_num_of_values - 1].data.uint32_val = netconf_counter.normal;
664 CREATE_NEW_VALUE(rc, v, current_num_of_values);
666 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "warning");
667 v[current_num_of_values - 1].type = SR_UINT32_T;
668 v[current_num_of_values - 1].data.uint32_val = netconf_counter.warning;
670 CREATE_NEW_VALUE(rc, v, current_num_of_values);
672 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "minor");
673 v[current_num_of_values - 1].type = SR_UINT32_T;
674 v[current_num_of_values - 1].data.uint32_val = netconf_counter.minor;
676 CREATE_NEW_VALUE(rc, v, current_num_of_values);
678 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "major");
679 v[current_num_of_values - 1].type = SR_UINT32_T;
680 v[current_num_of_values - 1].data.uint32_val = netconf_counter.major;
682 CREATE_NEW_VALUE(rc, v, current_num_of_values);
684 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "critical");
685 v[current_num_of_values - 1].type = SR_UINT32_T;
686 v[current_num_of_values - 1].data.uint32_val = netconf_counter.critical;
688 //return the values that we have just created
690 *values_cnt = current_num_of_values;
696 int odl_add_key_pair_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
697 sr_val_t **output, size_t *output_cnt, void *private_ctx)
700 controller_t controller_list[CONTROLLER_LIST_MAX_LEN];
701 int controller_list_size = 0;
703 controller_list[0] = controller_details;
704 controller_list_size++;
706 for (int i = 0; i < controller_list_size; ++i)
708 printf("%d iteration: Got back url=%s and credentials=%s\n", i, controller_list[i].url, controller_list[i].credentials);
711 rc = add_key_pair_to_odl(controller_list, controller_list_size);
714 printf("Failed to add key pair to ODL.\n");
715 return SR_ERR_OPERATION_FAILED;
723 sigint_handler(int signum)
725 exit_application = 1;
729 main(int argc, char **argv)
731 sr_conn_ctx_t *connection = NULL;
732 sr_session_ctx_t *session = NULL;
733 sr_subscription_ctx_t *subscription = NULL;
736 setbuf(stdout, NULL);
738 rc = _init_curl_k8s();
741 fprintf(stderr, "Could not initialize cURL for K8S connection: %s\n", sr_strerror(rc));
744 device_list = new_device_stack();
748 fprintf(stderr, "Could not initialize cURL: %s\n", sr_strerror(rc));
751 rc = writeSkeletonConfigFile();
754 fprintf(stderr, "Could not initialize configuration JSON file: %s\n", sr_strerror(rc));
757 /* connect to sysrepo */
758 rc = sr_connect("network-topology-simulator", SR_CONN_DEFAULT, &connection);
759 if (SR_ERR_OK != rc) {
760 fprintf(stderr, "Error by sr_connect: %s\n", sr_strerror(rc));
765 rc = sr_session_start(connection, SR_DS_STARTUP, SR_SESS_DEFAULT, &session);
766 if (SR_ERR_OK != rc) {
767 fprintf(stderr, "Error by sr_session_start: %s\n", sr_strerror(rc));
771 // setting the values that come in an ENV variable as defaults - ves-heartbeat-period
772 int vesHeartbeatPeriod = getIntFromString(getenv("VesHeartbeatPeriod"), 0);
774 sr_val_t value = { 0 };
775 value.type = SR_UINT32_T;
776 value.data.uint32_val = vesHeartbeatPeriod;
777 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/notification-config/ves-heartbeat-period",
778 &value, SR_EDIT_DEFAULT);
779 if (SR_ERR_OK != rc) {
780 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
784 rc = ves_heartbeat_period_changed(vesHeartbeatPeriod);
785 if (SR_ERR_OK != rc) {
786 printf("Error by ves_heartbeat_period_changed: %s\n", sr_strerror(rc));
790 // setting the values that come in an ENV variable as defaults - is-netconf-available
792 int isNetconfAvailable = 1;
794 char *isNetconfAvailablString = getenv("IsNetconfAvailable");
795 if (isNetconfAvailablString != NULL)
797 if (strcmp(isNetconfAvailablString, "false") == 0)
799 isNetconfAvailable = 0;
803 value = (const sr_val_t) { 0 };
804 value.type = SR_BOOL_T;
805 value.data.bool_val = isNetconfAvailable;
806 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/notification-config/is-netconf-available",
807 &value, SR_EDIT_DEFAULT);
808 if (SR_ERR_OK != rc) {
809 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
813 rc = is_netconf_available_changed(isNetconfAvailable);
814 if (SR_ERR_OK != rc) {
815 printf("Error by is_netconf_available_changed: %s\n", sr_strerror(rc));
819 // setting the values that come in an ENV variable as defaults - is-ves-available
821 int isVesAvailable = 1;
823 char *isVesAvailablString = getenv("IsVesAvailable");
824 if (isVesAvailablString != NULL)
826 if (strcmp(isVesAvailablString, "false") == 0)
832 value = (const sr_val_t) { 0 };
833 value.type = SR_BOOL_T;
834 value.data.bool_val = isVesAvailable;
835 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/notification-config/is-ves-available",
836 &value, SR_EDIT_DEFAULT);
837 if (SR_ERR_OK != rc) {
838 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
842 rc = is_ves_available_changed(isVesAvailable);
843 if (SR_ERR_OK != rc) {
844 printf("Error by is_ves_available_changed: %s\n", sr_strerror(rc));
848 // setting the values that come in an ENV variable as defaults - ves-endpoint-port
850 int vesEndpointPort = getIntFromString(getenv("VesEndpointPort"), 8080);
852 value = (const sr_val_t) { 0 };
853 value.type = SR_UINT16_T;
854 value.data.uint16_val = vesEndpointPort;
855 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-port",
856 &value, SR_EDIT_DEFAULT);
857 if (SR_ERR_OK != rc) {
858 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
862 rc = ves_port_changed(vesEndpointPort);
863 if (SR_ERR_OK != rc) {
864 printf("Error by ves_port_changed: %s\n", sr_strerror(rc));
868 // setting the values that come in an ENV variable as defaults - ves-endpoint-ip
870 value = (const sr_val_t) { 0 };
871 value.type = SR_STRING_T;
872 value.data.string_val = getenv("VesEndpointIp");
873 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-ip",
874 &value, SR_EDIT_DEFAULT);
875 if (SR_ERR_OK != rc) {
876 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
880 rc = ves_ip_changed(getenv("VesEndpointIp"));
881 if (SR_ERR_OK != rc) {
882 printf("Error by ves_ip_changed: %s\n", sr_strerror(rc));
886 // setting the values that come in an ENV variable as defaults - ssh-connections
888 int sshConnections = getIntFromString(getenv("SshConnections"), 1);
890 value = (const sr_val_t) { 0 };
891 value.type = SR_UINT32_T;
892 value.data.uint32_val = sshConnections;
893 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ssh-connections",
894 &value, SR_EDIT_DEFAULT);
895 if (SR_ERR_OK != rc) {
896 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
900 rc = ssh_connections_changed(sshConnections);
901 if (SR_ERR_OK != rc) {
902 printf("Error by ssh_connections_changed: %s\n", sr_strerror(rc));
906 // setting the values that come in an ENV variable as defaults - tls-connections
908 int tlsConnections = getIntFromString(getenv("TlsConnections"), 0);
910 value = (const sr_val_t) { 0 };
911 value.type = SR_UINT32_T;
912 value.data.uint32_val = tlsConnections;
913 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/tls-connections",
914 &value, SR_EDIT_DEFAULT);
915 if (SR_ERR_OK != rc) {
916 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
920 rc = tls_connections_changed(tlsConnections);
921 if (SR_ERR_OK != rc) {
922 printf("Error by tls_connections_changed: %s\n", sr_strerror(rc));
926 if (strcmp(getenv("K8S_DEPLOYMENT"), "true") == 0)
928 rc = send_k8s_extend_port();
931 printf("Could not send the number of ports to k8s cluster\n");
935 //commit the changes that we have done until now
936 rc = sr_commit(session);
937 if (SR_ERR_OK != rc) {
938 printf("Error by sr_commit: %s\n", sr_strerror(rc));
942 /* read startup config */
943 printf("\n\n ========== READING STARTUP CONFIG network-topology-simulator: ==========\n\n");
944 print_current_config(session, "network-topology-simulator");
946 /* subscribe for changes in running config */
947 rc = sr_module_change_subscribe(session, "network-topology-simulator", simulator_config_change_cb, NULL,
948 0, SR_SUBSCR_DEFAULT | SR_SUBSCR_APPLY_ONLY, &subscription);
949 if (SR_ERR_OK != rc) {
950 fprintf(stderr, "Error by sr_module_change_subscribe: %s\n", sr_strerror(rc));
954 /* subscribe as state data provider for the ntsimulator state data */
955 rc = sr_dp_get_items_subscribe(session, "/network-topology-simulator:simulator-status", simulator_status_cb, NULL,
956 SR_SUBSCR_CTX_REUSE, &subscription);
957 if (rc != SR_ERR_OK) {
961 rc = notification_delay_period_changed(NULL, 0);
962 if (rc != SR_ERR_OK) {
963 printf("Could not write the delay period to file!\n");
967 rc = _init_curl_odl();
970 fprintf(stderr, "Could not initialize cURL for ODL connection: %s\n", sr_strerror(rc));
973 rc = sr_rpc_subscribe(session, "/network-topology-simulator:add-key-pair-to-odl", odl_add_key_pair_cb, (void *)session,
974 SR_SUBSCR_CTX_REUSE, &subscription);
976 printf("\n\n ========== STARTUP CONFIG network-topology-simulator APPLIED AS RUNNING ==========\n\n");
978 rc = writeSkeletonStatusFile();
981 fprintf(stderr, "Could not initialize status JSON file: %s\n", sr_strerror(rc));
984 /* loop until ctrl-c is pressed / SIGINT is received */
985 signal(SIGINT, sigint_handler);
986 signal(SIGTERM, sigint_handler);
987 signal(SIGPIPE, SIG_IGN);
989 while (!exit_application) {
991 sleep(1); /* or do some more useful work... */
994 printf("Application exit requested, exiting.\n");
997 if (NULL != subscription) {
998 sr_unsubscribe(session, subscription);
1000 if (NULL != session) {
1001 sr_session_stop(session);
1003 if (NULL != connection) {
1004 sr_disconnect(connection);
1007 clean_current_docker_configuration();
1008 rc = cleanup_curl();
1009 rc = cleanup_curl_odl();
1010 rc = cleanup_curl_k8s();
1015 static void clean_current_docker_configuration(void)
1017 if (strcmp(getenv("K8S_DEPLOYMENT"), "true"))
1022 printf("Cleaning docker containers...\n");
1024 if (device_list == NULL)
1029 for (int i = 0; i < simulated_devices_config; ++i)
1031 stop_device(device_list);
1034 printf("Cleaning completed!\n");