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/netconf-call-home", &val);
359 if (rc != SR_ERR_OK) {
363 rc = netconf_call_home_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/controller-details/controller-ip", &val);
373 if (rc != SR_ERR_OK) {
377 rc = controller_ip_changed(val->data.string_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/controller-details/controller-port", &val);
387 if (rc != SR_ERR_OK) {
391 rc = controller_port_changed(val->data.uint16_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/controller-details/netconf-call-home-port", &val);
401 if (rc != SR_ERR_OK) {
405 rc = controller_netconf_call_home_port_changed(val->data.uint16_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-username", &val);
415 if (rc != SR_ERR_OK) {
419 rc = controller_username_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-password", &val);
429 if (rc != SR_ERR_OK) {
433 rc = controller_password_changed(val->data.string_val);
434 if (rc != SR_ERR_OK) {
444 printf("NTSimulator config change callback failed: %s.", sr_strerror(rc));
454 simulator_status_cb(const char *xpath, sr_val_t **values, size_t *values_cnt,
455 uint64_t request_id, const char *original_xpath, void *private_ctx)
459 // printf("\n\n ========== Called simulator_status_cb for xpath: %s ==========\n\n", xpath);
461 counterAlarms ves_counter, netconf_counter;
462 rc = compute_notifications_count(&ves_counter, &netconf_counter);
465 printf("Could not compute the total number of notification count.\n");
468 if (sr_xpath_node_name_eq(xpath, "simulated-devices-list"))
471 size_t current_num_of_values= 0;
473 if (simulated_devices_config == 0) //nothing to return if no devices are running
481 rc = get_docker_containers_operational_state_curl(device_list);
484 printf("Could not get the operational state for the devices simulated.\n");
485 return SR_ERR_OPERATION_FAILED;
488 device_t *current_device = device_list->head;
490 while (current_device != NULL)
492 counterAlarms vesCount, netconfCount;
493 rc = getDeviceCounters(current_device->device_id, &vesCount, &netconfCount);
496 printf("Could not get Notification Counters for device with uuid=\"%s\"", current_device->device_id);
499 CREATE_NEW_VALUE(rc, v, current_num_of_values);
501 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "device-ip");
502 v[current_num_of_values - 1].type = SR_STRING_T;
503 v[current_num_of_values - 1].data.string_val = getenv("NTS_IP");
505 for (int i = 0; i < NETCONF_CONNECTIONS_PER_DEVICE; ++i)
507 CREATE_NEW_VALUE(rc, v, current_num_of_values);
509 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "device-port");
510 v[current_num_of_values - 1].type = SR_UINT32_T;
511 v[current_num_of_values - 1].data.uint32_val = current_device->netconf_port + i;
514 CREATE_NEW_VALUE(rc, v, current_num_of_values);
516 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "is-mounted");
517 v[current_num_of_values - 1].type = SR_BOOL_T;
518 v[current_num_of_values - 1].data.bool_val = current_device->is_mounted;
520 char *operational_state = get_docker_container_operational_state(device_list, current_device->device_id);
522 CREATE_NEW_VALUE(rc, v, current_num_of_values);
524 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "operational-state");
525 sr_val_build_str_data(&v[current_num_of_values - 1], SR_ENUM_T, "%s", operational_state);
527 CREATE_NEW_VALUE(rc, v, current_num_of_values);
529 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "normal");
530 v[current_num_of_values - 1].type = SR_UINT32_T;
531 v[current_num_of_values - 1].data.uint32_val = vesCount.normal;
533 CREATE_NEW_VALUE(rc, v, current_num_of_values);
535 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "warning");
536 v[current_num_of_values - 1].type = SR_UINT32_T;
537 v[current_num_of_values - 1].data.uint32_val = vesCount.warning;
539 CREATE_NEW_VALUE(rc, v, current_num_of_values);
541 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "minor");
542 v[current_num_of_values - 1].type = SR_UINT32_T;
543 v[current_num_of_values - 1].data.uint32_val = vesCount.minor;
545 CREATE_NEW_VALUE(rc, v, current_num_of_values);
547 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "major");
548 v[current_num_of_values - 1].type = SR_UINT32_T;
549 v[current_num_of_values - 1].data.uint32_val = vesCount.major;
551 CREATE_NEW_VALUE(rc, v, current_num_of_values);
553 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "critical");
554 v[current_num_of_values - 1].type = SR_UINT32_T;
555 v[current_num_of_values - 1].data.uint32_val = vesCount.critical;
557 CREATE_NEW_VALUE(rc, v, current_num_of_values);
559 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "normal");
560 v[current_num_of_values - 1].type = SR_UINT32_T;
561 v[current_num_of_values - 1].data.uint32_val = netconfCount.normal;
563 CREATE_NEW_VALUE(rc, v, current_num_of_values);
565 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "warning");
566 v[current_num_of_values - 1].type = SR_UINT32_T;
567 v[current_num_of_values - 1].data.uint32_val = netconfCount.warning;
569 CREATE_NEW_VALUE(rc, v, current_num_of_values);
571 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "minor");
572 v[current_num_of_values - 1].type = SR_UINT32_T;
573 v[current_num_of_values - 1].data.uint32_val = netconfCount.minor;
575 CREATE_NEW_VALUE(rc, v, current_num_of_values);
577 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "major");
578 v[current_num_of_values - 1].type = SR_UINT32_T;
579 v[current_num_of_values - 1].data.uint32_val = netconfCount.major;
581 CREATE_NEW_VALUE(rc, v, current_num_of_values);
583 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "critical");
584 v[current_num_of_values - 1].type = SR_UINT32_T;
585 v[current_num_of_values - 1].data.uint32_val = netconfCount.critical;
587 current_device = current_device->next;
590 //return the values that we have just created
592 *values_cnt = current_num_of_values;
594 else if (sr_xpath_node_name_eq(xpath, "simulation-usage-details"))
596 float cpu_usage = 0.0, mem_usage = 0.0;
598 char *resource_usage_from_script = get_docker_container_resource_stats();
600 if (resource_usage_from_script != NULL)
602 printf("Received line: %s\n", resource_usage_from_script);
603 sscanf(resource_usage_from_script, "CPU=%f%%;RAM=%fMiB", &cpu_usage, &mem_usage);
604 printf("Read cpu=\"%f\" and mem=\"%f\"\n", cpu_usage, mem_usage);
605 free(resource_usage_from_script);
609 /* convenient functions such as this can be found in sysrepo/values.h */
610 size_t current_num_of_values= 0;
612 CREATE_NEW_VALUE(rc, v, current_num_of_values);
614 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "running-simulated-devices");
615 v[current_num_of_values - 1].type = SR_UINT32_T;
616 v[current_num_of_values - 1].data.uint32_val = get_current_number_of_devices(device_list);
618 CREATE_NEW_VALUE(rc, v, current_num_of_values);
620 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "running-mounted-devices");
621 v[current_num_of_values - 1].type = SR_UINT32_T;
622 v[current_num_of_values - 1].data.uint32_val = get_current_number_of_mounted_devices(device_list);
624 CREATE_NEW_VALUE(rc, v, current_num_of_values);
626 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "base-netconf-port");
627 v[current_num_of_values - 1].type = SR_UINT32_T;
628 v[current_num_of_values - 1].data.uint32_val = get_netconf_port_base();
630 CREATE_NEW_VALUE(rc, v, current_num_of_values);
632 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "cpu-usage");
633 v[current_num_of_values - 1].type = SR_DECIMAL64_T;
634 v[current_num_of_values - 1].data.decimal64_val = cpu_usage;
636 CREATE_NEW_VALUE(rc, v, current_num_of_values);
638 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "mem-usage");
639 v[current_num_of_values - 1].type = SR_UINT32_T;
640 v[current_num_of_values - 1].data.uint32_val = (int)mem_usage;
642 CREATE_NEW_VALUE(rc, v, current_num_of_values);
644 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "ssh-connections");
645 v[current_num_of_values - 1].type = SR_UINT32_T;
646 v[current_num_of_values - 1].data.uint32_val = getSshConnectionsFromConfigJson();
648 CREATE_NEW_VALUE(rc, v, current_num_of_values);
650 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "tls-connections");
651 v[current_num_of_values - 1].type = SR_UINT32_T;
652 v[current_num_of_values - 1].data.uint32_val = getTlsConnectionsFromConfigJson();
654 //return the values that we have just created
656 *values_cnt = current_num_of_values;
658 else if (sr_xpath_node_name_eq(xpath, "total-ves-notifications"))
661 /* convenient functions such as this can be found in sysrepo/values.h */
662 size_t current_num_of_values= 0;
664 CREATE_NEW_VALUE(rc, v, current_num_of_values);
666 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "normal");
667 v[current_num_of_values - 1].type = SR_UINT32_T;
668 v[current_num_of_values - 1].data.uint32_val = ves_counter.normal;
670 CREATE_NEW_VALUE(rc, v, current_num_of_values);
672 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "warning");
673 v[current_num_of_values - 1].type = SR_UINT32_T;
674 v[current_num_of_values - 1].data.uint32_val = ves_counter.warning;
676 CREATE_NEW_VALUE(rc, v, current_num_of_values);
678 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "minor");
679 v[current_num_of_values - 1].type = SR_UINT32_T;
680 v[current_num_of_values - 1].data.uint32_val = ves_counter.minor;
682 CREATE_NEW_VALUE(rc, v, current_num_of_values);
684 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "major");
685 v[current_num_of_values - 1].type = SR_UINT32_T;
686 v[current_num_of_values - 1].data.uint32_val = ves_counter.major;
688 CREATE_NEW_VALUE(rc, v, current_num_of_values);
690 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "critical");
691 v[current_num_of_values - 1].type = SR_UINT32_T;
692 v[current_num_of_values - 1].data.uint32_val = ves_counter.critical;
694 //return the values that we have just created
696 *values_cnt = current_num_of_values;
698 else if (sr_xpath_node_name_eq(xpath, "total-netconf-notifications"))
701 /* convenient functions such as this can be found in sysrepo/values.h */
702 size_t current_num_of_values= 0;
704 CREATE_NEW_VALUE(rc, v, current_num_of_values);
706 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "normal");
707 v[current_num_of_values - 1].type = SR_UINT32_T;
708 v[current_num_of_values - 1].data.uint32_val = netconf_counter.normal;
710 CREATE_NEW_VALUE(rc, v, current_num_of_values);
712 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "warning");
713 v[current_num_of_values - 1].type = SR_UINT32_T;
714 v[current_num_of_values - 1].data.uint32_val = netconf_counter.warning;
716 CREATE_NEW_VALUE(rc, v, current_num_of_values);
718 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "minor");
719 v[current_num_of_values - 1].type = SR_UINT32_T;
720 v[current_num_of_values - 1].data.uint32_val = netconf_counter.minor;
722 CREATE_NEW_VALUE(rc, v, current_num_of_values);
724 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "major");
725 v[current_num_of_values - 1].type = SR_UINT32_T;
726 v[current_num_of_values - 1].data.uint32_val = netconf_counter.major;
728 CREATE_NEW_VALUE(rc, v, current_num_of_values);
730 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "critical");
731 v[current_num_of_values - 1].type = SR_UINT32_T;
732 v[current_num_of_values - 1].data.uint32_val = netconf_counter.critical;
734 //return the values that we have just created
736 *values_cnt = current_num_of_values;
742 static int odl_add_key_pair_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
743 sr_val_t **output, size_t *output_cnt, void *private_ctx)
746 controller_t controller_list[CONTROLLER_LIST_MAX_LEN];
747 int controller_list_size = 0;
749 controller_list[0] = controller_details;
750 controller_list_size++;
752 for (int i = 0; i < controller_list_size; ++i)
754 printf("%d iteration: Got back url=%s and credentials=%s\n", i, controller_list[i].url, controller_list[i].credentials);
757 rc = add_key_pair_to_odl(controller_list, controller_list_size);
760 printf("Failed to add key pair to ODL.\n");
761 return SR_ERR_OPERATION_FAILED;
767 static int invoke_notification_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
768 sr_val_t **output, size_t *output_cnt, void *private_ctx)
772 char *device_name = NULL, *module_name = NULL, *notification_object = NULL;
774 /* print input values */
775 printf("\n\n ========== RECEIVED RPC REQUEST ==========\n\n");
776 printf(">>> RPC Input:\n\n");
778 device_name = strdup(input[0].data.string_val);
779 module_name = strdup(input[1].data.string_val);
780 notification_object = strdup(input[2].data.string_val);
782 rc = sr_new_values(1, output);
783 if (SR_ERR_OK != rc) {
787 /* set 'output/step-count' leaf */
788 rc = sr_val_set_xpath(&(*output)[0], "/network-topology-simulator:invoke-notification/status");
789 if (SR_ERR_OK != rc) {
793 rc = invoke_device_notification(device_name, module_name, notification_object);
797 sr_val_build_str_data(&(*output)[0], SR_ENUM_T, "%s", "ERROR");
801 sr_val_build_str_data(&(*output)[0], SR_ENUM_T, "%s", "SUCCESS");
810 sigint_handler(int signum)
812 exit_application = 1;
816 main(int argc, char **argv)
818 sr_conn_ctx_t *connection = NULL;
819 sr_session_ctx_t *session = NULL;
820 sr_subscription_ctx_t *subscription = NULL;
823 setbuf(stdout, NULL);
825 rc = _init_curl_k8s();
828 fprintf(stderr, "Could not initialize cURL for K8S connection: %s\n", sr_strerror(rc));
831 device_list = new_device_stack();
835 fprintf(stderr, "Could not initialize cURL: %s\n", sr_strerror(rc));
838 rc = writeSkeletonConfigFile();
841 fprintf(stderr, "Could not initialize configuration JSON file: %s\n", sr_strerror(rc));
844 /* connect to sysrepo */
845 rc = sr_connect("network-topology-simulator", SR_CONN_DEFAULT, &connection);
846 if (SR_ERR_OK != rc) {
847 fprintf(stderr, "Error by sr_connect: %s\n", sr_strerror(rc));
852 rc = sr_session_start(connection, SR_DS_STARTUP, SR_SESS_DEFAULT, &session);
853 if (SR_ERR_OK != rc) {
854 fprintf(stderr, "Error by sr_session_start: %s\n", sr_strerror(rc));
858 // setting the values that come in an ENV variable as defaults - ves-heartbeat-period
859 int vesHeartbeatPeriod = getIntFromString(getenv("VesHeartbeatPeriod"), 0);
861 sr_val_t value = { 0 };
862 value.type = SR_UINT32_T;
863 value.data.uint32_val = vesHeartbeatPeriod;
864 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/notification-config/ves-heartbeat-period",
865 &value, SR_EDIT_DEFAULT);
866 if (SR_ERR_OK != rc) {
867 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
871 rc = ves_heartbeat_period_changed(vesHeartbeatPeriod);
872 if (SR_ERR_OK != rc) {
873 printf("Error by ves_heartbeat_period_changed: %s\n", sr_strerror(rc));
877 // setting the values that come in an ENV variable as defaults - is-netconf-available
879 int isNetconfAvailable = 1;
881 char *isNetconfAvailablString = getenv("IsNetconfAvailable");
882 if (isNetconfAvailablString != NULL)
884 if (strcmp(isNetconfAvailablString, "false") == 0)
886 isNetconfAvailable = 0;
890 value = (const sr_val_t) { 0 };
891 value.type = SR_BOOL_T;
892 value.data.bool_val = isNetconfAvailable;
893 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/notification-config/is-netconf-available",
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 = is_netconf_available_changed(isNetconfAvailable);
901 if (SR_ERR_OK != rc) {
902 printf("Error by is_netconf_available_changed: %s\n", sr_strerror(rc));
906 // setting the values that come in an ENV variable as defaults - is-ves-available
908 int isVesAvailable = 1;
910 char *isVesAvailablString = getenv("IsVesAvailable");
911 if (isVesAvailablString != NULL)
913 if (strcmp(isVesAvailablString, "false") == 0)
919 value = (const sr_val_t) { 0 };
920 value.type = SR_BOOL_T;
921 value.data.bool_val = isVesAvailable;
922 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/notification-config/is-ves-available",
923 &value, SR_EDIT_DEFAULT);
924 if (SR_ERR_OK != rc) {
925 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
929 rc = is_ves_available_changed(isVesAvailable);
930 if (SR_ERR_OK != rc) {
931 printf("Error by is_ves_available_changed: %s\n", sr_strerror(rc));
935 // setting the values that come in an ENV variable as defaults - ves-endpoint-port
937 int vesEndpointPort = getIntFromString(getenv("VesEndpointPort"), 8080);
939 value = (const sr_val_t) { 0 };
940 value.type = SR_UINT16_T;
941 value.data.uint16_val = vesEndpointPort;
942 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-port",
943 &value, SR_EDIT_DEFAULT);
944 if (SR_ERR_OK != rc) {
945 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
949 rc = ves_port_changed(vesEndpointPort);
950 if (SR_ERR_OK != rc) {
951 printf("Error by ves_port_changed: %s\n", sr_strerror(rc));
955 // setting the values that come in an ENV variable as defaults - ves-endpoint-ip
957 value = (const sr_val_t) { 0 };
958 value.type = SR_STRING_T;
959 value.data.string_val = getenv("VesEndpointIp");
960 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-ip",
961 &value, SR_EDIT_DEFAULT);
962 if (SR_ERR_OK != rc) {
963 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
967 rc = ves_ip_changed(getenv("VesEndpointIp"));
968 if (SR_ERR_OK != rc) {
969 printf("Error by ves_ip_changed: %s\n", sr_strerror(rc));
973 // setting the values that come in an ENV variable as defaults - ssh-connections
975 int sshConnections = getIntFromString(getenv("SshConnections"), 1);
977 rc = ssh_connections_changed(sshConnections);
978 if (SR_ERR_OK != rc) {
979 printf("Error by ssh_connections_changed: %s\n", sr_strerror(rc));
983 // setting the values that come in an ENV variable as defaults - tls-connections
985 int tlsConnections = getIntFromString(getenv("TlsConnections"), 0);
987 rc = tls_connections_changed(tlsConnections);
988 if (SR_ERR_OK != rc) {
989 printf("Error by tls_connections_changed: %s\n", sr_strerror(rc));
993 if (strcmp(getenv("K8S_DEPLOYMENT"), "true") == 0)
995 rc = send_k8s_extend_port();
998 printf("Could not send the number of ports to k8s cluster\n");
1002 // setting the values that come in an ENV variable as defaults - controller-ip
1004 value = (const sr_val_t) { 0 };
1005 value.type = SR_STRING_T;
1006 value.data.string_val = getenv("ControllerIp");
1007 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-ip",
1008 &value, SR_EDIT_DEFAULT);
1009 if (SR_ERR_OK != rc) {
1010 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1014 rc = controller_ip_changed(getenv("ControllerIp"));
1015 if (SR_ERR_OK != rc) {
1016 printf("Error by controller_ip_changed: %s\n", sr_strerror(rc));
1020 // setting the values that come in an ENV variable as defaults - controller-port
1022 int controllerPort = getIntFromString(getenv("ControllerPort"), 8181);
1024 value = (const sr_val_t) { 0 };
1025 value.type = SR_UINT16_T;
1026 value.data.uint16_val = controllerPort;
1027 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-port",
1028 &value, SR_EDIT_DEFAULT);
1029 if (SR_ERR_OK != rc) {
1030 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1034 rc = controller_port_changed(controllerPort);
1035 if (SR_ERR_OK != rc) {
1036 printf("Error by controller_port_changed: %s\n", sr_strerror(rc));
1040 // setting the values that come in an ENV variable as defaults - netconf-call-home-port
1042 int netconfCallHomePort = getIntFromString(getenv("NetconfCallHomePort"), 6666);
1044 value = (const sr_val_t) { 0 };
1045 value.type = SR_UINT16_T;
1046 value.data.uint16_val = netconfCallHomePort;
1047 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/netconf-call-home-port",
1048 &value, SR_EDIT_DEFAULT);
1049 if (SR_ERR_OK != rc) {
1050 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1054 rc = controller_netconf_call_home_port_changed(netconfCallHomePort);
1055 if (SR_ERR_OK != rc) {
1056 printf("Error by controller_netconf_call_home_port_changed: %s\n", sr_strerror(rc));
1060 // setting the values that come in an ENV variable as defaults - controller-username
1062 value = (const sr_val_t) { 0 };
1063 value.type = SR_STRING_T;
1064 value.data.string_val = getenv("ControllerUsername");
1065 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-username",
1066 &value, SR_EDIT_DEFAULT);
1067 if (SR_ERR_OK != rc) {
1068 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1072 rc = controller_username_changed(getenv("ControllerUsername"));
1073 if (SR_ERR_OK != rc) {
1074 printf("Error by controller_username_changed: %s\n", sr_strerror(rc));
1078 // setting the values that come in an ENV variable as defaults - controller-password
1080 value = (const sr_val_t) { 0 };
1081 value.type = SR_STRING_T;
1082 value.data.string_val = getenv("ControllerPassword");
1083 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-password",
1084 &value, SR_EDIT_DEFAULT);
1085 if (SR_ERR_OK != rc) {
1086 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1090 rc = controller_password_changed(getenv("ControllerPassword"));
1091 if (SR_ERR_OK != rc) {
1092 printf("Error by controller_password_changed: %s\n", sr_strerror(rc));
1096 // setting the values that come in an ENV variable as defaults - netconf-call-home
1098 int netconfCallHome = 1;
1100 char *netconfCallHomeString = getenv("NetconfCallHome");
1101 if (netconfCallHomeString != NULL)
1103 if (strcmp(netconfCallHomeString, "false") == 0)
1105 netconfCallHome = 0;
1109 value = (const sr_val_t) { 0 };
1110 value.type = SR_BOOL_T;
1111 value.data.bool_val = netconfCallHome;
1112 rc = sr_set_item(session, "/network-topology-simulator:simulator-config/netconf-call-home",
1113 &value, SR_EDIT_DEFAULT);
1114 if (SR_ERR_OK != rc) {
1115 printf("Error by sr_set_item: %s\n", sr_strerror(rc));
1119 rc = netconf_call_home_changed(netconfCallHome);
1120 if (SR_ERR_OK != rc) {
1121 printf("Error by netconf_call_home_changed: %s\n", sr_strerror(rc));
1125 //commit the changes that we have done until now
1126 rc = sr_commit(session);
1127 if (SR_ERR_OK != rc) {
1128 printf("Error by sr_commit: %s\n", sr_strerror(rc));
1132 /* read startup config */
1133 printf("\n\n ========== READING STARTUP CONFIG network-topology-simulator: ==========\n\n");
1134 print_current_config(session, "network-topology-simulator");
1136 /* subscribe for changes in running config */
1137 rc = sr_module_change_subscribe(session, "network-topology-simulator", simulator_config_change_cb, NULL,
1138 0, SR_SUBSCR_DEFAULT | SR_SUBSCR_APPLY_ONLY, &subscription);
1139 if (SR_ERR_OK != rc) {
1140 fprintf(stderr, "Error by sr_module_change_subscribe: %s\n", sr_strerror(rc));
1144 /* subscribe as state data provider for the ntsimulator state data */
1145 rc = sr_dp_get_items_subscribe(session, "/network-topology-simulator:simulator-status", simulator_status_cb, NULL,
1146 SR_SUBSCR_CTX_REUSE, &subscription);
1147 if (rc != SR_ERR_OK) {
1151 rc = notification_delay_period_changed(NULL, 0);
1152 if (rc != SR_ERR_OK) {
1153 printf("Could not write the delay period to file!\n");
1157 rc = _init_curl_odl();
1158 if (rc != SR_ERR_OK)
1160 fprintf(stderr, "Could not initialize cURL for ODL connection: %s\n", sr_strerror(rc));
1163 rc = sr_rpc_subscribe(session, "/network-topology-simulator:add-key-pair-to-odl", odl_add_key_pair_cb, (void *)session,
1164 SR_SUBSCR_CTX_REUSE, &subscription);
1166 printf("\n\n ========== STARTUP CONFIG network-topology-simulator APPLIED AS RUNNING ==========\n\n");
1168 rc = writeSkeletonStatusFile();
1169 if (rc != SR_ERR_OK)
1171 fprintf(stderr, "Could not initialize status JSON file: %s\n", sr_strerror(rc));
1174 rc = sr_rpc_subscribe(session, "/network-topology-simulator:invoke-notification", invoke_notification_cb,
1175 (void *)session, SR_SUBSCR_DEFAULT, &subscription);
1176 if (SR_ERR_OK != rc) {
1177 fprintf(stderr, "Error by sr_rpc_subscribe: %s\n", sr_strerror(rc));
1181 rc = pull_docker_image_of_simulated_device();
1183 /* loop until ctrl-c is pressed / SIGINT is received */
1184 signal(SIGINT, sigint_handler);
1185 signal(SIGTERM, sigint_handler);
1186 signal(SIGPIPE, SIG_IGN);
1188 while (!exit_application) {
1190 sleep(1); /* or do some more useful work... */
1193 printf("Application exit requested, exiting.\n");
1196 if (NULL != subscription) {
1197 sr_unsubscribe(session, subscription);
1199 if (NULL != session) {
1200 sr_session_stop(session);
1202 if (NULL != connection) {
1203 sr_disconnect(connection);
1206 clean_current_docker_configuration();
1207 rc = cleanup_curl();
1208 rc = cleanup_curl_odl();
1209 rc = cleanup_curl_k8s();
1214 static void clean_current_docker_configuration(void)
1216 if (strcmp(getenv("K8S_DEPLOYMENT"), "true"))
1221 printf("Cleaning docker containers...\n");
1223 if (device_list == NULL)
1228 for (int i = 0; i < simulated_devices_config; ++i)
1230 stop_device(device_list);
1233 printf("Cleaning completed!\n");