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) {
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-endpoint-username", &val);
317 if (rc != SR_ERR_OK) {
321 rc = ves_username_changed(val->data.string_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/ves-endpoint-details/ves-endpoint-password", &val);
331 if (rc != SR_ERR_OK) {
335 rc = ves_password_changed(val->data.string_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/ves-endpoint-details/ves-endpoint-port", &val);
345 if (rc != SR_ERR_OK) {
349 rc = ves_port_changed(val->data.uint16_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/ves-endpoint-details/ves-registration", &val);
359 if (rc != SR_ERR_OK) {
363 rc = ves_registration_changed(val->data.bool_val);
364 if (rc != SR_ERR_OK) {
371 /* get the value from sysrepo, we do not care if the value did not change in our case */
372 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/is-netconf-available", &val);
373 if (rc != SR_ERR_OK) {
377 rc = is_netconf_available_changed(val->data.bool_val);
378 if (rc != SR_ERR_OK) {
385 /* get the value from sysrepo, we do not care if the value did not change in our case */
386 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/is-ves-available", &val);
387 if (rc != SR_ERR_OK) {
391 rc = is_ves_available_changed(val->data.bool_val);
392 if (rc != SR_ERR_OK) {
399 /* get the value from sysrepo, we do not care if the value did not change in our case */
400 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/netconf-call-home", &val);
401 if (rc != SR_ERR_OK) {
405 rc = netconf_call_home_changed(val->data.bool_val);
406 if (rc != SR_ERR_OK) {
413 /* get the value from sysrepo, we do not care if the value did not change in our case */
414 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-ip", &val);
415 if (rc != SR_ERR_OK) {
419 rc = controller_ip_changed(val->data.string_val);
420 if (rc != SR_ERR_OK) {
427 /* get the value from sysrepo, we do not care if the value did not change in our case */
428 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-port", &val);
429 if (rc != SR_ERR_OK) {
433 rc = controller_port_changed(val->data.uint16_val);
434 if (rc != SR_ERR_OK) {
441 /* get the value from sysrepo, we do not care if the value did not change in our case */
442 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/netconf-call-home-port", &val);
443 if (rc != SR_ERR_OK) {
447 rc = controller_netconf_call_home_port_changed(val->data.uint16_val);
448 if (rc != SR_ERR_OK) {
455 /* get the value from sysrepo, we do not care if the value did not change in our case */
456 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-username", &val);
457 if (rc != SR_ERR_OK) {
461 rc = controller_username_changed(val->data.string_val);
462 if (rc != SR_ERR_OK) {
469 /* get the value from sysrepo, we do not care if the value did not change in our case */
470 rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-password", &val);
471 if (rc != SR_ERR_OK) {
475 rc = controller_password_changed(val->data.string_val);
476 if (rc != SR_ERR_OK) {
486 printf("NTSimulator config change callback failed: %s.", sr_strerror(rc));
496 simulator_status_cb(const char *xpath, sr_val_t **values, size_t *values_cnt,
497 uint64_t request_id, const char *original_xpath, void *private_ctx)
501 // printf("\n\n ========== Called simulator_status_cb for xpath: %s ==========\n\n", xpath);
503 counterAlarms ves_counter, netconf_counter;
504 rc = compute_notifications_count(&ves_counter, &netconf_counter);
507 printf("Could not compute the total number of notification count.\n");
510 if (sr_xpath_node_name_eq(xpath, "simulated-devices-list"))
513 size_t current_num_of_values= 0;
515 if (simulated_devices_config == 0) //nothing to return if no devices are running
523 rc = get_docker_containers_operational_state_curl(device_list);
526 printf("Could not get the operational state for the devices simulated.\n");
527 return SR_ERR_OPERATION_FAILED;
530 device_t *current_device = device_list->head;
532 while (current_device != NULL)
534 counterAlarms vesCount, netconfCount;
535 rc = getDeviceCounters(current_device->device_id, &vesCount, &netconfCount);
538 printf("Could not get Notification Counters for device with uuid=\"%s\"", current_device->device_id);
541 char device_name[200];
542 sprintf(device_name, "%s-%d", getenv("CONTAINER_NAME"), current_device->device_number);
544 CREATE_NEW_VALUE(rc, v, current_num_of_values);
546 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, device_name, "device-ip");
547 v[current_num_of_values - 1].type = SR_STRING_T;
548 v[current_num_of_values - 1].data.string_val = getenv("NTS_IP");
550 for (int i = 0; i < NETCONF_CONNECTIONS_PER_DEVICE; ++i)
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-port");
555 v[current_num_of_values - 1].type = SR_UINT32_T;
556 v[current_num_of_values - 1].data.uint32_val = current_device->netconf_port + i;
559 CREATE_NEW_VALUE(rc, v, current_num_of_values);
561 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, device_name, "is-mounted");
562 v[current_num_of_values - 1].type = SR_BOOL_T;
563 v[current_num_of_values - 1].data.bool_val = current_device->is_mounted;
565 char *operational_state = get_docker_container_operational_state(device_list, current_device->device_id);
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, "operational-state");
570 sr_val_build_str_data(&v[current_num_of_values - 1], SR_ENUM_T, "%s", operational_state);
572 CREATE_NEW_VALUE(rc, v, current_num_of_values);
574 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "normal");
575 v[current_num_of_values - 1].type = SR_UINT32_T;
576 v[current_num_of_values - 1].data.uint32_val = vesCount.normal;
578 CREATE_NEW_VALUE(rc, v, current_num_of_values);
580 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "warning");
581 v[current_num_of_values - 1].type = SR_UINT32_T;
582 v[current_num_of_values - 1].data.uint32_val = vesCount.warning;
584 CREATE_NEW_VALUE(rc, v, current_num_of_values);
586 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "minor");
587 v[current_num_of_values - 1].type = SR_UINT32_T;
588 v[current_num_of_values - 1].data.uint32_val = vesCount.minor;
590 CREATE_NEW_VALUE(rc, v, current_num_of_values);
592 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "major");
593 v[current_num_of_values - 1].type = SR_UINT32_T;
594 v[current_num_of_values - 1].data.uint32_val = vesCount.major;
596 CREATE_NEW_VALUE(rc, v, current_num_of_values);
598 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "critical");
599 v[current_num_of_values - 1].type = SR_UINT32_T;
600 v[current_num_of_values - 1].data.uint32_val = vesCount.critical;
602 CREATE_NEW_VALUE(rc, v, current_num_of_values);
604 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "normal");
605 v[current_num_of_values - 1].type = SR_UINT32_T;
606 v[current_num_of_values - 1].data.uint32_val = netconfCount.normal;
608 CREATE_NEW_VALUE(rc, v, current_num_of_values);
610 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "warning");
611 v[current_num_of_values - 1].type = SR_UINT32_T;
612 v[current_num_of_values - 1].data.uint32_val = netconfCount.warning;
614 CREATE_NEW_VALUE(rc, v, current_num_of_values);
616 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "minor");
617 v[current_num_of_values - 1].type = SR_UINT32_T;
618 v[current_num_of_values - 1].data.uint32_val = netconfCount.minor;
620 CREATE_NEW_VALUE(rc, v, current_num_of_values);
622 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "major");
623 v[current_num_of_values - 1].type = SR_UINT32_T;
624 v[current_num_of_values - 1].data.uint32_val = netconfCount.major;
626 CREATE_NEW_VALUE(rc, v, current_num_of_values);
628 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "critical");
629 v[current_num_of_values - 1].type = SR_UINT32_T;
630 v[current_num_of_values - 1].data.uint32_val = netconfCount.critical;
632 current_device = current_device->next;
635 //return the values that we have just created
637 *values_cnt = current_num_of_values;
639 else if (sr_xpath_node_name_eq(xpath, "simulation-usage-details"))
641 float cpu_usage = 0.0, mem_usage = 0.0;
643 char *resource_usage_from_script = get_docker_container_resource_stats();
645 if (resource_usage_from_script != NULL)
647 printf("Received line: %s\n", resource_usage_from_script);
648 sscanf(resource_usage_from_script, "CPU=%f%%;RAM=%fMiB", &cpu_usage, &mem_usage);
649 printf("Read cpu=\"%f\" and mem=\"%f\"\n", cpu_usage, mem_usage);
650 free(resource_usage_from_script);
654 /* convenient functions such as this can be found in sysrepo/values.h */
655 size_t current_num_of_values= 0;
657 CREATE_NEW_VALUE(rc, v, current_num_of_values);
659 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "running-simulated-devices");
660 v[current_num_of_values - 1].type = SR_UINT32_T;
661 v[current_num_of_values - 1].data.uint32_val = get_current_number_of_devices(device_list);
663 CREATE_NEW_VALUE(rc, v, current_num_of_values);
665 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "running-mounted-devices");
666 v[current_num_of_values - 1].type = SR_UINT32_T;
667 v[current_num_of_values - 1].data.uint32_val = get_current_number_of_mounted_devices(device_list);
669 CREATE_NEW_VALUE(rc, v, current_num_of_values);
671 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "base-netconf-port");
672 v[current_num_of_values - 1].type = SR_UINT32_T;
673 v[current_num_of_values - 1].data.uint32_val = get_netconf_port_base();
675 CREATE_NEW_VALUE(rc, v, current_num_of_values);
677 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "cpu-usage");
678 v[current_num_of_values - 1].type = SR_DECIMAL64_T;
679 v[current_num_of_values - 1].data.decimal64_val = cpu_usage;
681 CREATE_NEW_VALUE(rc, v, current_num_of_values);
683 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "mem-usage");
684 v[current_num_of_values - 1].type = SR_UINT32_T;
685 v[current_num_of_values - 1].data.uint32_val = (int)mem_usage;
687 CREATE_NEW_VALUE(rc, v, current_num_of_values);
689 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "ssh-connections");
690 v[current_num_of_values - 1].type = SR_UINT32_T;
691 v[current_num_of_values - 1].data.uint32_val = getSshConnectionsFromConfigJson();
693 CREATE_NEW_VALUE(rc, v, current_num_of_values);
695 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "tls-connections");
696 v[current_num_of_values - 1].type = SR_UINT32_T;
697 v[current_num_of_values - 1].data.uint32_val = getTlsConnectionsFromConfigJson();
699 //return the values that we have just created
701 *values_cnt = current_num_of_values;
703 else if (sr_xpath_node_name_eq(xpath, "total-ves-notifications"))
706 /* convenient functions such as this can be found in sysrepo/values.h */
707 size_t current_num_of_values= 0;
709 CREATE_NEW_VALUE(rc, v, current_num_of_values);
711 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "normal");
712 v[current_num_of_values - 1].type = SR_UINT32_T;
713 v[current_num_of_values - 1].data.uint32_val = ves_counter.normal;
715 CREATE_NEW_VALUE(rc, v, current_num_of_values);
717 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "warning");
718 v[current_num_of_values - 1].type = SR_UINT32_T;
719 v[current_num_of_values - 1].data.uint32_val = ves_counter.warning;
721 CREATE_NEW_VALUE(rc, v, current_num_of_values);
723 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "minor");
724 v[current_num_of_values - 1].type = SR_UINT32_T;
725 v[current_num_of_values - 1].data.uint32_val = ves_counter.minor;
727 CREATE_NEW_VALUE(rc, v, current_num_of_values);
729 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "major");
730 v[current_num_of_values - 1].type = SR_UINT32_T;
731 v[current_num_of_values - 1].data.uint32_val = ves_counter.major;
733 CREATE_NEW_VALUE(rc, v, current_num_of_values);
735 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "critical");
736 v[current_num_of_values - 1].type = SR_UINT32_T;
737 v[current_num_of_values - 1].data.uint32_val = ves_counter.critical;
739 //return the values that we have just created
741 *values_cnt = current_num_of_values;
743 else if (sr_xpath_node_name_eq(xpath, "total-netconf-notifications"))
746 /* convenient functions such as this can be found in sysrepo/values.h */
747 size_t current_num_of_values= 0;
749 CREATE_NEW_VALUE(rc, v, current_num_of_values);
751 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "normal");
752 v[current_num_of_values - 1].type = SR_UINT32_T;
753 v[current_num_of_values - 1].data.uint32_val = netconf_counter.normal;
755 CREATE_NEW_VALUE(rc, v, current_num_of_values);
757 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "warning");
758 v[current_num_of_values - 1].type = SR_UINT32_T;
759 v[current_num_of_values - 1].data.uint32_val = netconf_counter.warning;
761 CREATE_NEW_VALUE(rc, v, current_num_of_values);
763 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "minor");
764 v[current_num_of_values - 1].type = SR_UINT32_T;
765 v[current_num_of_values - 1].data.uint32_val = netconf_counter.minor;
767 CREATE_NEW_VALUE(rc, v, current_num_of_values);
769 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "major");
770 v[current_num_of_values - 1].type = SR_UINT32_T;
771 v[current_num_of_values - 1].data.uint32_val = netconf_counter.major;
773 CREATE_NEW_VALUE(rc, v, current_num_of_values);
775 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "critical");
776 v[current_num_of_values - 1].type = SR_UINT32_T;
777 v[current_num_of_values - 1].data.uint32_val = netconf_counter.critical;
779 //return the values that we have just created
781 *values_cnt = current_num_of_values;
787 static int odl_add_key_pair_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
788 sr_val_t **output, size_t *output_cnt, void *private_ctx)
791 controller_t controller_list[CONTROLLER_LIST_MAX_LEN];
792 int controller_list_size = 0;
794 controller_list[0] = controller_details;
795 controller_list_size++;
797 for (int i = 0; i < controller_list_size; ++i)
799 printf("%d iteration: Got back url=%s and credentials=%s\n", i, controller_list[i].url, controller_list[i].credentials);
802 rc = add_key_pair_to_odl(controller_list, controller_list_size);
805 printf("Failed to add key pair to ODL.\n");
806 return SR_ERR_OPERATION_FAILED;
812 static int invoke_notification_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
813 sr_val_t **output, size_t *output_cnt, void *private_ctx)
817 char *device_name = NULL, *module_name = NULL, *notification_object = NULL;
819 /* print input values */
820 printf("\n\n ========== RECEIVED RPC REQUEST ==========\n\n");
821 printf(">>> RPC Input:\n\n");
823 device_name = strdup(input[0].data.string_val);
824 module_name = strdup(input[1].data.string_val);
825 notification_object = strdup(input[2].data.string_val);
827 rc = sr_new_values(1, output);
828 if (SR_ERR_OK != rc) {
832 /* set 'output/step-count' leaf */
833 rc = sr_val_set_xpath(&(*output)[0], "/network-topology-simulator:invoke-notification/status");
834 if (SR_ERR_OK != rc) {
838 rc = invoke_device_notification(device_name, module_name, notification_object);
842 sr_val_build_str_data(&(*output)[0], SR_ENUM_T, "%s", "ERROR");
846 sr_val_build_str_data(&(*output)[0], SR_ENUM_T, "%s", "SUCCESS");
855 sigint_handler(int signum)
857 exit_application = 1;
861 main(int argc, char **argv)
863 sr_conn_ctx_t *connection = NULL;
864 sr_session_ctx_t *session = NULL;
865 sr_subscription_ctx_t *subscription = NULL;
868 setbuf(stdout, NULL);
870 rc = _init_curl_k8s();
873 fprintf(stderr, "Could not initialize cURL for K8S connection: %s\n", sr_strerror(rc));
876 device_list = new_device_stack();
880 fprintf(stderr, "Could not initialize cURL: %s\n", sr_strerror(rc));
883 rc = writeSkeletonConfigFile();
886 fprintf(stderr, "Could not initialize configuration JSON file: %s\n", sr_strerror(rc));
889 /* connect to sysrepo */
890 rc = sr_connect("network-topology-simulator", SR_CONN_DEFAULT, &connection);
891 if (SR_ERR_OK != rc) {
892 fprintf(stderr, "Error by sr_connect: %s\n", sr_strerror(rc));
897 rc = sr_session_start(connection, SR_DS_STARTUP, SR_SESS_DEFAULT, &session);
898 if (SR_ERR_OK != rc) {
899 fprintf(stderr, "Error by sr_session_start: %s\n", sr_strerror(rc));
903 // setting the values that come in an ENV variable as defaults - ves-heartbeat-period
904 int vesHeartbeatPeriod = getIntFromString(getenv("VesHeartbeatPeriod"), 0);
906 sr_val_t value = { 0 };
907 value.type = SR_UINT32_T;
908 value.data.uint32_val = vesHeartbeatPeriod;
909 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/notification-config/ves-heartbeat-period",
910 &value, SR_EDIT_DEFAULT);
911 if (SR_ERR_OK != rc) {
912 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
916 rc = ves_heartbeat_period_changed(vesHeartbeatPeriod);
917 if (SR_ERR_OK != rc) {
918 printf("Error by ves_heartbeat_period_changed: %s\n", sr_strerror(rc));
922 // setting the values that come in an ENV variable as defaults - is-netconf-available
924 int isNetconfAvailable = 1;
926 char *isNetconfAvailablString = getenv("IsNetconfAvailable");
927 if (isNetconfAvailablString != NULL)
929 if (strcmp(isNetconfAvailablString, "false") == 0)
931 isNetconfAvailable = 0;
935 value = (const sr_val_t) { 0 };
936 value.type = SR_BOOL_T;
937 value.data.bool_val = isNetconfAvailable;
938 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/notification-config/is-netconf-available",
939 &value, SR_EDIT_DEFAULT);
940 if (SR_ERR_OK != rc) {
941 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
945 rc = is_netconf_available_changed(isNetconfAvailable);
946 if (SR_ERR_OK != rc) {
947 printf("Error by is_netconf_available_changed: %s\n", sr_strerror(rc));
951 // setting the values that come in an ENV variable as defaults - is-ves-available
953 int isVesAvailable = 1;
955 char *isVesAvailablString = getenv("IsVesAvailable");
956 if (isVesAvailablString != NULL)
958 if (strcmp(isVesAvailablString, "false") == 0)
964 value = (const sr_val_t) { 0 };
965 value.type = SR_BOOL_T;
966 value.data.bool_val = isVesAvailable;
967 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/notification-config/is-ves-available",
968 &value, SR_EDIT_DEFAULT);
969 if (SR_ERR_OK != rc) {
970 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
974 rc = is_ves_available_changed(isVesAvailable);
975 if (SR_ERR_OK != rc) {
976 printf("Error by is_ves_available_changed: %s\n", sr_strerror(rc));
980 // setting the values that come in an ENV variable as defaults - ves-endpoint-port
982 int vesEndpointPort = getIntFromString(getenv("VesEndpointPort"), 8080);
984 value = (const sr_val_t) { 0 };
985 value.type = SR_UINT16_T;
986 value.data.uint16_val = vesEndpointPort;
987 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-port",
988 &value, SR_EDIT_DEFAULT);
989 if (SR_ERR_OK != rc) {
990 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
994 rc = ves_port_changed(vesEndpointPort);
995 if (SR_ERR_OK != rc) {
996 printf("Error by ves_port_changed: %s\n", sr_strerror(rc));
1000 // setting the values that come in an ENV variable as defaults - ves-endpoint-ip
1002 value = (const sr_val_t) { 0 };
1003 value.type = SR_STRING_T;
1004 value.data.string_val = getenv("VesEndpointIp");
1005 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-ip",
1006 &value, SR_EDIT_DEFAULT);
1007 if (SR_ERR_OK != rc) {
1008 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1012 rc = ves_ip_changed(getenv("VesEndpointIp"));
1013 if (SR_ERR_OK != rc) {
1014 printf("Error by ves_ip_changed: %s\n", sr_strerror(rc));
1018 // setting the values that come in an ENV variable as defaults - ves-endpoint-auth-method
1020 value = (const sr_val_t) { 0 };
1021 value.type = SR_ENUM_T;
1022 value.data.enum_val = getenv("VesEndpointAuthMethod");
1023 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-auth-method",
1024 &value, SR_EDIT_DEFAULT);
1025 if (SR_ERR_OK != rc) {
1026 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1030 rc = ves_auth_method_changed(getenv("VesEndpointAuthMethod"));
1031 if (SR_ERR_OK != rc) {
1032 printf("Error by ves_auth_method_changed: %s\n", sr_strerror(rc));
1036 //TODO only basic-auth implemented vor VES
1037 if (strcmp(getenv("VesEndpointAuthMethod"), "basic-auth") == 0)
1039 // setting the values that come in an ENV variable as defaults - ves-endpoint-usename
1041 value = (const sr_val_t) { 0 };
1042 value.type = SR_STRING_T;
1043 value.data.string_val = getenv("VesEndpointUsername");
1044 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-username",
1045 &value, SR_EDIT_DEFAULT);
1046 if (SR_ERR_OK != rc) {
1047 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1051 rc = ves_username_changed(getenv("VesEndpointUsername"));
1052 if (SR_ERR_OK != rc) {
1053 printf("Error by ves_username_changed: %s\n", sr_strerror(rc));
1057 // setting the values that come in an ENV variable as defaults - ves-endpoint-password
1059 value = (const sr_val_t) { 0 };
1060 value.type = SR_STRING_T;
1061 value.data.string_val = getenv("VesEndpointPassword");
1062 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-password",
1063 &value, SR_EDIT_DEFAULT);
1064 if (SR_ERR_OK != rc) {
1065 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1069 rc = ves_password_changed(getenv("VesEndpointPassword"));
1070 if (SR_ERR_OK != rc) {
1071 printf("Error by ves_password_changed: %s\n", sr_strerror(rc));
1076 // setting the values that come in an ENV variable as defaults - ves-registration
1078 int vesRegistration = 1;
1080 char *vesRegistrationString = getenv("VesRegistration");
1081 if (vesRegistrationString != NULL)
1083 if (strcmp(vesRegistrationString, "false") == 0)
1085 vesRegistration = 0;
1089 value = (const sr_val_t) { 0 };
1090 value.type = SR_BOOL_T;
1091 value.data.bool_val = vesRegistration;
1092 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-registration",
1093 &value, SR_EDIT_DEFAULT);
1094 if (SR_ERR_OK != rc) {
1095 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1099 rc = ves_registration_changed(vesRegistration);
1100 if (SR_ERR_OK != rc) {
1101 printf("Error by ves_registration_changed: %s\n", sr_strerror(rc));
1105 // setting the values that come in an ENV variable as defaults - ssh-connections
1107 int sshConnections = getIntFromString(getenv("SshConnections"), 1);
1109 rc = ssh_connections_changed(sshConnections);
1110 if (SR_ERR_OK != rc) {
1111 printf("Error by ssh_connections_changed: %s\n", sr_strerror(rc));
1115 // setting the values that come in an ENV variable as defaults - tls-connections
1117 int tlsConnections = getIntFromString(getenv("TlsConnections"), 0);
1119 rc = tls_connections_changed(tlsConnections);
1120 if (SR_ERR_OK != rc) {
1121 printf("Error by tls_connections_changed: %s\n", sr_strerror(rc));
1125 if (strcmp(getenv("K8S_DEPLOYMENT"), "true") == 0)
1127 rc = send_k8s_extend_port();
1128 if (rc != SR_ERR_OK)
1130 printf("Could not send the number of ports to k8s cluster\n");
1134 // setting the values that come in an ENV variable as defaults - controller-ip
1136 value = (const sr_val_t) { 0 };
1137 value.type = SR_STRING_T;
1138 value.data.string_val = getenv("ControllerIp");
1139 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-ip",
1140 &value, SR_EDIT_DEFAULT);
1141 if (SR_ERR_OK != rc) {
1142 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1146 rc = controller_ip_changed(getenv("ControllerIp"));
1147 if (SR_ERR_OK != rc) {
1148 printf("Error by controller_ip_changed: %s\n", sr_strerror(rc));
1152 // setting the values that come in an ENV variable as defaults - controller-port
1154 int controllerPort = getIntFromString(getenv("ControllerPort"), 8181);
1156 value = (const sr_val_t) { 0 };
1157 value.type = SR_UINT16_T;
1158 value.data.uint16_val = controllerPort;
1159 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-port",
1160 &value, SR_EDIT_DEFAULT);
1161 if (SR_ERR_OK != rc) {
1162 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1166 rc = controller_port_changed(controllerPort);
1167 if (SR_ERR_OK != rc) {
1168 printf("Error by controller_port_changed: %s\n", sr_strerror(rc));
1172 // setting the values that come in an ENV variable as defaults - netconf-call-home-port
1174 int netconfCallHomePort = getIntFromString(getenv("NetconfCallHomePort"), 6666);
1176 value = (const sr_val_t) { 0 };
1177 value.type = SR_UINT16_T;
1178 value.data.uint16_val = netconfCallHomePort;
1179 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/netconf-call-home-port",
1180 &value, SR_EDIT_DEFAULT);
1181 if (SR_ERR_OK != rc) {
1182 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1186 rc = controller_netconf_call_home_port_changed(netconfCallHomePort);
1187 if (SR_ERR_OK != rc) {
1188 printf("Error by controller_netconf_call_home_port_changed: %s\n", sr_strerror(rc));
1192 // setting the values that come in an ENV variable as defaults - controller-username
1194 value = (const sr_val_t) { 0 };
1195 value.type = SR_STRING_T;
1196 value.data.string_val = getenv("ControllerUsername");
1197 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-username",
1198 &value, SR_EDIT_DEFAULT);
1199 if (SR_ERR_OK != rc) {
1200 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1204 rc = controller_username_changed(getenv("ControllerUsername"));
1205 if (SR_ERR_OK != rc) {
1206 printf("Error by controller_username_changed: %s\n", sr_strerror(rc));
1210 // setting the values that come in an ENV variable as defaults - controller-password
1212 value = (const sr_val_t) { 0 };
1213 value.type = SR_STRING_T;
1214 value.data.string_val = getenv("ControllerPassword");
1215 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-password",
1216 &value, SR_EDIT_DEFAULT);
1217 if (SR_ERR_OK != rc) {
1218 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1222 rc = controller_password_changed(getenv("ControllerPassword"));
1223 if (SR_ERR_OK != rc) {
1224 printf("Error by controller_password_changed: %s\n", sr_strerror(rc));
1228 // setting the values that come in an ENV variable as defaults - netconf-call-home
1230 int netconfCallHome = 1;
1232 char *netconfCallHomeString = getenv("NetconfCallHome");
1233 if (netconfCallHomeString != NULL)
1235 if (strcmp(netconfCallHomeString, "false") == 0)
1237 netconfCallHome = 0;
1241 value = (const sr_val_t) { 0 };
1242 value.type = SR_BOOL_T;
1243 value.data.bool_val = netconfCallHome;
1244 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/netconf-call-home",
1245 &value, SR_EDIT_DEFAULT);
1246 if (SR_ERR_OK != rc) {
1247 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1251 rc = netconf_call_home_changed(netconfCallHome);
1252 if (SR_ERR_OK != rc) {
1253 printf("Error by netconf_call_home_changed: %s\n", sr_strerror(rc));
1257 //commit the changes that we have done until now
1258 rc = sr_commit(session);
1259 if (SR_ERR_OK != rc) {
1260 printf("Error by sr_commit: %s\n", sr_strerror(rc));
1264 /* read startup config */
1265 printf("\n\n ========== READING STARTUP CONFIG network-topology-simulator: ==========\n\n");
1266 print_current_config(session, "network-topology-simulator");
1268 /* subscribe for changes in running config */
1269 rc = sr_module_change_subscribe(session, "network-topology-simulator", simulator_config_change_cb, NULL,
1270 0, SR_SUBSCR_DEFAULT | SR_SUBSCR_APPLY_ONLY, &subscription);
1271 if (SR_ERR_OK != rc) {
1272 fprintf(stderr, "Error by sr_module_change_subscribe: %s\n", sr_strerror(rc));
1276 /* subscribe as state data provider for the ntsimulator state data */
1277 rc = sr_dp_get_items_subscribe(session, "/network-topology-simulator:simulator-status", simulator_status_cb, NULL,
1278 SR_SUBSCR_CTX_REUSE, &subscription);
1279 if (rc != SR_ERR_OK) {
1283 rc = notification_delay_period_changed(NULL, 0);
1284 if (rc != SR_ERR_OK) {
1285 printf("Could not write the delay period to file!\n");
1289 rc = _init_curl_odl();
1290 if (rc != SR_ERR_OK)
1292 fprintf(stderr, "Could not initialize cURL for ODL connection: %s\n", sr_strerror(rc));
1295 rc = sr_rpc_subscribe(session, "/network-topology-simulator:add-key-pair-to-odl", odl_add_key_pair_cb, (void *)session,
1296 SR_SUBSCR_CTX_REUSE, &subscription);
1298 printf("\n\n ========== STARTUP CONFIG network-topology-simulator APPLIED AS RUNNING ==========\n\n");
1300 rc = writeSkeletonStatusFile();
1301 if (rc != SR_ERR_OK)
1303 fprintf(stderr, "Could not initialize status JSON file: %s\n", sr_strerror(rc));
1306 rc = sr_rpc_subscribe(session, "/network-topology-simulator:invoke-notification", invoke_notification_cb,
1307 (void *)session, SR_SUBSCR_DEFAULT, &subscription);
1308 if (SR_ERR_OK != rc) {
1309 fprintf(stderr, "Error by sr_rpc_subscribe: %s\n", sr_strerror(rc));
1313 rc = pull_docker_image_of_simulated_device();
1315 /* loop until ctrl-c is pressed / SIGINT is received */
1316 signal(SIGINT, sigint_handler);
1317 signal(SIGTERM, sigint_handler);
1318 signal(SIGPIPE, SIG_IGN);
1320 while (!exit_application) {
1322 sleep(1); /* or do some more useful work... */
1325 printf("Application exit requested, exiting.\n");
1328 if (NULL != subscription) {
1329 sr_unsubscribe(session, subscription);
1331 if (NULL != session) {
1332 sr_session_stop(session);
1334 if (NULL != connection) {
1335 sr_disconnect(connection);
1338 clean_current_docker_configuration();
1339 rc = cleanup_curl();
1340 rc = cleanup_curl_odl();
1341 rc = cleanup_curl_k8s();
1346 static void clean_current_docker_configuration(void)
1348 if (strcmp(getenv("K8S_DEPLOYMENT"), "true"))
1353 printf("Cleaning docker containers...\n");
1355 if (device_list == NULL)
1360 for (int i = 0; i < simulated_devices_config; ++i)
1362 stop_device(device_list);
1365 printf("Cleaning completed!\n");