ea120c7f19cfcfea099b3bc48cd647f573cff539
[sim/o1-interface.git] / ntsimulator / src / ntsimulator-manager / ntsimulator-manager.c
1 /*************************************************************************
2 *
3 * Copyright 2019 highstreet technologies GmbH and others
4 *
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
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
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 ***************************************************************************/
17
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <signal.h>
23 #include <inttypes.h>
24 #include <limits.h>
25 #include <string.h>
26
27 #include "sysrepo.h"
28 #include "sysrepo/values.h"
29
30 #include "utils.h"
31 #include "simulator-operations.h"
32
33 volatile int exit_application = 0;
34
35 volatile unsigned int simulated_devices_config = 0;
36 volatile unsigned int mounted_devices_config = 0;
37
38
39 static device_stack_t *device_list = NULL;
40
41 controller_t controller_details;
42
43 #define XPATH_MAX_LEN 500
44 #define CONTROLLER_LIST_MAX_LEN 1
45
46 static void
47 print_current_config(sr_session_ctx_t *session, const char *module_name)
48 {
49     sr_val_t *values = NULL;
50     size_t count = 0;
51     int rc = SR_ERR_OK;
52     char xpath[XPATH_MAX_LEN] = {0};
53     snprintf(xpath, XPATH_MAX_LEN, "/%s:*//.", module_name);
54
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;
59
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));
63         return;
64     }
65     for (size_t i = 0; i < count; i++){
66
67         sr_print_val(&values[i]);
68
69         if (sr_xpath_node_name_eq(values[i].xpath, "controller-ip"))
70         {
71                 rc = sr_dup_val(&values[i], &odl_ip);
72         }
73         else if (sr_xpath_node_name_eq(values[i].xpath, "controller-port"))
74         {
75                 rc = sr_dup_val(&values[i], &odl_port);
76         }
77         else if (sr_xpath_node_name_eq(values[i].xpath, "controller-username"))
78         {
79                 rc = sr_dup_val(&values[i], &odl_username);
80         }
81         else if (sr_xpath_node_name_eq(values[i].xpath, "controller-password"))
82         {
83                 rc = sr_dup_val(&values[i], &odl_password);
84         }
85     }
86
87     //URL used for mounting/unmounting a device; the device name needs to be appended
88    char url[URL_AND_CREDENTIALS_MAX_LEN];
89    sprintf(url, "http://%s:%d/restconf/config/network-topology:network-topology/topology/"
90                  "topology-netconf/node/",
91                  odl_ip->data.string_val, odl_port->data.uint32_val);
92
93    char credentials[URL_AND_CREDENTIALS_MAX_LEN];
94    sprintf(credentials, "%s:%s", odl_username->data.string_val, odl_password->data.string_val);
95
96    //URLs used for adding key pair to ODL, for TLS connections
97    char url_for_keystore_add[URL_AND_CREDENTIALS_MAX_LEN];
98    sprintf(url_for_keystore_add, "http://%s:%d/restconf/operations/netconf-keystore:add-keystore-entry",
99                          odl_ip->data.string_val, odl_port->data.uint32_val);
100
101    char url_for_private_key_add[URL_AND_CREDENTIALS_MAX_LEN];
102    sprintf(url_for_private_key_add, "http://%s:%d/restconf/operations/netconf-keystore:add-private-key",
103                          odl_ip->data.string_val, odl_port->data.uint32_val);
104
105    char url_for_trusted_ca_add[URL_AND_CREDENTIALS_MAX_LEN];
106    sprintf(url_for_trusted_ca_add, "http://%s:%d/restconf/operations/netconf-keystore:add-trusted-certificate",
107                          odl_ip->data.string_val, odl_port->data.uint32_val);
108
109    strcpy(controller_details.url, url);
110    strcpy(controller_details.credentials, credentials);
111    strcpy(controller_details.url_for_keystore_add, url_for_keystore_add);
112    strcpy(controller_details.url_for_private_key_add, url_for_private_key_add);
113    strcpy(controller_details.url_for_trusted_ca_add, url_for_trusted_ca_add);
114
115    sr_free_val(odl_ip);
116    sr_free_val(odl_port);
117    sr_free_val(odl_username);
118    sr_free_val(odl_password);
119
120    sr_free_values(values, count);
121 }
122
123 static void clean_current_docker_configuration(void);
124
125 static int simulated_devices_changed(int new_value)
126 {
127         int rc = SR_ERR_OK;
128
129     if (simulated_devices_config > new_value)
130     {
131         //we are configuring less elements that currently
132         for (int i = 0; i < simulated_devices_config - new_value; ++i)
133         {
134                 rc = stop_device(device_list);
135         }
136     }
137     else if (simulated_devices_config < new_value)
138     {
139         //we are configuring more elements that currently
140         for (int i = 0; i < new_value - simulated_devices_config; ++i)
141         {
142                 rc = start_device(device_list);
143         }
144     }
145
146     simulated_devices_config = new_value;
147
148     return rc;
149 }
150
151 int mounted_devices_changed(sr_session_ctx_t *session, int new_value)
152 {
153         int rc = SR_ERR_OK;
154
155         if (mounted_devices_config > new_value)
156         {
157           //we need have less mounted elements
158           for (int i = 0; i < mounted_devices_config - new_value; ++i)
159           {
160                   printf("Sending unmount device...\n");
161                   rc = unmount_device(device_list, controller_details);
162           }
163         }
164         else if (mounted_devices_config < new_value)
165         {
166           //we are configuring more elements that currently
167           for (int i = 0; i < new_value - mounted_devices_config; ++i)
168           {
169                   printf("Sending mount device...\n");
170                   rc = mount_device(device_list, controller_details);
171           }
172         }
173
174         mounted_devices_config = new_value;
175
176     return rc;
177 }
178
179 static int
180 simulator_config_change_cb(sr_session_ctx_t *session, const char *module_name, sr_notif_event_t event, void *private_ctx)
181 {
182         int rc;
183
184     printf("\n\n ========== CONFIG HAS CHANGED, CURRENT RUNNING CONFIG %s: ==========\n\n", module_name);
185     print_current_config(session, module_name);
186
187     sr_val_t *val = NULL;
188
189     /* get the value from sysrepo, we do not care if the value did not change in our case */
190     rc = sr_get_item(session, "/network-topology-simulator:simulator-config/simulated-devices", &val);
191     if (rc != SR_ERR_OK) {
192         goto sr_error;
193     }
194
195     rc = simulated_devices_changed(val->data.uint32_val);
196     if (rc != SR_ERR_OK) {
197         goto sr_error;
198     }
199
200     sr_free_val(val);
201         val = NULL;
202
203     /* get the value from sysrepo, we do not care if the value did not change in our case */
204     rc = sr_get_item(session, "/network-topology-simulator:simulator-config/mounted-devices", &val);
205     if (rc != SR_ERR_OK) {
206         goto sr_error;
207     }
208
209     if (mounted_devices_config != val->data.uint32_val)
210     {
211         if (val->data.uint32_val > simulated_devices_config)
212         {
213                 printf("Cannot set mount value greater than number of simulated devices.\n");
214                 sr_free_val(val);
215                         val = NULL;
216                 return SR_ERR_OK;
217         }
218
219                 rc = mounted_devices_changed(session, val->data.uint32_val);
220                 if (rc != SR_ERR_OK) {
221                         goto sr_error;
222                 }
223     }
224
225     sr_free_val(val);
226         val = NULL;
227
228     size_t count = 0;
229
230     /* get the value from sysrepo, we do not care if the value did not change in our case */
231     rc = sr_get_items(session, "/network-topology-simulator:simulator-config/notification-config/fault-notification-delay-period", &val, &count);
232     if (rc != SR_ERR_OK) {
233         goto sr_error;
234     }
235
236     rc = notification_delay_period_changed(val, count);
237     if (rc != SR_ERR_OK) {
238         goto sr_error;
239     }
240     sr_free_values(val, count);
241         val = NULL;
242
243     /* get the value from sysrepo, we do not care if the value did not change in our case */
244         rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/ves-heartbeat-period", &val);
245         if (rc != SR_ERR_OK) {
246                 goto sr_error;
247         }
248
249         rc = ves_heartbeat_period_changed(val->data.uint32_val);
250         if (rc != SR_ERR_OK) {
251                 goto sr_error;
252         }
253
254         sr_free_val(val);
255         val = NULL;
256
257         /* get the value from sysrepo, we do not care if the value did not change in our case */
258         rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-ip", &val);
259         if (rc != SR_ERR_OK) {
260                 goto sr_error;
261         }
262
263         rc = ves_ip_changed(val->data.string_val);
264         if (rc != SR_ERR_OK) {
265                 goto sr_error;
266         }
267
268         sr_free_val(val);
269         val = NULL;
270
271         /* get the value from sysrepo, we do not care if the value did not change in our case */
272         rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-port", &val);
273         if (rc != SR_ERR_OK) {
274                 goto sr_error;
275         }
276
277         rc = ves_port_changed(val->data.uint16_val);
278         if (rc != SR_ERR_OK) {
279                 goto sr_error;
280         }
281
282         sr_free_val(val);
283         val = NULL;
284
285         /* get the value from sysrepo, we do not care if the value did not change in our case */
286         rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-registration", &val);
287         if (rc != SR_ERR_OK) {
288                 goto sr_error;
289         }
290
291         rc = ves_registration_changed(val->data.bool_val);
292         if (rc != SR_ERR_OK) {
293                 goto sr_error;
294         }
295
296         sr_free_val(val);
297         val = NULL;
298
299         /* get the value from sysrepo, we do not care if the value did not change in our case */
300         rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/is-netconf-available", &val);
301         if (rc != SR_ERR_OK) {
302                 goto sr_error;
303         }
304
305         rc = is_netconf_available_changed(val->data.bool_val);
306         if (rc != SR_ERR_OK) {
307                 goto sr_error;
308         }
309
310         sr_free_val(val);
311         val = NULL;
312
313         /* get the value from sysrepo, we do not care if the value did not change in our case */
314         rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/is-ves-available", &val);
315         if (rc != SR_ERR_OK) {
316                 goto sr_error;
317         }
318
319         rc = is_ves_available_changed(val->data.bool_val);
320         if (rc != SR_ERR_OK) {
321                 goto sr_error;
322         }
323
324         sr_free_val(val);
325         val = NULL;
326
327     return SR_ERR_OK;
328
329 sr_error:
330         printf("NTSimulator config change callback failed: %s.", sr_strerror(rc));
331         if (val != NULL)
332         {
333                 sr_free_val(val);
334                 val = NULL;
335         }
336         return rc;
337 }
338
339 static int
340 simulator_status_cb(const char *xpath, sr_val_t **values, size_t *values_cnt,
341         uint64_t request_id, const char *original_xpath, void *private_ctx)
342 {
343         int rc;
344
345         // printf("\n\n ========== Called simulator_status_cb for xpath: %s ==========\n\n", xpath);
346
347     counterAlarms ves_counter, netconf_counter;
348     rc = compute_notifications_count(&ves_counter, &netconf_counter);
349     if (rc != SR_ERR_OK)
350     {
351         printf("Could not compute the total number of notification count.\n");
352     }
353
354         if (sr_xpath_node_name_eq(xpath, "simulated-devices-list")) {
355                 sr_val_t *v;
356                 size_t current_num_of_values= 0;
357
358                 if (simulated_devices_config == 0) //nothing to return if no devices are running
359                 {
360                         *values = NULL;
361                         *values_cnt = 0;
362
363                         return SR_ERR_OK;
364                 }
365
366                 rc = get_docker_containers_operational_state_curl(device_list);
367                 if (rc != SR_ERR_OK)
368                 {
369                         printf("Could not get the operational state for the devices simulated.\n");
370                         return SR_ERR_OPERATION_FAILED;
371                 }
372
373                 device_t *current_device = device_list->head;
374
375                 while (current_device != NULL)
376                 {
377             counterAlarms vesCount, netconfCount;
378             rc = getDeviceCounters(current_device->device_id, &vesCount, &netconfCount);
379             if (rc != SR_ERR_OK)
380             {
381                 printf("Could not get Notification Counters for device with uuid=\"%s\"", current_device->device_id);
382             }            
383
384                         CREATE_NEW_VALUE(rc, v, current_num_of_values);
385
386                         sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "device-ip");
387                         v[current_num_of_values - 1].type = SR_STRING_T;
388                         v[current_num_of_values - 1].data.string_val = getenv("NTS_IP");
389
390                         for (int i = 0; i < NETCONF_CONNECTIONS_PER_DEVICE; ++i)
391                         {
392                                 CREATE_NEW_VALUE(rc, v, current_num_of_values);
393
394                                 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "device-port");
395                                 v[current_num_of_values - 1].type = SR_UINT32_T;
396                                 v[current_num_of_values - 1].data.uint32_val = current_device->netconf_port + i;
397                         }
398
399                         CREATE_NEW_VALUE(rc, v, current_num_of_values);
400
401                         sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "is-mounted");
402                         v[current_num_of_values - 1].type = SR_BOOL_T;
403                         v[current_num_of_values - 1].data.bool_val = current_device->is_mounted;
404
405                         char *operational_state = get_docker_container_operational_state(device_list, current_device->device_id);
406
407                         CREATE_NEW_VALUE(rc, v, current_num_of_values);
408
409                         sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "operational-state");
410                         sr_val_build_str_data(&v[current_num_of_values - 1], SR_ENUM_T, "%s", operational_state);
411
412             CREATE_NEW_VALUE(rc, v, current_num_of_values);
413
414             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "normal");
415             v[current_num_of_values - 1].type = SR_UINT32_T;
416             v[current_num_of_values - 1].data.uint32_val = vesCount.normal;
417
418             CREATE_NEW_VALUE(rc, v, current_num_of_values);
419
420             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "warning");
421             v[current_num_of_values - 1].type = SR_UINT32_T;
422             v[current_num_of_values - 1].data.uint32_val = vesCount.warning;
423
424             CREATE_NEW_VALUE(rc, v, current_num_of_values);
425
426             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "minor");
427             v[current_num_of_values - 1].type = SR_UINT32_T;
428             v[current_num_of_values - 1].data.uint32_val = vesCount.minor;
429
430             CREATE_NEW_VALUE(rc, v, current_num_of_values);
431
432             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "major");
433             v[current_num_of_values - 1].type = SR_UINT32_T;
434             v[current_num_of_values - 1].data.uint32_val = vesCount.major;
435
436             CREATE_NEW_VALUE(rc, v, current_num_of_values);
437
438             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "critical");
439             v[current_num_of_values - 1].type = SR_UINT32_T;
440             v[current_num_of_values - 1].data.uint32_val = vesCount.critical;
441
442             CREATE_NEW_VALUE(rc, v, current_num_of_values);
443
444             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "normal");
445             v[current_num_of_values - 1].type = SR_UINT32_T;
446             v[current_num_of_values - 1].data.uint32_val = netconfCount.normal;
447
448             CREATE_NEW_VALUE(rc, v, current_num_of_values);
449
450             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "warning");
451             v[current_num_of_values - 1].type = SR_UINT32_T;
452             v[current_num_of_values - 1].data.uint32_val = netconfCount.warning;
453
454             CREATE_NEW_VALUE(rc, v, current_num_of_values);
455
456             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "minor");
457             v[current_num_of_values - 1].type = SR_UINT32_T;
458             v[current_num_of_values - 1].data.uint32_val = netconfCount.minor;
459
460             CREATE_NEW_VALUE(rc, v, current_num_of_values);
461
462             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "major");
463             v[current_num_of_values - 1].type = SR_UINT32_T;
464             v[current_num_of_values - 1].data.uint32_val = netconfCount.major;
465
466             CREATE_NEW_VALUE(rc, v, current_num_of_values);
467
468             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "critical");
469             v[current_num_of_values - 1].type = SR_UINT32_T;
470             v[current_num_of_values - 1].data.uint32_val = netconfCount.critical;
471
472                         current_device = current_device->next;
473                 }
474
475                 //return the values that we have just created
476                 *values = v;
477                 *values_cnt = current_num_of_values;
478          }
479          else if (sr_xpath_node_name_eq(xpath, "simulation-usage-details"))
480          {
481                 float cpu_usage = 0.0, mem_usage = 0.0;
482
483                 char *resource_usage_from_script = get_docker_container_resource_stats();
484
485                 if (resource_usage_from_script != NULL)
486                 {
487                         printf("Received line: %s\n", resource_usage_from_script);
488                         sscanf(resource_usage_from_script, "CPU=%f%%;RAM=%fMiB", &cpu_usage, &mem_usage);
489                         printf("Read cpu=\"%f\" and mem=\"%f\"\n", cpu_usage, mem_usage);
490                         free(resource_usage_from_script);
491                 }
492
493                 sr_val_t *v;
494                 /* convenient functions such as this can be found in sysrepo/values.h */
495                 size_t current_num_of_values= 0;
496
497                 CREATE_NEW_VALUE(rc, v, current_num_of_values);
498
499                 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "running-simulated-devices");
500                 v[current_num_of_values - 1].type = SR_UINT32_T;
501                 v[current_num_of_values - 1].data.uint32_val = get_current_number_of_devices(device_list);
502
503                 CREATE_NEW_VALUE(rc, v, current_num_of_values);
504
505                 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "running-mounted-devices");
506                 v[current_num_of_values - 1].type = SR_UINT32_T;
507                 v[current_num_of_values - 1].data.uint32_val = get_current_number_of_mounted_devices(device_list);
508
509                 CREATE_NEW_VALUE(rc, v, current_num_of_values);
510
511                 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "base-netconf-port");
512                 v[current_num_of_values - 1].type = SR_UINT32_T;
513                 v[current_num_of_values - 1].data.uint32_val = get_netconf_port_base();
514
515                 CREATE_NEW_VALUE(rc, v, current_num_of_values);
516
517                 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "cpu-usage");
518                 v[current_num_of_values - 1].type = SR_DECIMAL64_T;
519                 v[current_num_of_values - 1].data.decimal64_val = cpu_usage;
520
521                 CREATE_NEW_VALUE(rc, v, current_num_of_values);
522
523                 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "mem-usage");
524                 v[current_num_of_values - 1].type = SR_UINT32_T;
525                 v[current_num_of_values - 1].data.uint32_val = (int)mem_usage;
526
527                 //return the values that we have just created
528                 *values = v;
529                 *values_cnt = current_num_of_values;
530          }
531      else if (sr_xpath_node_name_eq(xpath, "total-ves-notifications"))
532      {
533         sr_val_t *v;
534         /* convenient functions such as this can be found in sysrepo/values.h */
535         size_t current_num_of_values= 0;
536
537         CREATE_NEW_VALUE(rc, v, current_num_of_values);
538
539         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "normal");
540         v[current_num_of_values - 1].type = SR_UINT32_T;
541         v[current_num_of_values - 1].data.uint32_val = ves_counter.normal;
542
543         CREATE_NEW_VALUE(rc, v, current_num_of_values);
544
545         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "warning");
546         v[current_num_of_values - 1].type = SR_UINT32_T;
547         v[current_num_of_values - 1].data.uint32_val = ves_counter.warning;
548
549         CREATE_NEW_VALUE(rc, v, current_num_of_values);
550
551         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "minor");
552         v[current_num_of_values - 1].type = SR_UINT32_T;
553         v[current_num_of_values - 1].data.uint32_val = ves_counter.minor;
554
555         CREATE_NEW_VALUE(rc, v, current_num_of_values);
556
557         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "major");
558         v[current_num_of_values - 1].type = SR_UINT32_T;
559         v[current_num_of_values - 1].data.uint32_val = ves_counter.major;
560
561         CREATE_NEW_VALUE(rc, v, current_num_of_values);
562
563         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "critical");
564         v[current_num_of_values - 1].type = SR_UINT32_T;
565         v[current_num_of_values - 1].data.uint32_val = ves_counter.critical;
566
567         //return the values that we have just created
568         *values = v;
569         *values_cnt = current_num_of_values;
570      }
571      else if (sr_xpath_node_name_eq(xpath, "total-netconf-notifications"))
572      {
573         sr_val_t *v;
574         /* convenient functions such as this can be found in sysrepo/values.h */
575         size_t current_num_of_values= 0;
576
577         CREATE_NEW_VALUE(rc, v, current_num_of_values);
578
579         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "normal");
580         v[current_num_of_values - 1].type = SR_UINT32_T;
581         v[current_num_of_values - 1].data.uint32_val = netconf_counter.normal;
582
583         CREATE_NEW_VALUE(rc, v, current_num_of_values);
584
585         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "warning");
586         v[current_num_of_values - 1].type = SR_UINT32_T;
587         v[current_num_of_values - 1].data.uint32_val = netconf_counter.warning;
588
589         CREATE_NEW_VALUE(rc, v, current_num_of_values);
590
591         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "minor");
592         v[current_num_of_values - 1].type = SR_UINT32_T;
593         v[current_num_of_values - 1].data.uint32_val = netconf_counter.minor;
594
595         CREATE_NEW_VALUE(rc, v, current_num_of_values);
596
597         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "major");
598         v[current_num_of_values - 1].type = SR_UINT32_T;
599         v[current_num_of_values - 1].data.uint32_val = netconf_counter.major;
600
601         CREATE_NEW_VALUE(rc, v, current_num_of_values);
602
603         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "critical");
604         v[current_num_of_values - 1].type = SR_UINT32_T;
605         v[current_num_of_values - 1].data.uint32_val = netconf_counter.critical;
606
607         //return the values that we have just created
608         *values = v;
609         *values_cnt = current_num_of_values;
610      }
611
612     return SR_ERR_OK;
613 }
614
615 int odl_add_key_pair_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
616                 sr_val_t **output, size_t *output_cnt, void *private_ctx)
617 {
618         int rc = SR_ERR_OK;
619         controller_t controller_list[CONTROLLER_LIST_MAX_LEN];
620         int controller_list_size = 0;
621
622         controller_list[0] = controller_details;
623         controller_list_size++;
624
625         for (int i = 0; i < controller_list_size; ++i)
626         {
627                 printf("%d iteration: Got back url=%s and credentials=%s\n", i, controller_list[i].url, controller_list[i].credentials);
628         }
629
630         rc = add_key_pair_to_odl(controller_list, controller_list_size);
631         if (rc != SR_ERR_OK)
632         {
633                 printf("Failed to add key pair to ODL.\n");
634                 return SR_ERR_OPERATION_FAILED;
635         }
636
637         return rc;
638 }
639
640
641 static void
642 sigint_handler(int signum)
643 {
644     exit_application = 1;
645 }
646
647 int
648 main(int argc, char **argv)
649 {
650     sr_conn_ctx_t *connection = NULL;
651     sr_session_ctx_t *session = NULL;
652     sr_subscription_ctx_t *subscription = NULL;
653     int rc = SR_ERR_OK;
654
655     setbuf(stdout, NULL);
656
657     device_list = new_device_stack();
658     rc = _init_curl();
659     if (rc != SR_ERR_OK)
660     {
661         fprintf(stderr, "Could not initialize cURL: %s\n", sr_strerror(rc));
662     }
663
664     /* connect to sysrepo */
665     rc = sr_connect("network-topology-simulator", SR_CONN_DEFAULT, &connection);
666     if (SR_ERR_OK != rc) {
667         fprintf(stderr, "Error by sr_connect: %s\n", sr_strerror(rc));
668         goto cleanup;
669     }
670
671     /* start session */
672     rc = sr_session_start(connection, SR_DS_STARTUP, SR_SESS_DEFAULT, &session);
673     if (SR_ERR_OK != rc) {
674         fprintf(stderr, "Error by sr_session_start: %s\n", sr_strerror(rc));
675         goto cleanup;
676     }
677
678         /* read startup config */
679         printf("\n\n ========== READING STARTUP CONFIG network-topology-simulator: ==========\n\n");
680         print_current_config(session, "network-topology-simulator");
681
682         /* subscribe for changes in running config */
683         rc = sr_module_change_subscribe(session, "network-topology-simulator", simulator_config_change_cb, NULL,
684                         0, SR_SUBSCR_DEFAULT | SR_SUBSCR_APPLY_ONLY, &subscription);
685         if (SR_ERR_OK != rc) {
686                 fprintf(stderr, "Error by sr_module_change_subscribe: %s\n", sr_strerror(rc));
687                 goto cleanup;
688         }
689
690     /* subscribe as state data provider for the ntsimulator state data */
691     rc = sr_dp_get_items_subscribe(session, "/network-topology-simulator:simulator-status", simulator_status_cb, NULL,
692                 SR_SUBSCR_CTX_REUSE, &subscription);
693     if (rc != SR_ERR_OK) {
694         goto cleanup;
695     }
696
697     rc = notification_delay_period_changed(NULL, 0);
698     if (rc != SR_ERR_OK) {
699         printf("Could not write the delay period to file!\n");
700         goto cleanup;
701     }
702
703     rc = _init_curl_odl();
704     if (rc != SR_ERR_OK)
705     {
706         fprintf(stderr, "Could not initialize cURL for ODL connection: %s\n", sr_strerror(rc));
707     }
708
709     rc = sr_rpc_subscribe(session, "/network-topology-simulator:add-key-pair-to-odl", odl_add_key_pair_cb, (void *)session,
710                 SR_SUBSCR_CTX_REUSE, &subscription);
711
712         printf("\n\n ========== STARTUP CONFIG network-topology-simulator APPLIED AS RUNNING ==========\n\n");
713
714     rc = writeSkeletonStatusFile();
715     if (rc != SR_ERR_OK)
716     {
717         fprintf(stderr, "Could not initialize status JSON file: %s\n", sr_strerror(rc));
718     }
719
720     /* loop until ctrl-c is pressed / SIGINT is received */
721     signal(SIGINT, sigint_handler);
722     signal(SIGTERM, sigint_handler);
723     signal(SIGPIPE, SIG_IGN);
724
725     while (!exit_application) {
726
727                 sleep(1);  /* or do some more useful work... */
728     }
729
730     printf("Application exit requested, exiting.\n");
731
732 cleanup:
733     if (NULL != subscription) {
734         sr_unsubscribe(session, subscription);
735     }
736     if (NULL != session) {
737         sr_session_stop(session);
738     }
739     if (NULL != connection) {
740         sr_disconnect(connection);
741     }
742
743     clean_current_docker_configuration();
744     rc = cleanup_curl();
745     rc = cleanup_curl_odl();
746
747     return rc;
748 }
749
750 static void clean_current_docker_configuration(void)
751 {
752         printf("Cleaning docker containers...\n");
753
754         if (device_list == NULL)
755         {
756                 return;
757         }
758
759         for (int i = 0; i < simulated_devices_config; ++i)
760         {
761                 stop_device(device_list);
762         }
763
764         printf("Cleaning completed!\n");
765 }