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-auth-method", &val);
303 if (rc != SR_ERR_OK) {
307 rc = ves_auth_method_changed(val->data.enum_val);
308 if (rc != SR_ERR_OK) {
312 if (strcmp(val->data.enum_val, "basic-auth") == 0)
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) {
323 rc = ves_username_changed(val->data.string_val);
324 if (rc != SR_ERR_OK) {
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) {
337 rc = ves_password_changed(val->data.string_val);
338 if (rc != SR_ERR_OK) {
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) {
357 rc = ves_port_changed(val->data.uint16_val);
358 if (rc != SR_ERR_OK) {
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) {
371 rc = ves_registration_changed(val->data.bool_val);
372 if (rc != SR_ERR_OK) {
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) {
385 rc = is_netconf_available_changed(val->data.bool_val);
386 if (rc != SR_ERR_OK) {
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) {
399 rc = is_ves_available_changed(val->data.bool_val);
400 if (rc != SR_ERR_OK) {
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) {
413 rc = netconf_call_home_changed(val->data.bool_val);
414 if (rc != SR_ERR_OK) {
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) {
427 rc = controller_ip_changed(val->data.string_val);
428 if (rc != SR_ERR_OK) {
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) {
441 rc = controller_port_changed(val->data.uint16_val);
442 if (rc != SR_ERR_OK) {
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) {
455 rc = controller_netconf_call_home_port_changed(val->data.uint16_val);
456 if (rc != SR_ERR_OK) {
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) {
469 rc = controller_username_changed(val->data.string_val);
470 if (rc != SR_ERR_OK) {
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) {
483 rc = controller_password_changed(val->data.string_val);
484 if (rc != SR_ERR_OK) {
494 printf("NTSimulator config change callback failed: %s.", sr_strerror(rc));
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)
509 // printf("\n\n ========== Called simulator_status_cb for xpath: %s ==========\n\n", xpath);
511 counterAlarms ves_counter, netconf_counter;
512 rc = compute_notifications_count(&ves_counter, &netconf_counter);
515 printf("Could not compute the total number of notification count.\n");
518 if (sr_xpath_node_name_eq(xpath, "simulated-devices-list"))
521 size_t current_num_of_values= 0;
523 if (simulated_devices_config == 0) //nothing to return if no devices are running
531 rc = get_docker_containers_operational_state_curl(device_list);
534 printf("Could not get the operational state for the devices simulated.\n");
535 return SR_ERR_OPERATION_FAILED;
538 device_t *current_device = device_list->head;
540 while (current_device != NULL)
542 counterAlarms vesCount, netconfCount;
543 rc = getDeviceCounters(current_device->device_id, &vesCount, &netconfCount);
546 printf("Could not get Notification Counters for device with uuid=\"%s\"", current_device->device_id);
549 char device_name[200];
550 sprintf(device_name, "%s-%d", getenv("CONTAINER_NAME"), current_device->device_number);
552 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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");
558 for (int i = 0; i < NETCONF_CONNECTIONS_PER_DEVICE; ++i)
560 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
567 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
573 char *operational_state = get_docker_container_operational_state(device_list, current_device->device_id);
575 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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);
580 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
586 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
592 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
598 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
604 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
610 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
616 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
622 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
628 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
634 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
640 current_device = current_device->next;
643 //return the values that we have just created
645 *values_cnt = current_num_of_values;
647 else if (sr_xpath_node_name_eq(xpath, "simulation-usage-details"))
649 float cpu_usage = 0.0, mem_usage = 0.0;
651 char *resource_usage_from_script = get_docker_container_resource_stats();
653 if (resource_usage_from_script != NULL)
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);
662 /* convenient functions such as this can be found in sysrepo/values.h */
663 size_t current_num_of_values= 0;
665 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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);
671 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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);
677 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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();
683 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
689 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
695 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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();
701 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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();
707 //return the values that we have just created
709 *values_cnt = current_num_of_values;
711 else if (sr_xpath_node_name_eq(xpath, "total-ves-notifications"))
714 /* convenient functions such as this can be found in sysrepo/values.h */
715 size_t current_num_of_values= 0;
717 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
723 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
729 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
735 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
741 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
747 //return the values that we have just created
749 *values_cnt = current_num_of_values;
751 else if (sr_xpath_node_name_eq(xpath, "total-netconf-notifications"))
754 /* convenient functions such as this can be found in sysrepo/values.h */
755 size_t current_num_of_values= 0;
757 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
763 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
769 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
775 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
781 CREATE_NEW_VALUE(rc, v, current_num_of_values);
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;
787 //return the values that we have just created
789 *values_cnt = current_num_of_values;
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)
799 controller_t controller_list[CONTROLLER_LIST_MAX_LEN];
800 int controller_list_size = 0;
802 controller_list[0] = controller_details;
803 controller_list_size++;
805 for (int i = 0; i < controller_list_size; ++i)
807 printf("%d iteration: Got back url=%s and credentials=%s\n", i, controller_list[i].url, controller_list[i].credentials);
810 rc = add_key_pair_to_odl(controller_list, controller_list_size);
813 printf("Failed to add key pair to ODL.\n");
814 return SR_ERR_OPERATION_FAILED;
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)
825 char *device_name = NULL, *module_name = NULL, *notification_object = NULL;
827 /* print input values */
828 printf("\n\n ========== RECEIVED RPC REQUEST ==========\n\n");
829 printf(">>> RPC Input:\n\n");
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);
835 rc = sr_new_values(1, output);
836 if (SR_ERR_OK != rc) {
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) {
846 rc = invoke_device_notification(device_name, module_name, notification_object);
850 sr_val_build_str_data(&(*output)[0], SR_ENUM_T, "%s", "ERROR");
854 sr_val_build_str_data(&(*output)[0], SR_ENUM_T, "%s", "SUCCESS");
863 sigint_handler(int signum)
865 exit_application = 1;
869 main(int argc, char **argv)
871 sr_conn_ctx_t *connection = NULL;
872 sr_session_ctx_t *session = NULL;
873 sr_subscription_ctx_t *subscription = NULL;
876 setbuf(stdout, NULL);
878 rc = _init_curl_k8s();
881 fprintf(stderr, "Could not initialize cURL for K8S connection: %s\n", sr_strerror(rc));
884 device_list = new_device_stack();
888 fprintf(stderr, "Could not initialize cURL: %s\n", sr_strerror(rc));
891 rc = writeSkeletonConfigFile();
894 fprintf(stderr, "Could not initialize configuration JSON file: %s\n", sr_strerror(rc));
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));
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));
911 // setting the values that come in an ENV variable as defaults - ves-heartbeat-period
912 int vesHeartbeatPeriod = getIntFromString(getenv("VesHeartbeatPeriod"), 0);
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));
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));
930 // setting the values that come in an ENV variable as defaults - is-netconf-available
932 int isNetconfAvailable = 1;
934 char *isNetconfAvailablString = getenv("IsNetconfAvailable");
935 if (isNetconfAvailablString != NULL)
937 if (strcmp(isNetconfAvailablString, "false") == 0)
939 isNetconfAvailable = 0;
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));
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));
959 // setting the values that come in an ENV variable as defaults - is-ves-available
961 int isVesAvailable = 1;
963 char *isVesAvailablString = getenv("IsVesAvailable");
964 if (isVesAvailablString != NULL)
966 if (strcmp(isVesAvailablString, "false") == 0)
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));
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));
988 // setting the values that come in an ENV variable as defaults - ves-endpoint-port
990 int vesEndpointPort = getIntFromString(getenv("VesEndpointPort"), 8080);
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));
1002 rc = ves_port_changed(vesEndpointPort);
1003 if (SR_ERR_OK != rc) {
1004 printf("Error by ves_port_changed: %s\n", sr_strerror(rc));
1008 // setting the values that come in an ENV variable as defaults - ves-endpoint-ip
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));
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));
1026 // setting the values that come in an ENV variable as defaults - ves-endpoint-auth-method
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));
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));
1044 //TODO only basic-auth implemented vor VES
1045 if (strcmp(getenv("VesEndpointAuthMethod"), "basic-auth") == 0)
1047 // setting the values that come in an ENV variable as defaults - ves-endpoint-usename
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));
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));
1065 // setting the values that come in an ENV variable as defaults - ves-endpoint-password
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));
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));
1084 // setting the values that come in an ENV variable as defaults - ves-registration
1086 int vesRegistration = 1;
1088 char *vesRegistrationString = getenv("VesRegistration");
1089 if (vesRegistrationString != NULL)
1091 if (strcmp(vesRegistrationString, "false") == 0)
1093 vesRegistration = 0;
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));
1107 rc = ves_registration_changed(vesRegistration);
1108 if (SR_ERR_OK != rc) {
1109 printf("Error by ves_registration_changed: %s\n", sr_strerror(rc));
1113 // setting the values that come in an ENV variable as defaults - ssh-connections
1115 int sshConnections = getIntFromString(getenv("SshConnections"), 1);
1117 rc = ssh_connections_changed(sshConnections);
1118 if (SR_ERR_OK != rc) {
1119 printf("Error by ssh_connections_changed: %s\n", sr_strerror(rc));
1123 // setting the values that come in an ENV variable as defaults - tls-connections
1125 int tlsConnections = getIntFromString(getenv("TlsConnections"), 0);
1127 rc = tls_connections_changed(tlsConnections);
1128 if (SR_ERR_OK != rc) {
1129 printf("Error by tls_connections_changed: %s\n", sr_strerror(rc));
1133 if (strcmp(getenv("K8S_DEPLOYMENT"), "true") == 0)
1135 rc = send_k8s_extend_port();
1136 if (rc != SR_ERR_OK)
1138 printf("Could not send the number of ports to k8s cluster\n");
1142 // setting the values that come in an ENV variable as defaults - controller-ip
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));
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));
1160 // setting the values that come in an ENV variable as defaults - controller-port
1162 int controllerPort = getIntFromString(getenv("ControllerPort"), 8181);
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));
1174 rc = controller_port_changed(controllerPort);
1175 if (SR_ERR_OK != rc) {
1176 printf("Error by controller_port_changed: %s\n", sr_strerror(rc));
1180 // setting the values that come in an ENV variable as defaults - netconf-call-home-port
1182 int netconfCallHomePort = getIntFromString(getenv("NetconfCallHomePort"), 6666);
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));
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));
1200 // setting the values that come in an ENV variable as defaults - controller-username
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));
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));
1218 // setting the values that come in an ENV variable as defaults - controller-password
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));
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));
1236 // setting the values that come in an ENV variable as defaults - netconf-call-home
1238 int netconfCallHome = 1;
1240 char *netconfCallHomeString = getenv("NetconfCallHome");
1241 if (netconfCallHomeString != NULL)
1243 if (strcmp(netconfCallHomeString, "false") == 0)
1245 netconfCallHome = 0;
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));
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));
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));
1272 /* read startup config */
1273 printf("\n\n ========== READING STARTUP CONFIG network-topology-simulator: ==========\n\n");
1274 print_current_config(session, "network-topology-simulator");
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));
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) {
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");
1297 rc = _init_curl_odl();
1298 if (rc != SR_ERR_OK)
1300 fprintf(stderr, "Could not initialize cURL for ODL connection: %s\n", sr_strerror(rc));
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);
1306 printf("\n\n ========== STARTUP CONFIG network-topology-simulator APPLIED AS RUNNING ==========\n\n");
1308 rc = writeSkeletonStatusFile();
1309 if (rc != SR_ERR_OK)
1311 fprintf(stderr, "Could not initialize status JSON file: %s\n", sr_strerror(rc));
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));
1321 rc = pull_docker_image_of_simulated_device();
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);
1328 while (!exit_application) {
1330 sleep(1); /* or do some more useful work... */
1333 printf("Application exit requested, exiting.\n");
1336 if (NULL != subscription) {
1337 sr_unsubscribe(session, subscription);
1339 if (NULL != session) {
1340 sr_session_stop(session);
1342 if (NULL != connection) {
1343 sr_disconnect(connection);
1346 clean_current_docker_configuration();
1347 rc = cleanup_curl();
1348 rc = cleanup_curl_odl();
1349 rc = cleanup_curl_k8s();
1354 static void clean_current_docker_configuration(void)
1356 if (strcmp(getenv("K8S_DEPLOYMENT"), "true"))
1361 printf("Cleaning docker containers...\n");
1363 if (device_list == NULL)
1368 for (int i = 0; i < simulated_devices_config; ++i)
1370 stop_device(device_list);
1373 printf("Cleaning completed!\n");