Add counters for generated notifications.
[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     /* get the value from sysrepo, we do not care if the value did not change in our case */
229     rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/fault-notification-delay-period", &val);
230     if (rc != SR_ERR_OK) {
231         goto sr_error;
232     }
233
234     rc = notification_delay_period_changed(val->data.uint32_val);
235     if (rc != SR_ERR_OK) {
236         goto sr_error;
237     }
238
239     sr_free_val(val);
240         val = NULL;
241
242     /* get the value from sysrepo, we do not care if the value did not change in our case */
243         rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/ves-heartbeat-period", &val);
244         if (rc != SR_ERR_OK) {
245                 goto sr_error;
246         }
247
248         rc = ves_heartbeat_period_changed(val->data.uint32_val);
249         if (rc != SR_ERR_OK) {
250                 goto sr_error;
251         }
252
253         sr_free_val(val);
254         val = NULL;
255
256         /* get the value from sysrepo, we do not care if the value did not change in our case */
257         rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-ip", &val);
258         if (rc != SR_ERR_OK) {
259                 goto sr_error;
260         }
261
262         rc = ves_ip_changed(val->data.string_val);
263         if (rc != SR_ERR_OK) {
264                 goto sr_error;
265         }
266
267         sr_free_val(val);
268         val = NULL;
269
270         /* get the value from sysrepo, we do not care if the value did not change in our case */
271         rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-port", &val);
272         if (rc != SR_ERR_OK) {
273                 goto sr_error;
274         }
275
276         rc = ves_port_changed(val->data.uint16_val);
277         if (rc != SR_ERR_OK) {
278                 goto sr_error;
279         }
280
281         sr_free_val(val);
282         val = NULL;
283
284         /* get the value from sysrepo, we do not care if the value did not change in our case */
285         rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-registration", &val);
286         if (rc != SR_ERR_OK) {
287                 goto sr_error;
288         }
289
290         rc = ves_registration_changed(val->data.bool_val);
291         if (rc != SR_ERR_OK) {
292                 goto sr_error;
293         }
294
295         sr_free_val(val);
296         val = NULL;
297
298         /* get the value from sysrepo, we do not care if the value did not change in our case */
299         rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/is-netconf-available", &val);
300         if (rc != SR_ERR_OK) {
301                 goto sr_error;
302         }
303
304         rc = is_netconf_available_changed(val->data.bool_val);
305         if (rc != SR_ERR_OK) {
306                 goto sr_error;
307         }
308
309         sr_free_val(val);
310         val = NULL;
311
312         /* get the value from sysrepo, we do not care if the value did not change in our case */
313         rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/is-ves-available", &val);
314         if (rc != SR_ERR_OK) {
315                 goto sr_error;
316         }
317
318         rc = is_ves_available_changed(val->data.bool_val);
319         if (rc != SR_ERR_OK) {
320                 goto sr_error;
321         }
322
323         sr_free_val(val);
324         val = NULL;
325
326     return SR_ERR_OK;
327
328 sr_error:
329         printf("NTSimulator config change callback failed: %s.", sr_strerror(rc));
330         if (val != NULL)
331         {
332                 sr_free_val(val);
333                 val = NULL;
334         }
335         return rc;
336 }
337
338 static int
339 simulator_status_cb(const char *xpath, sr_val_t **values, size_t *values_cnt,
340         uint64_t request_id, const char *original_xpath, void *private_ctx)
341 {
342         int rc;
343
344         // printf("\n\n ========== Called simulator_status_cb for xpath: %s ==========\n\n", xpath);
345
346     counterAlarms ves_counter, netconf_counter;
347     rc = compute_notifications_count(&ves_counter, &netconf_counter);
348     if (rc != SR_ERR_OK)
349     {
350         printf("Could not compute the total number of notification count.\n");
351     }
352
353         if (sr_xpath_node_name_eq(xpath, "simulated-devices-list")) {
354                 sr_val_t *v;
355                 size_t current_num_of_values= 0;
356
357                 if (simulated_devices_config == 0) //nothing to return if no devices are running
358                 {
359                         *values = NULL;
360                         *values_cnt = 0;
361
362                         return SR_ERR_OK;
363                 }
364
365                 rc = get_docker_containers_operational_state_curl(device_list);
366                 if (rc != SR_ERR_OK)
367                 {
368                         printf("Could not get the operational state for the devices simulated.\n");
369                         return SR_ERR_OPERATION_FAILED;
370                 }
371
372                 device_t *current_device = device_list->head;
373
374                 while (current_device != NULL)
375                 {
376             counterAlarms vesCount, netconfCount;
377             rc = getDeviceCounters(current_device->device_id, &vesCount, &netconfCount);
378             if (rc != SR_ERR_OK)
379             {
380                 printf("Could not get Notification Counters for device with uuid=\"%s\"", current_device->device_id);
381             }            
382
383                         CREATE_NEW_VALUE(rc, v, current_num_of_values);
384
385                         sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "device-ip");
386                         v[current_num_of_values - 1].type = SR_STRING_T;
387                         v[current_num_of_values - 1].data.string_val = getenv("NTS_IP");
388
389                         for (int i = 0; i < NETCONF_CONNECTIONS_PER_DEVICE; ++i)
390                         {
391                                 CREATE_NEW_VALUE(rc, v, current_num_of_values);
392
393                                 sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "device-port");
394                                 v[current_num_of_values - 1].type = SR_UINT32_T;
395                                 v[current_num_of_values - 1].data.uint32_val = current_device->netconf_port + i;
396                         }
397
398                         CREATE_NEW_VALUE(rc, v, current_num_of_values);
399
400                         sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "is-mounted");
401                         v[current_num_of_values - 1].type = SR_BOOL_T;
402                         v[current_num_of_values - 1].data.bool_val = current_device->is_mounted;
403
404                         char *operational_state = get_docker_container_operational_state(device_list, current_device->device_id);
405
406                         CREATE_NEW_VALUE(rc, v, current_num_of_values);
407
408                         sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "operational-state");
409                         sr_val_build_str_data(&v[current_num_of_values - 1], SR_ENUM_T, "%s", operational_state);
410
411             CREATE_NEW_VALUE(rc, v, current_num_of_values);
412
413             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "normal");
414             v[current_num_of_values - 1].type = SR_UINT32_T;
415             v[current_num_of_values - 1].data.uint32_val = vesCount.normal;
416
417             CREATE_NEW_VALUE(rc, v, current_num_of_values);
418
419             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "warning");
420             v[current_num_of_values - 1].type = SR_UINT32_T;
421             v[current_num_of_values - 1].data.uint32_val = vesCount.warning;
422
423             CREATE_NEW_VALUE(rc, v, current_num_of_values);
424
425             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "minor");
426             v[current_num_of_values - 1].type = SR_UINT32_T;
427             v[current_num_of_values - 1].data.uint32_val = vesCount.minor;
428
429             CREATE_NEW_VALUE(rc, v, current_num_of_values);
430
431             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "major");
432             v[current_num_of_values - 1].type = SR_UINT32_T;
433             v[current_num_of_values - 1].data.uint32_val = vesCount.major;
434
435             CREATE_NEW_VALUE(rc, v, current_num_of_values);
436
437             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, current_device->device_id, "critical");
438             v[current_num_of_values - 1].type = SR_UINT32_T;
439             v[current_num_of_values - 1].data.uint32_val = vesCount.critical;
440
441             CREATE_NEW_VALUE(rc, v, current_num_of_values);
442
443             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "normal");
444             v[current_num_of_values - 1].type = SR_UINT32_T;
445             v[current_num_of_values - 1].data.uint32_val = netconfCount.normal;
446
447             CREATE_NEW_VALUE(rc, v, current_num_of_values);
448
449             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "warning");
450             v[current_num_of_values - 1].type = SR_UINT32_T;
451             v[current_num_of_values - 1].data.uint32_val = netconfCount.warning;
452
453             CREATE_NEW_VALUE(rc, v, current_num_of_values);
454
455             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "minor");
456             v[current_num_of_values - 1].type = SR_UINT32_T;
457             v[current_num_of_values - 1].data.uint32_val = netconfCount.minor;
458
459             CREATE_NEW_VALUE(rc, v, current_num_of_values);
460
461             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "major");
462             v[current_num_of_values - 1].type = SR_UINT32_T;
463             v[current_num_of_values - 1].data.uint32_val = netconfCount.major;
464
465             CREATE_NEW_VALUE(rc, v, current_num_of_values);
466
467             sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, current_device->device_id, "critical");
468             v[current_num_of_values - 1].type = SR_UINT32_T;
469             v[current_num_of_values - 1].data.uint32_val = netconfCount.critical;
470
471                         current_device = current_device->next;
472                 }
473
474                 //return the values that we have just created
475                 *values = v;
476                 *values_cnt = current_num_of_values;
477          }
478          else if (sr_xpath_node_name_eq(xpath, "simulation-usage-details"))
479          {
480                 float cpu_usage = 0.0, mem_usage = 0.0;
481
482                 char *resource_usage_from_script = get_docker_container_resource_stats();
483
484                 if (resource_usage_from_script != NULL)
485                 {
486                         printf("Received line: %s\n", resource_usage_from_script);
487                         sscanf(resource_usage_from_script, "CPU=%f%%;RAM=%fMiB", &cpu_usage, &mem_usage);
488                         printf("Read cpu=\"%f\" and mem=\"%f\"\n", cpu_usage, mem_usage);
489                         free(resource_usage_from_script);
490                 }
491
492                 sr_val_t *v;
493                 /* convenient functions such as this can be found in sysrepo/values.h */
494                 size_t current_num_of_values= 0;
495
496                 CREATE_NEW_VALUE(rc, v, current_num_of_values);
497
498                 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "running-simulated-devices");
499                 v[current_num_of_values - 1].type = SR_UINT32_T;
500                 v[current_num_of_values - 1].data.uint32_val = get_current_number_of_devices(device_list);
501
502                 CREATE_NEW_VALUE(rc, v, current_num_of_values);
503
504                 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "running-mounted-devices");
505                 v[current_num_of_values - 1].type = SR_UINT32_T;
506                 v[current_num_of_values - 1].data.uint32_val = get_current_number_of_mounted_devices(device_list);
507
508                 CREATE_NEW_VALUE(rc, v, current_num_of_values);
509
510                 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "base-netconf-port");
511                 v[current_num_of_values - 1].type = SR_UINT32_T;
512                 v[current_num_of_values - 1].data.uint32_val = get_netconf_port_base();
513
514                 CREATE_NEW_VALUE(rc, v, current_num_of_values);
515
516                 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "cpu-usage");
517                 v[current_num_of_values - 1].type = SR_DECIMAL64_T;
518                 v[current_num_of_values - 1].data.decimal64_val = cpu_usage;
519
520                 CREATE_NEW_VALUE(rc, v, current_num_of_values);
521
522                 sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "mem-usage");
523                 v[current_num_of_values - 1].type = SR_UINT32_T;
524                 v[current_num_of_values - 1].data.uint32_val = (int)mem_usage;
525
526                 //return the values that we have just created
527                 *values = v;
528                 *values_cnt = current_num_of_values;
529          }
530      else if (sr_xpath_node_name_eq(xpath, "total-ves-notifications"))
531      {
532         sr_val_t *v;
533         /* convenient functions such as this can be found in sysrepo/values.h */
534         size_t current_num_of_values= 0;
535
536         CREATE_NEW_VALUE(rc, v, current_num_of_values);
537
538         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "normal");
539         v[current_num_of_values - 1].type = SR_UINT32_T;
540         v[current_num_of_values - 1].data.uint32_val = ves_counter.normal;
541
542         CREATE_NEW_VALUE(rc, v, current_num_of_values);
543
544         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "warning");
545         v[current_num_of_values - 1].type = SR_UINT32_T;
546         v[current_num_of_values - 1].data.uint32_val = ves_counter.warning;
547
548         CREATE_NEW_VALUE(rc, v, current_num_of_values);
549
550         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "minor");
551         v[current_num_of_values - 1].type = SR_UINT32_T;
552         v[current_num_of_values - 1].data.uint32_val = ves_counter.minor;
553
554         CREATE_NEW_VALUE(rc, v, current_num_of_values);
555
556         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "major");
557         v[current_num_of_values - 1].type = SR_UINT32_T;
558         v[current_num_of_values - 1].data.uint32_val = ves_counter.major;
559
560         CREATE_NEW_VALUE(rc, v, current_num_of_values);
561
562         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "critical");
563         v[current_num_of_values - 1].type = SR_UINT32_T;
564         v[current_num_of_values - 1].data.uint32_val = ves_counter.critical;
565
566         //return the values that we have just created
567         *values = v;
568         *values_cnt = current_num_of_values;
569      }
570      else if (sr_xpath_node_name_eq(xpath, "total-netconf-notifications"))
571      {
572         sr_val_t *v;
573         /* convenient functions such as this can be found in sysrepo/values.h */
574         size_t current_num_of_values= 0;
575
576         CREATE_NEW_VALUE(rc, v, current_num_of_values);
577
578         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "normal");
579         v[current_num_of_values - 1].type = SR_UINT32_T;
580         v[current_num_of_values - 1].data.uint32_val = netconf_counter.normal;
581
582         CREATE_NEW_VALUE(rc, v, current_num_of_values);
583
584         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "warning");
585         v[current_num_of_values - 1].type = SR_UINT32_T;
586         v[current_num_of_values - 1].data.uint32_val = netconf_counter.warning;
587
588         CREATE_NEW_VALUE(rc, v, current_num_of_values);
589
590         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "minor");
591         v[current_num_of_values - 1].type = SR_UINT32_T;
592         v[current_num_of_values - 1].data.uint32_val = netconf_counter.minor;
593
594         CREATE_NEW_VALUE(rc, v, current_num_of_values);
595
596         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "major");
597         v[current_num_of_values - 1].type = SR_UINT32_T;
598         v[current_num_of_values - 1].data.uint32_val = netconf_counter.major;
599
600         CREATE_NEW_VALUE(rc, v, current_num_of_values);
601
602         sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "critical");
603         v[current_num_of_values - 1].type = SR_UINT32_T;
604         v[current_num_of_values - 1].data.uint32_val = netconf_counter.critical;
605
606         //return the values that we have just created
607         *values = v;
608         *values_cnt = current_num_of_values;
609      }
610
611     return SR_ERR_OK;
612 }
613
614 int odl_add_key_pair_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
615                 sr_val_t **output, size_t *output_cnt, void *private_ctx)
616 {
617         int rc = SR_ERR_OK;
618         controller_t controller_list[CONTROLLER_LIST_MAX_LEN];
619         int controller_list_size = 0;
620
621         controller_list[0] = controller_details;
622         controller_list_size++;
623
624         for (int i = 0; i < controller_list_size; ++i)
625         {
626                 printf("%d iteration: Got back url=%s and credentials=%s\n", i, controller_list[i].url, controller_list[i].credentials);
627         }
628
629         rc = add_key_pair_to_odl(controller_list, controller_list_size);
630         if (rc != SR_ERR_OK)
631         {
632                 printf("Failed to add key pair to ODL.\n");
633                 return SR_ERR_OPERATION_FAILED;
634         }
635
636         return rc;
637 }
638
639
640 static void
641 sigint_handler(int signum)
642 {
643     exit_application = 1;
644 }
645
646 int
647 main(int argc, char **argv)
648 {
649     sr_conn_ctx_t *connection = NULL;
650     sr_session_ctx_t *session = NULL;
651     sr_subscription_ctx_t *subscription = NULL;
652     int rc = SR_ERR_OK;
653
654     setbuf(stdout, NULL);
655
656     device_list = new_device_stack();
657     rc = _init_curl();
658     if (rc != SR_ERR_OK)
659     {
660         fprintf(stderr, "Could not initialize cURL: %s\n", sr_strerror(rc));
661     }
662
663     /* connect to sysrepo */
664     rc = sr_connect("network-topology-simulator", SR_CONN_DEFAULT, &connection);
665     if (SR_ERR_OK != rc) {
666         fprintf(stderr, "Error by sr_connect: %s\n", sr_strerror(rc));
667         goto cleanup;
668     }
669
670     /* start session */
671     rc = sr_session_start(connection, SR_DS_STARTUP, SR_SESS_DEFAULT, &session);
672     if (SR_ERR_OK != rc) {
673         fprintf(stderr, "Error by sr_session_start: %s\n", sr_strerror(rc));
674         goto cleanup;
675     }
676
677         /* read startup config */
678         printf("\n\n ========== READING STARTUP CONFIG network-topology-simulator: ==========\n\n");
679         print_current_config(session, "network-topology-simulator");
680
681         /* subscribe for changes in running config */
682         rc = sr_module_change_subscribe(session, "network-topology-simulator", simulator_config_change_cb, NULL,
683                         0, SR_SUBSCR_DEFAULT | SR_SUBSCR_APPLY_ONLY, &subscription);
684         if (SR_ERR_OK != rc) {
685                 fprintf(stderr, "Error by sr_module_change_subscribe: %s\n", sr_strerror(rc));
686                 goto cleanup;
687         }
688
689     /* subscribe as state data provider for the ntsimulator state data */
690     rc = sr_dp_get_items_subscribe(session, "/network-topology-simulator:simulator-status", simulator_status_cb, NULL,
691                 SR_SUBSCR_CTX_REUSE, &subscription);
692     if (rc != SR_ERR_OK) {
693         goto cleanup;
694     }
695
696     rc = notification_delay_period_changed(0);
697     if (rc != SR_ERR_OK) {
698         printf("Could not write the delay period to file!\n");
699         goto cleanup;
700     }
701
702     rc = _init_curl_odl();
703     if (rc != SR_ERR_OK)
704     {
705         fprintf(stderr, "Could not initialize cURL for ODL connection: %s\n", sr_strerror(rc));
706     }
707
708     rc = sr_rpc_subscribe(session, "/network-topology-simulator:add-key-pair-to-odl", odl_add_key_pair_cb, (void *)session,
709                 SR_SUBSCR_CTX_REUSE, &subscription);
710
711         printf("\n\n ========== STARTUP CONFIG network-topology-simulator APPLIED AS RUNNING ==========\n\n");
712
713     rc = writeSkeletonStatusFile();
714     if (rc != SR_ERR_OK)
715     {
716         fprintf(stderr, "Could not initialize status JSON file: %s\n", sr_strerror(rc));
717     }
718
719     /* loop until ctrl-c is pressed / SIGINT is received */
720     signal(SIGINT, sigint_handler);
721     signal(SIGTERM, sigint_handler);
722     signal(SIGPIPE, SIG_IGN);
723
724     while (!exit_application) {
725
726                 sleep(1);  /* or do some more useful work... */
727     }
728
729     printf("Application exit requested, exiting.\n");
730
731 cleanup:
732     if (NULL != subscription) {
733         sr_unsubscribe(session, subscription);
734     }
735     if (NULL != session) {
736         sr_session_stop(session);
737     }
738     if (NULL != connection) {
739         sr_disconnect(connection);
740     }
741
742     clean_current_docker_configuration();
743     rc = cleanup_curl();
744     rc = cleanup_curl_odl();
745
746     return rc;
747 }
748
749 static void clean_current_docker_configuration(void)
750 {
751         printf("Cleaning docker containers...\n");
752
753         if (device_list == NULL)
754         {
755                 return;
756         }
757
758         for (int i = 0; i < simulated_devices_config; ++i)
759         {
760                 stop_device(device_list);
761         }
762
763         printf("Cleaning completed!\n");
764 }