f734307030ed6b54d5fd3ce957f5763558ff7f91
[sim/o1-interface.git] / ntsimulator / src / ntsimulator-manager / simulator-operations.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 #include "simulator-operations.h"
19 #include "sysrepo.h"
20 #include "sysrepo/values.h"
21 #include <string.h>
22 #include <math.h>
23 #include <linux/limits.h>
24
25 #include "utils.h"
26
27 #define LINE_BUFSIZE 128
28
29 static  CURL *curl; //share the same curl connection for communicating with the Docker Engine API
30 static  CURL *curl_odl; //share the same curl connection for mounting servers in ODL
31
32 static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
33 {
34   size_t realsize = size * nmemb;
35   struct MemoryStruct *mem = (struct MemoryStruct *)userp;
36
37   char *ptr = realloc(mem->memory, mem->size + realsize + 1);
38   if(ptr == NULL) {
39     /* out of memory! */
40     printf("not enough memory (realloc returned NULL)\n");
41     return 0;
42   }
43
44   mem->memory = ptr;
45   memcpy(&(mem->memory[mem->size]), contents, realsize);
46   mem->size += realsize;
47   mem->memory[mem->size] = 0;
48
49   return realsize;
50 }
51
52 static void set_curl_common_info()
53 {
54         struct curl_slist *chunk = NULL;
55         chunk = curl_slist_append(chunk, "Content-Type: application/json");
56         chunk = curl_slist_append(chunk, "Accept: application/json");
57
58     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
59
60         curl_easy_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, "/var/run/docker.sock");
61
62         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
63     curl_easy_setopt(curl_odl, CURLOPT_CONNECTTIMEOUT, 2L); // seconds timeout for a connection
64     curl_easy_setopt(curl_odl, CURLOPT_TIMEOUT, 5L); //seconds timeout for an operation
65
66     curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
67 }
68
69 static void set_curl_common_info_odl()
70 {
71         struct curl_slist *chunk = NULL;
72         chunk = curl_slist_append(chunk, "Content-Type: application/xml");
73         chunk = curl_slist_append(chunk, "Accept: application/xml");
74
75     curl_easy_setopt(curl_odl, CURLOPT_HTTPHEADER, chunk);
76
77     curl_easy_setopt(curl_odl, CURLOPT_CONNECTTIMEOUT, 2L); // seconds timeout for a connection
78     curl_easy_setopt(curl_odl, CURLOPT_TIMEOUT, 5L); //seconds timeout for an operation
79
80     curl_easy_setopt(curl_odl, CURLOPT_VERBOSE, 1L);
81 }
82
83 static cJSON* get_docker_container_bindings(void)
84 {
85         struct MemoryStruct curl_response_mem;
86
87         curl_response_mem.memory = malloc(1);  /* will be grown as needed by the realloc above */
88         curl_response_mem.size = 0;    /* no data at this point */
89
90         CURLcode res;
91
92         curl_easy_reset(curl);
93         set_curl_common_info();
94
95         char url[200];
96         sprintf(url, "http:/v%s/containers/%s/json", getenv("DOCKER_ENGINE_VERSION"), getenv("HOSTNAME"));
97
98         curl_easy_setopt(curl, CURLOPT_URL, url);
99
100     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
101     curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
102
103         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
104
105         res = curl_easy_perform(curl);
106
107         if (res != CURLE_OK)
108         {
109                 return NULL;
110         }
111         else
112         {
113                 cJSON *json_response = cJSON_Parse(curl_response_mem.memory);
114
115                 printf("%lu bytes retrieved\n", (unsigned long)curl_response_mem.size);
116
117                 if (json_response == NULL)
118                 {
119                         printf("Could not parse JSON response for url=\"%s\"\n", url);
120                         return NULL;
121                 }
122
123                 cJSON *hostConfig = cJSON_GetObjectItemCaseSensitive(json_response, "HostConfig");
124
125                 if (hostConfig == NULL)
126                 {
127                         printf("Could not get HostConfig object\n");
128                         return NULL;
129                 }
130
131                 cJSON *binds = cJSON_GetObjectItemCaseSensitive(hostConfig, "Binds");
132
133                 if (binds == NULL)
134                 {
135                         printf("Could not get Binds object\n");
136                         return NULL;
137                 }
138
139                 cJSON *bindsCopy = cJSON_Duplicate(binds, 1);
140
141             cJSON_Delete(json_response);
142
143                 return bindsCopy;
144         }
145
146         return NULL;
147 }
148
149 static char* create_docker_container_curl(int base_netconf_port, cJSON* managerBinds)
150 {
151         if (managerBinds == NULL)
152         {
153                 printf("Could not retrieve JSON object: Binds\n");
154                 return NULL;
155         }
156         cJSON *binds = cJSON_Duplicate(managerBinds, 1);
157
158         struct MemoryStruct curl_response_mem;
159
160         curl_response_mem.memory = malloc(1);  /* will be grown as needed by the realloc above */
161         curl_response_mem.size = 0;    /* no data at this point */
162
163         CURLcode res;
164
165         curl_easy_reset(curl);
166         set_curl_common_info();
167
168         char url[100];
169         sprintf(url, "http:/v%s/containers/create", getenv("DOCKER_ENGINE_VERSION"));
170
171         // the docker image name to be used is defined in the Dockerfile of the NTS Manager,
172         // under the MODELS_IMAGE env variable
173         char models_var[50];
174         sprintf(models_var, "%s", getenv("MODELS_IMAGE"));
175
176         curl_easy_setopt(curl, CURLOPT_URL, url);
177
178     cJSON *postDataJson = cJSON_CreateObject();
179
180     if (cJSON_AddStringToObject(postDataJson, "Image", models_var) == NULL)
181         {
182         printf("Could not create JSON object: Image\n");
183                 return NULL;
184         }
185
186     cJSON *hostConfig = cJSON_CreateObject();
187     if (hostConfig == NULL)
188         {
189         printf("Could not create JSON object: HostConfig\n");
190                 return NULL;
191         }
192
193     cJSON_AddItemToObject(postDataJson, "HostConfig", hostConfig);
194
195     cJSON *portBindings = cJSON_CreateObject();
196     if (portBindings == NULL)
197         {
198         printf("Could not create JSON object: PortBindings\n");
199                 return NULL;
200         }
201
202     cJSON_AddItemToObject(hostConfig, "PortBindings", portBindings);
203
204     for (int i = 0; i < NETCONF_CONNECTIONS_PER_DEVICE; ++i)
205     {
206         cJSON *port = cJSON_CreateArray();
207                 if (port == NULL)
208                 {
209                 printf("Could not create JSON object: port\n");
210                         return NULL;
211                 }
212
213                 char dockerContainerPort[20];
214                 sprintf(dockerContainerPort, "%d/tcp", 830 + i);
215
216             cJSON_AddItemToObject(portBindings, dockerContainerPort, port);
217
218             cJSON *hostPort = cJSON_CreateObject();
219             if (hostPort == NULL)
220                 {
221                 printf("Could not create JSON object: HostPort\n");
222                         return NULL;
223                 }
224
225             char dockerHostPort[10];
226             sprintf(dockerHostPort, "%d", base_netconf_port + i);
227             if (cJSON_AddStringToObject(hostPort, "HostPort", dockerHostPort) == NULL)
228             {
229                 printf("Could not create JSON object: HostPortString\n");
230                 return NULL;
231             }
232             if (cJSON_AddStringToObject(hostPort, "HostIp", getenv("NTS_IP")) == NULL)
233             {
234                 printf("Could not create JSON object: HostIpString\n");
235                 return NULL;
236             }
237
238             cJSON_AddItemToArray(port, hostPort);
239     }
240
241     cJSON *labels = cJSON_CreateObject();
242     if (labels == NULL)
243         {
244         printf("Could not create JSON object: Labels\n");
245                 return NULL;
246         }
247
248     cJSON_AddItemToObject(postDataJson, "Labels", labels);
249
250     if (cJSON_AddStringToObject(labels, "NTS", "") == NULL)
251     {
252         printf("Could not create JSON object: NTS\n");
253         return NULL;
254     }
255
256         if (cJSON_AddStringToObject(labels, "NTS_Manager", getenv("HOSTNAME")) == NULL)
257     {
258         printf("Could not create JSON object: NTS Manager\n");
259         return NULL;
260     }
261
262     cJSON *env_variables_array = cJSON_CreateArray();
263     if (env_variables_array == NULL)
264         {
265         printf("Could not create JSON object: Env array\n");
266                 return NULL;
267         }
268
269     cJSON_AddItemToObject(postDataJson, "Env", env_variables_array);
270
271     char environment_var[50];
272     sprintf(environment_var, "NTS_IP=%s", getenv("NTS_IP"));
273
274     cJSON *env_var_obj = cJSON_CreateString(environment_var);
275     if (env_var_obj == NULL)
276         {
277         printf("Could not create JSON object: Env array object NTS_IP\n");
278                 return NULL;
279         }
280     cJSON_AddItemToArray(env_variables_array, env_var_obj);
281
282     sprintf(environment_var, "NETCONF_BASE=%d", base_netconf_port);
283     cJSON *env_var_obj_2 = cJSON_CreateString(environment_var);
284     if (env_var_obj_2 == NULL)
285         {
286         printf("Could not create JSON object: Env array object NETCONF_BASE\n");
287                 return NULL;
288         }
289     cJSON_AddItemToArray(env_variables_array, env_var_obj_2);
290
291         char scripts_dir[200];
292         sprintf(scripts_dir, "SCRIPTS_DIR=%s", getenv("SCRIPTS_DIR"));
293         cJSON *env_var_obj_3 = cJSON_CreateString(scripts_dir);
294         if (env_var_obj_3 == NULL)
295         {
296                 printf("Could not create JSON object: Env array object SCRIPTS_DIR\n");
297                 return NULL;
298         }
299         cJSON_AddItemToArray(env_variables_array, env_var_obj_3);
300
301     cJSON_AddItemToObject(hostConfig, "Binds", binds);
302
303     char *post_data_string = NULL;
304
305     post_data_string = cJSON_PrintUnformatted(postDataJson);
306
307     printf("Post data JSON:\n%s\n", post_data_string);
308
309     if (postDataJson != NULL)
310     {
311         cJSON_Delete(postDataJson);
312     }
313
314     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data_string);
315
316         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
317
318         res = curl_easy_perform(curl);
319
320         if (res != CURLE_OK)
321         {
322                 return NULL;
323         }
324         else
325         {
326                 cJSON *json_response = cJSON_Parse(curl_response_mem.memory);
327                 const cJSON *container_id = NULL;
328
329                 printf("%lu bytes retrieved\n", (unsigned long)curl_response_mem.size);
330
331                 container_id = cJSON_GetObjectItemCaseSensitive(json_response, "Id");
332
333                 if (cJSON_IsString(container_id) && (container_id->valuestring != NULL))
334                 {
335                         printf("Container id: \"%s\"\n", container_id->valuestring);
336
337                         char container_id_short[13];
338
339                         memset(container_id_short, '\0', sizeof(container_id_short));
340                         strncpy(container_id_short, container_id->valuestring, 12);
341
342                         printf("Container id short: \"%s\"\n", container_id_short);
343
344                     cJSON_Delete(json_response);
345                         return strdup(container_id_short);
346                 }
347
348             cJSON_Delete(json_response);
349         }
350
351         return NULL;
352 }
353
354 static int start_docker_container_curl(char *container_id)
355 {
356         struct MemoryStruct curl_response_mem;
357
358         curl_response_mem.memory = malloc(1);  /* will be grown as needed by the realloc above */
359         curl_response_mem.size = 0;    /* no data at this point */
360
361         CURLcode res;
362
363         curl_easy_reset(curl);
364         set_curl_common_info();
365
366         char url[100];
367         sprintf(url, "http:/v%s/containers/%s/start", getenv("DOCKER_ENGINE_VERSION"), container_id);
368
369         curl_easy_setopt(curl, CURLOPT_URL, url);
370
371     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
372
373         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
374
375         res = curl_easy_perform(curl);
376
377         if (res != CURLE_OK)
378         {
379                 return SR_ERR_OPERATION_FAILED;
380         }
381         else
382         {
383                 printf("Container %s started successfully!\n", container_id);
384         }
385
386         return SR_ERR_OK;
387 }
388
389 static int kill_and_remove_docker_container_curl(char *container_id)
390 {
391         struct MemoryStruct curl_response_mem;
392
393         curl_response_mem.memory = malloc(1);  /* will be grown as needed by the realloc above */
394         curl_response_mem.size = 0;    /* no data at this point */
395
396         CURLcode res;
397
398         curl_easy_reset(curl);
399         set_curl_common_info();
400
401         char url[100];
402         sprintf(url, "http:/v%s/containers/%s?force=true", getenv("DOCKER_ENGINE_VERSION"), container_id);
403
404         curl_easy_setopt(curl, CURLOPT_URL, url);
405
406     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
407     curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
408
409         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
410
411         res = curl_easy_perform(curl);
412
413         if (res != CURLE_OK)
414         {
415                 return SR_ERR_OPERATION_FAILED;
416         }
417         else
418         {
419                 printf("Container %s removed successfully!\n", container_id);
420         }
421
422         return SR_ERR_OK;
423 }
424
425 static int send_mount_device_instance_ssh(char *url, char *credentials, char *device_name, int device_port)
426 {
427         CURLcode res;
428
429         curl_easy_reset(curl_odl);
430         set_curl_common_info_odl();
431
432         char url_for_curl[200];
433         sprintf(url_for_curl, "%s%s_%d", url, device_name, device_port);
434
435         curl_easy_setopt(curl_odl, CURLOPT_URL, url_for_curl);
436
437         char post_data_xml[1500];
438
439         sprintf(post_data_xml,
440                         "<node xmlns=\"urn:TBD:params:xml:ns:yang:network-topology\">"
441                         "<node-id>%s_%d</node-id>"
442                         "<host xmlns=\"urn:opendaylight:netconf-node-topology\">%s</host>"
443                         "<port xmlns=\"urn:opendaylight:netconf-node-topology\">%d</port>"
444                         "<username xmlns=\"urn:opendaylight:netconf-node-topology\">%s</username>"
445                         "<password xmlns=\"urn:opendaylight:netconf-node-topology\">%s</password>"
446                         "<tcp-only xmlns=\"urn:opendaylight:netconf-node-topology\">false</tcp-only>"
447                         "<keepalive-delay xmlns=\"urn:opendaylight:netconf-node-topology\">120</keepalive-delay>"
448                         "<reconnect-on-changed-schema xmlns=\"urn:opendaylight:netconf-node-topology\">false</reconnect-on-changed-schema>"
449                         "<sleep-factor xmlns=\"urn:opendaylight:netconf-node-topology\">1.5</sleep-factor>"
450                         "<connection-timeout-millis xmlns=\"urn:opendaylight:netconf-node-topology\">20000</connection-timeout-millis>"
451                         "<max-connection-attempts xmlns=\"urn:opendaylight:netconf-node-topology\">100</max-connection-attempts>"
452                         "<between-attempts-timeout-millis xmlns=\"urn:opendaylight:netconf-node-topology\">2000</between-attempts-timeout-millis>"
453                         "</node>",
454                         device_name, device_port, getenv("NTS_IP"), device_port, "netconf", "netconf");
455
456         printf("Post data:\n%s\n", post_data_xml);
457
458         curl_easy_setopt(curl_odl, CURLOPT_POSTFIELDS, post_data_xml);
459     curl_easy_setopt(curl_odl, CURLOPT_CUSTOMREQUEST, "PUT");
460     curl_easy_setopt(curl_odl, CURLOPT_USERPWD, credentials);
461
462         res = curl_easy_perform(curl_odl);
463         if (res != CURLE_OK)
464         {
465                 printf("cURL failed to url=%s\n", url_for_curl);
466         }
467
468         long http_response_code = 0;
469         curl_easy_getinfo (curl_odl, CURLINFO_RESPONSE_CODE, &http_response_code);
470         if (http_response_code >= 200 && http_response_code <= 226 && http_response_code != CURLE_ABORTED_BY_CALLBACK)
471         {
472                 printf("cURL succeeded to url=%s\n", url_for_curl);
473         }
474         else
475         {
476             printf("cURL to url=%s failed with code=%ld\n", url_for_curl, http_response_code);
477                 return SR_ERR_OPERATION_FAILED;
478         }
479
480         return SR_ERR_OK;
481 }
482
483 static int send_mount_device_instance_tls(char *url, char *credentials, char *device_name, int device_port)
484 {
485         CURLcode res;
486
487         curl_easy_reset(curl_odl);
488         set_curl_common_info_odl();
489
490         char url_for_curl[200];
491         sprintf(url_for_curl, "%s%s_%d", url, device_name, device_port);
492
493         curl_easy_setopt(curl_odl, CURLOPT_URL, url_for_curl);
494
495         char post_data_xml[1500];
496
497         sprintf(post_data_xml,
498                         "<node xmlns=\"urn:TBD:params:xml:ns:yang:network-topology\">"
499                         "<protocol xmlns=\"urn:opendaylight:netconf-node-topology\">"
500                         "<name>TLS</name>"
501                         "</protocol>"
502                         "<node-id>%s_%d</node-id>"
503                         "<host xmlns=\"urn:opendaylight:netconf-node-topology\">%s</host>"
504                         "<key-based xmlns=\"urn:opendaylight:netconf-node-topology\">"
505                         "<username>%s</username>"
506                         "<key-id>device-key</key-id>"
507                         "</key-based>"
508                         "<port xmlns=\"urn:opendaylight:netconf-node-topology\">%d</port>"
509                         "<tcp-only xmlns=\"urn:opendaylight:netconf-node-topology\">false</tcp-only>"
510                         "<keepalive-delay xmlns=\"urn:opendaylight:netconf-node-topology\">120</keepalive-delay>"
511                         "<reconnect-on-changed-schema xmlns=\"urn:opendaylight:netconf-node-topology\">false</reconnect-on-changed-schema>"
512                         "<sleep-factor xmlns=\"urn:opendaylight:netconf-node-topology\">1.5</sleep-factor>"
513                         "<connection-timeout-millis xmlns=\"urn:opendaylight:netconf-node-topology\">20000</connection-timeout-millis>"
514                         "<max-connection-attempts xmlns=\"urn:opendaylight:netconf-node-topology\">100</max-connection-attempts>"
515                         "<between-attempts-timeout-millis xmlns=\"urn:opendaylight:netconf-node-topology\">2000</between-attempts-timeout-millis>"
516                         "</node>",
517                         device_name, device_port, getenv("NTS_IP"), "netconf", device_port);
518
519         printf("Post data:\n%s\n", post_data_xml);
520
521         curl_easy_setopt(curl_odl, CURLOPT_POSTFIELDS, post_data_xml);
522     curl_easy_setopt(curl_odl, CURLOPT_CUSTOMREQUEST, "PUT");
523     curl_easy_setopt(curl_odl, CURLOPT_USERPWD, credentials);
524
525         res = curl_easy_perform(curl_odl);
526         if (res != CURLE_OK)
527         {
528                 printf("cURL failed to url=%s\n", url_for_curl);
529         }
530
531         long http_response_code = 0;
532         curl_easy_getinfo (curl_odl, CURLINFO_RESPONSE_CODE, &http_response_code);
533         if (http_response_code >= 200 && http_response_code <= 226 && http_response_code != CURLE_ABORTED_BY_CALLBACK)
534         {
535                 printf("cURL succeeded to url=%s\n", url_for_curl);
536         }
537         else
538         {
539             printf("cURL to url=%s failed with code=%ld\n", url_for_curl, http_response_code);
540                 return SR_ERR_OPERATION_FAILED;
541         }
542
543         return SR_ERR_OK;
544 }
545
546 static int send_unmount_device_instance(char *url, char *credentials, char *device_name, int device_port)
547 {
548         CURLcode res;
549
550         curl_easy_reset(curl_odl);
551         set_curl_common_info_odl();
552
553         char url_for_curl[200];
554         sprintf(url_for_curl, "%s%s_%d", url, device_name, device_port);
555
556         curl_easy_setopt(curl_odl, CURLOPT_URL, url_for_curl);
557
558         curl_easy_setopt(curl_odl, CURLOPT_POSTFIELDS, "");
559         curl_easy_setopt(curl_odl, CURLOPT_CUSTOMREQUEST, "DELETE");
560         curl_easy_setopt(curl_odl, CURLOPT_USERPWD, credentials);
561
562         res = curl_easy_perform(curl_odl);
563         if (res != CURLE_OK)
564         {
565                 printf("cURL failed to url=%s\n", url_for_curl);
566         }
567
568         long http_response_code = 0;
569         curl_easy_getinfo (curl_odl, CURLINFO_RESPONSE_CODE, &http_response_code);
570         if (http_response_code == 200 && http_response_code != CURLE_ABORTED_BY_CALLBACK)
571         {
572                 printf("cURL succeeded to url=%s\n", url_for_curl);
573         }
574         else
575         {
576                 printf("cURL to url=%s failed with code=%ld\n", url_for_curl, http_response_code);
577                 return SR_ERR_OPERATION_FAILED;
578         }
579
580
581         return SR_ERR_OK;
582 }
583
584
585 static int send_mount_device(device_t *current_device, controller_t controller_details)
586 {
587         int rc = SR_ERR_OK;
588         bool is_mounted = true;
589
590         //This is where we hardcoded: 7 devices will have SSH connections and 3 devices will have TLS connections
591         for (int port = 0; port < NETCONF_CONNECTIONS_PER_DEVICE - 3; ++port)
592         {
593                 rc = send_mount_device_instance_ssh(controller_details.url, controller_details.credentials,
594                                 current_device->device_id, current_device->netconf_port + port);
595                 if (rc != SR_ERR_OK)
596                 {
597                         is_mounted = false;
598                 }
599         }
600         for (int port = NETCONF_CONNECTIONS_PER_DEVICE - 3; port < NETCONF_CONNECTIONS_PER_DEVICE; ++port)
601         {
602                 rc = send_mount_device_instance_tls(controller_details.url, controller_details.credentials,
603                                 current_device->device_id, current_device->netconf_port + port);
604                 if (rc != SR_ERR_OK)
605                 {
606                         is_mounted = false;
607                 }
608         }
609
610         current_device->is_mounted = is_mounted;
611
612         return SR_ERR_OK;
613 }
614
615 static int send_unmount_device(device_t *current_device, controller_t controller_details)
616 {
617         int rc = SR_ERR_OK;
618
619         for (int port = 0; port < NETCONF_CONNECTIONS_PER_DEVICE; ++port)
620         {
621                 rc = send_unmount_device_instance(controller_details.url, controller_details.credentials,
622                                 current_device->device_id, current_device->netconf_port + port);
623                 if (rc != SR_ERR_OK)
624                 {
625                         printf("Could not send unmount for ODL with url=\"%s\", for device=\"%s\" and port=%d\n",
626                                         controller_details.url, current_device->device_id, current_device->netconf_port);
627                 }
628         }
629         current_device->is_mounted = false;
630
631         return SR_ERR_OK;
632 }
633
634 device_stack_t *new_device_stack(void)
635 {
636         device_stack_t *stack = malloc(sizeof(*stack));
637
638         if (stack) {
639                 stack->head = NULL;
640                 stack->stack_size = 0;
641         }
642         return stack;
643 }
644
645 void push_device(device_stack_t *theStack, char *dev_id, int port)
646 {
647         device_t *new_dev = malloc(sizeof(*new_dev));
648
649         if (new_dev) {
650                 new_dev->device_id = strdup(dev_id);
651                 new_dev->netconf_port = port;
652                 new_dev->is_mounted = false;
653                 new_dev->operational_state = strdup("not-specified");
654
655                 new_dev->next = theStack->head;
656
657                 theStack->head = new_dev;
658                 theStack->stack_size++;
659         }
660 }
661
662 void pop_device(device_stack_t *theStack)
663 {
664         if (theStack && theStack->head) {
665                 device_t *temp = theStack->head;
666                 theStack->head = theStack->head->next;
667
668                 free(temp->device_id);
669                 free(temp->operational_state);
670                 free(temp);
671                 theStack->stack_size--;
672         }
673 }
674
675 int get_netconf_port_next(device_stack_t *theStack)
676 {
677         if (theStack && theStack->stack_size > 0) {
678                 return theStack->head->netconf_port + NETCONF_CONNECTIONS_PER_DEVICE;
679         }
680
681         return get_netconf_port_base();
682 }
683
684 int get_netconf_port_base()
685 {
686         int netconf_port_base = 0, rc;
687
688         char *netconf_base_string = getenv("NETCONF_BASE");
689
690         if (netconf_base_string != NULL)
691         {
692                 rc = sscanf(netconf_base_string, "%d", &netconf_port_base);
693                 if (rc != 1)
694                 {
695                         printf("Could not get the NETCONF_BASE port! Using the default 30.000...\n");
696                         netconf_port_base = 30000;
697                 }
698         }
699
700         return netconf_port_base;
701 }
702
703
704 char *get_id_last_device(device_stack_t *theStack)
705 {
706         if (theStack && theStack->head) {
707                 return theStack->head->device_id;
708         }
709         return NULL;
710 }
711
712 int get_current_number_of_mounted_devices(device_stack_t *theStack)
713 {
714         int mounted_devices = 0;
715
716         if (theStack && theStack->head)
717         {
718                 device_t *current_device = theStack->head;
719
720                 while (current_device != NULL)
721                 {
722                         if (current_device->is_mounted)
723                         {
724                                 mounted_devices++;
725                         }
726                         current_device = current_device->next;
727                 }
728         }
729
730         return mounted_devices;
731 }
732
733 int get_current_number_of_devices(device_stack_t *theStack)
734 {
735         struct MemoryStruct curl_response_mem;
736
737         curl_response_mem.memory = malloc(1);  /* will be grown as needed by the realloc above */
738         curl_response_mem.size = 0;    /* no data at this point */
739
740         CURLcode res;
741
742         curl_easy_reset(curl);
743         set_curl_common_info();
744
745         char url[100];
746         sprintf(url, "http:/v%s/containers/json?all=true&filters={\"label\":[\"NTS\"],\"status\":[\"running\"]}",
747                         getenv("DOCKER_ENGINE_VERSION"));
748
749         curl_easy_setopt(curl, CURLOPT_URL, url);
750
751         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
752         curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
753
754         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
755
756         res = curl_easy_perform(curl);
757
758         if (res != CURLE_OK)
759         {
760                 return SR_ERR_OPERATION_FAILED;
761         }
762         else
763         {
764                 cJSON *json_response = cJSON_Parse(curl_response_mem.memory);
765
766                 printf("%lu bytes retrieved\n", (unsigned long)curl_response_mem.size);
767
768                 if (json_response == NULL || !cJSON_IsArray(json_response))
769                 {
770                         printf("Could not parse JSON response for url=\"%s\"\n", url);
771                         return SR_ERR_OPERATION_FAILED;
772                 }
773
774                 int num_of_devices = cJSON_GetArraySize(json_response);
775                 cJSON_Delete(json_response);
776
777                 return num_of_devices;
778         }
779
780         return 0;
781 }
782
783 static int set_operational_state_of_device(device_stack_t *theStack, char *device_id, char *operational_state)
784 {
785         if (theStack && theStack->head)
786         {
787                 device_t *current_device = theStack->head;
788
789                 while (current_device != NULL)
790                 {
791                         if (strcmp(current_device->device_id, device_id) == 0)
792                         {
793                                 free(current_device->operational_state);
794                                 current_device->operational_state = strdup(operational_state);
795
796                                 return SR_ERR_OK;
797                         }
798
799                         current_device = current_device->next;
800                 }
801         }
802
803         printf("Could not find device with uuid=\"%s\"\n", device_id);
804         return SR_ERR_OPERATION_FAILED;
805 }
806
807 char* get_docker_container_operational_state(device_stack_t *theStack, char *container_id)
808 {
809         if (theStack && theStack->head)
810         {
811                 device_t *current_device = theStack->head;
812
813                 while (current_device != NULL)
814                 {
815                         if (strcmp(current_device->device_id, container_id) == 0)
816                         {
817                                 return current_device->operational_state;
818                         }
819
820                         current_device = current_device->next;
821                 }
822         }
823
824         return NULL;
825 }
826
827 int start_device(device_stack_t *theStack)
828 {
829         int rc = SR_ERR_OK;
830         static cJSON* managerBindings = NULL;
831
832         if (managerBindings == NULL)
833         {
834                 managerBindings = get_docker_container_bindings();
835         }
836
837         int netconf_base = get_netconf_port_next(theStack);
838
839         char *dev_id = create_docker_container_curl(netconf_base, managerBindings);
840
841         push_device(theStack, dev_id, netconf_base);
842
843         rc = start_docker_container_curl(dev_id);
844         if (rc != SR_ERR_OK)
845         {
846                 printf("Could not start device with device_id=\"%s\"\n", dev_id);
847         }
848
849         if (dev_id) {
850                 free(dev_id);
851         }
852
853         return SR_ERR_OK;
854 }
855
856 int _init_curl()
857 {
858         curl = curl_easy_init();
859
860         if (curl == NULL) {
861                 printf("cURL initialization error! Aborting call!\n");
862                 return SR_ERR_OPERATION_FAILED;
863         }
864
865         return SR_ERR_OK;
866 }
867
868 int cleanup_curl()
869 {
870         if (curl != NULL)
871         {
872                 curl_easy_cleanup(curl);
873         }
874
875         return SR_ERR_OK;
876 }
877
878 int _init_curl_odl()
879 {
880         curl_odl = curl_easy_init();
881
882         if (curl_odl == NULL) {
883                 printf("cURL initialization error! Aborting call!\n");
884                 return SR_ERR_OPERATION_FAILED;
885         }
886
887         return SR_ERR_OK;
888 }
889
890 int cleanup_curl_odl()
891 {
892         if (curl_odl != NULL)
893         {
894                 curl_easy_cleanup(curl_odl);
895         }
896
897         return SR_ERR_OK;
898 }
899
900 int stop_device(device_stack_t *theStack)
901 {
902         int rc = SR_ERR_OK;
903         char *last_id = get_id_last_device(theStack);
904
905         rc = kill_and_remove_docker_container_curl(last_id);
906         if (rc != SR_ERR_OK)
907         {
908                 printf("Could not kill and remove docker container with uuid=\"%s\"\n", last_id);
909         }
910
911     rc = removeDeviceEntryFromStatusFile(last_id);
912     if (rc != SR_ERR_OK)
913     {
914         printf("Could not remove entry from status file for uuid=\"%s\"\n", last_id);
915     }
916
917         pop_device(theStack);
918
919         return SR_ERR_OK;
920 }
921
922 int mount_device(device_stack_t *theStack, controller_t controller_details)
923 {
924         int rc;
925
926         if (theStack && theStack->head)
927         {
928                 device_t *current_device = theStack->head;
929                 while (current_device != NULL && current_device->is_mounted == true)
930                 {
931                         printf("Device \"%s\" is already mounted, skipping...\n", current_device->device_id);
932                         current_device = current_device->next;
933                 }
934
935                 if (current_device != NULL)
936                 {
937                         printf("Sending mount device for device \"%s\"...\n", current_device->device_id);
938                         rc = send_mount_device(current_device, controller_details);
939                         if (rc != SR_ERR_OK)
940                         {
941                                 return SR_ERR_OPERATION_FAILED;
942                         }
943                 }
944         }
945
946         return SR_ERR_OK;
947 }
948
949 int unmount_device(device_stack_t *theStack, controller_t controller_list)
950 {
951         int rc;
952
953         if (theStack && theStack->head)
954         {
955                 device_t *current_device = theStack->head;
956                 while (current_device != NULL && current_device->is_mounted == false)
957                 {
958                         printf("Device \"%s\" is already unmounted, skipping...\n", current_device->device_id);
959                         current_device = current_device->next;
960                 }
961
962                 if (current_device != NULL)
963                 {
964                         printf("Sending unmount device for device \"%s\"...\n", current_device->device_id);
965                         rc = send_unmount_device(current_device, controller_list);
966                         if (rc != SR_ERR_OK)
967                         {
968                                 return SR_ERR_OPERATION_FAILED;
969                         }
970                 }
971         }
972
973         return SR_ERR_OK;
974 }
975
976 int get_docker_containers_operational_state_curl(device_stack_t *theStack)
977 {
978         int rc = SR_ERR_OK;
979         struct MemoryStruct curl_response_mem;
980
981         curl_response_mem.memory = malloc(1);  /* will be grown as needed by the realloc above */
982         curl_response_mem.size = 0;    /* no data at this point */
983
984         CURLcode res;
985
986         curl_easy_reset(curl);
987         set_curl_common_info();
988
989         char url[100];
990         sprintf(url, "http:/v%s/containers/json?all=true&filters={\"label\":[\"NTS\"]}", getenv("DOCKER_ENGINE_VERSION"));
991
992         curl_easy_setopt(curl, CURLOPT_URL, url);
993
994     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
995     curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
996
997         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
998
999         res = curl_easy_perform(curl);
1000
1001         if (res != CURLE_OK)
1002         {
1003                 return SR_ERR_OPERATION_FAILED;
1004         }
1005         else
1006         {
1007                 cJSON *json_response = cJSON_Parse(curl_response_mem.memory);
1008                 const cJSON *container = NULL;
1009
1010                 printf("%lu bytes retrieved\n", (unsigned long)curl_response_mem.size);
1011
1012                 if (json_response == NULL || !cJSON_IsArray(json_response))
1013                 {
1014                         printf("Could not parse JSON response for url=\"%s\"\n", url);
1015                         return SR_ERR_OPERATION_FAILED;
1016                 }
1017
1018             cJSON_ArrayForEach(container, json_response)
1019             {
1020                 cJSON *container_id_long = cJSON_GetObjectItemCaseSensitive(container, "Id");
1021                 cJSON *state = cJSON_GetObjectItemCaseSensitive(container, "State");
1022
1023                         if (cJSON_IsString(container_id_long) && (container_id_long->valuestring != NULL))
1024                         {
1025                                 char container_id_short[13];
1026
1027                                 memset(container_id_short, '\0', sizeof(container_id_short));
1028                                 strncpy(container_id_short, container_id_long->valuestring, 12);
1029
1030                                 if (cJSON_IsString(state) && (state->valuestring != NULL))
1031                                 {
1032                                         rc = set_operational_state_of_device(theStack, container_id_short, state->valuestring);
1033                                         if (rc != SR_ERR_OK)
1034                                         {
1035                                                 printf("Could not set the operational state for the device with uuid=\"%s\"\n", container_id_short);
1036                                                 return SR_ERR_OPERATION_FAILED;
1037                                         }
1038                                 }
1039                         }
1040             }
1041
1042             cJSON_Delete(json_response);
1043         }
1044
1045         return SR_ERR_OK;
1046 }
1047
1048 char* get_docker_container_resource_stats(device_stack_t *theStack)
1049 {
1050         char line[LINE_BUFSIZE];
1051         int linenr;
1052         FILE *pipe;
1053
1054         /* Get a pipe where the output from the scripts comes in */
1055         char script[200];
1056         sprintf(script, "%s/docker_stats.sh", getenv("SCRIPTS_DIR"));
1057
1058         pipe = popen(script, "r");
1059         if (pipe == NULL) {  /* check for errors */
1060                 printf("Could not open script.\n");
1061                 return NULL;        /* return with exit code indicating error */
1062         }
1063
1064         /* Read script output from the pipe line by line */
1065         linenr = 1;
1066         while (fgets(line, LINE_BUFSIZE, pipe) != NULL) {
1067                 printf("Script output line %d: %s", linenr, line);
1068                 ++linenr;
1069
1070                 pclose(pipe); /* Close the pipe */
1071                 return strdup(line);
1072         }
1073
1074         /* Once here, out of the loop, the script has ended. */
1075         pclose(pipe); /* Close the pipe */
1076         return NULL;     /* return with exit code indicating success. */
1077 }
1078
1079 int notification_delay_period_changed(sr_val_t *val, size_t count)
1080 {
1081         char *stringConfiguration = readConfigFileInString();
1082
1083         if (stringConfiguration == NULL)
1084         {
1085                 printf("Could not read configuration file!\n");
1086                 return SR_ERR_OPERATION_FAILED;
1087         }
1088
1089         cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
1090         if (jsonConfig == NULL)
1091         {
1092                 free(stringConfiguration);
1093                 const char *error_ptr = cJSON_GetErrorPtr();
1094                 if (error_ptr != NULL)
1095                 {
1096                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
1097                 }
1098                 return SR_ERR_OPERATION_FAILED;
1099         }
1100         //we don't need the string anymore
1101         free(stringConfiguration);
1102         stringConfiguration = NULL;
1103
1104         cJSON *notifConfig = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
1105         if (!cJSON_IsObject(notifConfig))
1106         {
1107                 printf("Configuration JSON is not as expected: notification-config is not an object");
1108                 cJSON_Delete(jsonConfig);
1109                 return SR_ERR_OPERATION_FAILED;
1110         }
1111
1112         cJSON *faultNotifDelay = cJSON_GetObjectItemCaseSensitive(notifConfig, "fault-notification-delay-period");
1113         if (!cJSON_IsArray(faultNotifDelay))
1114         {
1115                 printf("Configuration JSON is not as expected: fault-notification-delay-period is not an array.");
1116                 cJSON_Delete(jsonConfig);
1117                 return SR_ERR_OPERATION_FAILED;
1118         }
1119
1120     cJSON_DeleteItemFromObject(notifConfig, "fault-notification-delay-period");
1121
1122     faultNotifDelay = NULL;
1123
1124     faultNotifDelay = cJSON_CreateArray();
1125     if (faultNotifDelay == NULL) 
1126     {
1127         cJSON_Delete(jsonConfig);
1128                 return SR_ERR_OPERATION_FAILED;
1129     }
1130     cJSON_AddItemToObject(notifConfig, "fault-notification-delay-period", faultNotifDelay);
1131
1132     if (val != NULL && count > 0)
1133     {
1134         cJSON *arrayEntry = NULL;
1135         for (size_t i=0; i<count; ++i)
1136         {
1137             arrayEntry = cJSON_CreateNumber(val[i].data.uint32_val);
1138             if (arrayEntry == NULL) 
1139             {
1140                 cJSON_Delete(jsonConfig);
1141                 return SR_ERR_OPERATION_FAILED;
1142             }
1143             cJSON_AddItemToArray(faultNotifDelay, arrayEntry);
1144         }
1145     }
1146     else
1147     {
1148         cJSON *arrayEntry =  cJSON_CreateNumber(0);
1149         if (arrayEntry == NULL) 
1150         {
1151             cJSON_Delete(jsonConfig);
1152             return SR_ERR_OPERATION_FAILED;
1153         }
1154         cJSON_AddItemToArray(faultNotifDelay, arrayEntry);
1155     }
1156
1157         //writing the new JSON to the configuration file
1158         stringConfiguration = cJSON_Print(jsonConfig);
1159         writeConfigFile(stringConfiguration);
1160
1161         cJSON_Delete(jsonConfig);
1162
1163         return SR_ERR_OK;
1164 }
1165
1166 int ves_heartbeat_period_changed(int period)
1167 {
1168         char *stringConfiguration = readConfigFileInString();
1169
1170         if (stringConfiguration == NULL)
1171         {
1172                 printf("Could not read configuration file!\n");
1173                 return SR_ERR_OPERATION_FAILED;
1174         }
1175
1176         cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
1177         if (jsonConfig == NULL)
1178         {
1179                 free(stringConfiguration);
1180                 const char *error_ptr = cJSON_GetErrorPtr();
1181                 if (error_ptr != NULL)
1182                 {
1183                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
1184                 }
1185                 return SR_ERR_OPERATION_FAILED;
1186         }
1187         //we don't need the string anymore
1188         free(stringConfiguration);
1189         stringConfiguration = NULL;
1190
1191         cJSON *notifConfig = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
1192         if (!cJSON_IsObject(notifConfig))
1193         {
1194                 printf("Configuration JSON is not as expected: notification-config is not an object");
1195                 cJSON_Delete(jsonConfig);
1196                 return SR_ERR_OPERATION_FAILED;
1197         }
1198
1199         cJSON *vesHeartbeatPeriod = cJSON_GetObjectItemCaseSensitive(notifConfig, "ves-heartbeat-period");
1200         if (!cJSON_IsNumber(vesHeartbeatPeriod))
1201         {
1202                 printf("Configuration JSON is not as expected: ves-heartbeat-period is not an object");
1203                 cJSON_Delete(jsonConfig);
1204                 return SR_ERR_OPERATION_FAILED;
1205         }
1206
1207         //we set the value of the fault-notification-delay-period object
1208         cJSON_SetNumberValue(vesHeartbeatPeriod, period);
1209
1210         //writing the new JSON to the configuration file
1211         stringConfiguration = cJSON_Print(jsonConfig);
1212         writeConfigFile(stringConfiguration);
1213
1214         cJSON_Delete(jsonConfig);
1215
1216         return SR_ERR_OK;
1217 }
1218
1219 static int add_keystore_entry_odl(char *url, char *credentials)
1220 {
1221         CURLcode res;
1222
1223         curl_easy_reset(curl_odl);
1224         set_curl_common_info_odl();
1225
1226         char url_for_curl[200];
1227         sprintf(url_for_curl, "%s", url);
1228
1229         curl_easy_setopt(curl_odl, CURLOPT_URL, url_for_curl);
1230
1231         char post_data_xml[2000];
1232
1233         sprintf(post_data_xml,
1234                         "<input xmlns=\"urn:opendaylight:netconf:keystore\">"
1235                         "<key-credential>"
1236                         "<key-id>device-key</key-id>"
1237                         "<private-key>MIIEpAIBAAKCAQEAueCQaNQWoNmFK6LKu1p8U8ZWdWg/PvDdLsJyzfzl/Qw4UA68"
1238                         "SfFNaY06zZl8QB9W02nr5kWeeMY0VA3adrPgOlvfx3oWlFbkETnMaN4OT3WTQ0Wt"
1239                         "6jAWZDzVfopwpJPAzRPxACDftIqFGagYcF32hZlVNqqnVdbXh0S0EViweqp/dbG4"
1240                         "VDUHSNVbglc+u4UbEzNIFXMdEFsJZpkynOmSiTsIATqIhb+2srkVgLwhfkC2qkuH"
1241                         "QwAHdubuB07ObM2z01UhyEdDvEYGHwtYAGDBL2TAcsI0oGeVkRyuOkV0QY0UN7UE"
1242                         "FI1yTYw+xZ42HgFx3uGwApCImxhbj69GBYWFqwIDAQABAoIBAQCZN9kR8DGu6V7y"
1243                         "t0Ax68asL8O5B/OKaHWKQ9LqpVrXmikZJOxkbzoGldow/CIFoU+q+Zbwu9aDa65a"
1244                         "0wiP7Hoa4Py3q5XNNUrOQDyU/OYC7cI0I83WS0lJ2zOJGYj8wKae5Z81IeQFKGHK"
1245                         "4lsy1OGPAvPRGh7RjUUgRavA2MCwe07rWRuDb/OJFe4Oh56UMEjwMiNBtMNtncog"
1246                         "j1vr/qgRJdf9tf0zlJmLvUJ9+HSFFV9I/97LJyFhb95gAfHkjdVroLVgT3Cho+4P"
1247                         "WtZaKCIGD0OwfOG2nLV4leXvRUk62/LMlB8NI9+JF7Xm+HCKbaWHNWC7mvWSLV58"
1248                         "Zl4AbUWRAoGBANyJ6SFHFRHSPDY026SsdMzXR0eUxBAK7G70oSBKKhY+O1j0ocLE"
1249                         "jI2krHJBhHbLlnvJVyMUaCUOTS5m0uDw9hgSsAqeSL3hL38kxVZw+KNG9Ouno1Fl"
1250                         "KnE/xXHlPQyeGs/P8nAMzHZxQtEsQdQayJEhK2XXHTsy7Q3MxDisfVJ1AoGBANfD"
1251                         "34gB+OMx6pwj7zk3qWbYXSX8xjCZMR0ciko+h4xeMP2N8B0oyoqC+v1ABMAtJ3wG"
1252                         "sGZd0hV9gwM7OUM3SEwkn6oeg1GemWLcn4rlSmTnZc4aeVwrEWlnSNFX3s4g9l4u"
1253                         "k8Ugu4MVJYqH8HuDQ5Ggl6/QAwPzMSEdCW0O+jOfAoGAIBRbegC5+t6m7Yegz4Ja"
1254                         "dxV1g98K6f58x+MDsQu4tYWV4mmrQgaPH2dtwizvlMwmdpkh+LNWNtWuumowkJHc"
1255                         "akIFo3XExQIFg6wYnGtQb4e5xrGa2xMpKlIJaXjb+YLiCYqJDG2ALFZrTrvuU2kV"
1256                         "9a5qfqTc1qigvNolTM0iaaUCgYApmrZWhnLUdEKV2wP813PNxfioI4afxlpHD8LG"
1257                         "sCn48gymR6E+Lihn7vuwq5B+8fYEH1ISWxLwW+RQUjIneNhy/jjfV8TgjyFqg7or"
1258                         "0Sy4KjpiNI6kLBXOakELRNNMkeSPopGR2E7v5rr3bGD9oAD+aqX1G7oJH/KgPPYd"
1259                         "Vl7+ZwKBgQDcHyWYrimjyUgKaQD2GmoO9wdcJYQ59ke9K+OuGlp4ti5arsi7N1tP"
1260                         "B4f09aeELM2ASIuk8Q/Mx0jQFnm8lzRFXdewgvdPoZW/7VufM9O7dGPOc41cm2Dh"
1261                         "yrTcXx/VmUBb+/fnXVEgCv7gylp/wtdTGHQBQJHR81jFBz0lnLj+gg==</private-key>"
1262                         "<passphrase></passphrase>"
1263                         "</key-credential>"
1264                         "</input>");
1265
1266         printf("Post data:\n%s\n", post_data_xml);
1267
1268         curl_easy_setopt(curl_odl, CURLOPT_POSTFIELDS, post_data_xml);
1269         curl_easy_setopt(curl_odl, CURLOPT_CUSTOMREQUEST, "POST");
1270         curl_easy_setopt(curl_odl, CURLOPT_USERPWD, credentials);
1271
1272         res = curl_easy_perform(curl_odl);
1273         if (res != CURLE_OK)
1274         {
1275                 printf("cURL failed to url=%s\n", url_for_curl);
1276         }
1277
1278         long http_response_code = 0;
1279         curl_easy_getinfo (curl_odl, CURLINFO_RESPONSE_CODE, &http_response_code);
1280         if (http_response_code >= 200 && http_response_code <= 226 && http_response_code != CURLE_ABORTED_BY_CALLBACK)
1281         {
1282                 printf("cURL succeeded to url=%s\n", url_for_curl);
1283         }
1284         else
1285         {
1286                 printf("cURL to url=%s failed with code=%ld\n", url_for_curl, http_response_code);
1287                 return SR_ERR_OPERATION_FAILED;
1288         }
1289
1290         return SR_ERR_OK;
1291 }
1292
1293 static int add_private_key_odl(char *url, char *credentials)
1294 {
1295         CURLcode res;
1296
1297         curl_easy_reset(curl_odl);
1298         set_curl_common_info_odl();
1299
1300         char url_for_curl[200];
1301         sprintf(url_for_curl, "%s", url);
1302
1303         curl_easy_setopt(curl_odl, CURLOPT_URL, url_for_curl);
1304
1305         char post_data_xml[4000];
1306
1307         sprintf(post_data_xml,
1308                         "<input xmlns=\"urn:opendaylight:netconf:keystore\">"
1309                         "<private-key>"
1310                         "<name>device-key</name>"
1311                         "<data>MIIEpAIBAAKCAQEAueCQaNQWoNmFK6LKu1p8U8ZWdWg/PvDdLsJyzfzl/Qw4UA68SfFNaY06zZl8QB9W02nr5kWeeMY0VA3adrPgOlvfx3oWlFbkETnMaN4OT3WTQ0Wt6jAWZDzVfopwpJPAzRPxACDftIqFGagYcF32hZlVNqqnVdbXh0S0EViweqp/dbG4VDUHSNVbglc+u4UbEzNIFXMdEFsJZpkynOmSiTsIATqIhb+2srkVgLwhfkC2qkuHQwAHdubuB07ObM2z01UhyEdDvEYGHwtYAGDBL2TAcsI0oGeVkRyuOkV0QY0UN7UEFI1yTYw+xZ42HgFx3uGwApCImxhbj69GBYWFqwIDAQABAoIBAQCZN9kR8DGu6V7yt0Ax68asL8O5B/OKaHWKQ9LqpVrXmikZJOxkbzoGldow/CIFoU+q+Zbwu9aDa65a0wiP7Hoa4Py3q5XNNUrOQDyU/OYC7cI0I83WS0lJ2zOJGYj8wKae5Z81IeQFKGHK4lsy1OGPAvPRGh7RjUUgRavA2MCwe07rWRuDb/OJFe4Oh56UMEjwMiNBtMNtncogj1vr/qgRJdf9tf0zlJmLvUJ9+HSFFV9I/97LJyFhb95gAfHkjdVroLVgT3Cho+4PWtZaKCIGD0OwfOG2nLV4leXvRUk62/LMlB8NI9+JF7Xm+HCKbaWHNWC7mvWSLV58Zl4AbUWRAoGBANyJ6SFHFRHSPDY026SsdMzXR0eUxBAK7G70oSBKKhY+O1j0ocLEjI2krHJBhHbLlnvJVyMUaCUOTS5m0uDw9hgSsAqeSL3hL38kxVZw+KNG9Ouno1FlKnE/xXHlPQyeGs/P8nAMzHZxQtEsQdQayJEhK2XXHTsy7Q3MxDisfVJ1AoGBANfD34gB+OMx6pwj7zk3qWbYXSX8xjCZMR0ciko+h4xeMP2N8B0oyoqC+v1ABMAtJ3wGsGZd0hV9gwM7OUM3SEwkn6oeg1GemWLcn4rlSmTnZc4aeVwrEWlnSNFX3s4g9l4uk8Ugu4MVJYqH8HuDQ5Ggl6/QAwPzMSEdCW0O+jOfAoGAIBRbegC5+t6m7Yegz4JadxV1g98K6f58x+MDsQu4tYWV4mmrQgaPH2dtwizvlMwmdpkh+LNWNtWuumowkJHcakIFo3XExQIFg6wYnGtQb4e5xrGa2xMpKlIJaXjb+YLiCYqJDG2ALFZrTrvuU2kV9a5qfqTc1qigvNolTM0iaaUCgYApmrZWhnLUdEKV2wP813PNxfioI4afxlpHD8LGsCn48gymR6E+Lihn7vuwq5B+8fYEH1ISWxLwW+RQUjIneNhy/jjfV8TgjyFqg7or0Sy4KjpiNI6kLBXOakELRNNMkeSPopGR2E7v5rr3bGD9oAD+aqX1G7oJH/KgPPYdVl7+ZwKBgQDcHyWYrimjyUgKaQD2GmoO9wdcJYQ59ke9K+OuGlp4ti5arsi7N1tPB4f09aeELM2ASIuk8Q/Mx0jQFnm8lzRFXdewgvdPoZW/7VufM9O7dGPOc41cm2DhyrTcXx/VmUBb+/fnXVEgCv7gylp/wtdTGHQBQJHR81jFBz0lnLj+gg==</data>"
1312                         "<certificate-chain>MIIECTCCAvGgAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBjDELMAkGA1UEBhMCQ1oxFjAUBgNVBAgMDVNvdXRoIE1vcmF2aWExDTALBgNVBAcMBEJybm8xDzANBgNVBAoMBkNFU05FVDEMMAoGA1UECwwDVE1DMRMwEQYDVQQDDApleGFtcGxlIENBMSIwIAYJKoZIhvcNAQkBFhNleGFtcGxlY2FAbG9jYWxob3N0MB4XDTE1MDczMDA3MjcxOFoXDTM1MDcyNTA3MjcxOFowgYUxCzAJBgNVBAYTAkNaMRYwFAYDVQQIDA1Tb3V0aCBNb3JhdmlhMQ8wDQYDVQQKDAZDRVNORVQxDDAKBgNVBAsMA1RNQzEXMBUGA1UEAwwOZXhhbXBsZSBjbGllbnQxJjAkBgkqhkiG9w0BCQEWF2V4YW1wbGVjbGllbnRAbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAueCQaNQWoNmFK6LKu1p8U8ZWdWg/PvDdLsJyzfzl/Qw4UA68SfFNaY06zZl8QB9W02nr5kWeeMY0VA3adrPgOlvfx3oWlFbkETnMaN4OT3WTQ0Wt6jAWZDzVfopwpJPAzRPxACDftIqFGagYcF32hZlVNqqnVdbXh0S0EViweqp/dbG4VDUHSNVbglc+u4UbEzNIFXMdEFsJZpkynOmSiTsIATqIhb+2srkVgLwhfkC2qkuHQwAHdubuB07ObM2z01UhyEdDvEYGHwtYAGDBL2TAcsI0oGeVkRyuOkV0QY0UN7UEFI1yTYw+xZ42HgFx3uGwApCImxhbj69GBYWFqwIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUXGpLeLnh2cSDARAVA7KrBxGYpo8wHwYDVR0jBBgwFoAUc1YQIqjZsHVwlea0AB4N+ilNI2gwDQYJKoZIhvcNAQELBQADggEBAJPV3RTXFRtNyOU4rjPpYeBAIAFp2aqGc4t2J1c7oPp/1n+lZvjnwtlJpZHxMM783e2ryDQ6dkvXDf8kpwKlg3U3mkJ3xKkDdWrM4QwghXdCN519aa9qmu0zdFL+jUAaWlQ5tsceOrvbusCcbMqiFGk/QfpHqPv52SVWbYyUx7IX7DE+UjgsLHycfV/tlcx4ZE6soTzl9VdgSL/zmzG3rjsr58J80rXckLgBhvijgBlIAJvWfC7D0vaouvBInSFXymdPVoUDZ30cdGLf+hI/i/TfsEMOinLrXVdkSGNo6FXAHKSvXeB9oFKSzhQ7OPyRyqvEPycUSw/qD6FVr80oDDc=</certificate-chain>"
1313                         "</private-key>"
1314                         "</input>");
1315
1316         printf("Post data:\n%s\n", post_data_xml);
1317
1318         curl_easy_setopt(curl_odl, CURLOPT_POSTFIELDS, post_data_xml);
1319         curl_easy_setopt(curl_odl, CURLOPT_CUSTOMREQUEST, "POST");
1320         curl_easy_setopt(curl_odl, CURLOPT_USERPWD, credentials);
1321
1322         res = curl_easy_perform(curl_odl);
1323         if (res != CURLE_OK)
1324         {
1325                 printf("cURL failed to url=%s\n", url_for_curl);
1326         }
1327
1328         long http_response_code = 0;
1329         curl_easy_getinfo (curl_odl, CURLINFO_RESPONSE_CODE, &http_response_code);
1330         if (http_response_code >= 200 && http_response_code <= 226 && http_response_code != CURLE_ABORTED_BY_CALLBACK)
1331         {
1332                 printf("cURL succeeded to url=%s\n", url_for_curl);
1333         }
1334         else
1335         {
1336                 printf("cURL to url=%s failed with code=%ld\n", url_for_curl, http_response_code);
1337                 return SR_ERR_OPERATION_FAILED;
1338         }
1339
1340         return SR_ERR_OK;
1341 }
1342
1343 static int add_trusted_ca_odl(char *url, char *credentials)
1344 {
1345         CURLcode res;
1346
1347         curl_easy_reset(curl_odl);
1348         set_curl_common_info_odl();
1349
1350         char url_for_curl[200];
1351         sprintf(url_for_curl, "%s", url);
1352
1353         curl_easy_setopt(curl_odl, CURLOPT_URL, url_for_curl);
1354
1355         char post_data_xml[2000];
1356
1357         sprintf(post_data_xml,
1358                         "<input xmlns=\"urn:opendaylight:netconf:keystore\">"
1359                         "<trusted-certificate>"
1360                         "<name>test_trusted_cert</name>"
1361                         "<certificate>MIID7TCCAtWgAwIBAgIJAMtE1NGAR5KoMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJDWjEWMBQGA1UECAwNU291dGggTW9yYXZpYTENMAsGA1UEBwwEQnJubzEPMA0GA1UECgwGQ0VTTkVUMQwwCgYDVQQLDANUTUMxEzARBgNVBAMMCmV4YW1wbGUgQ0ExIjAgBgkqhkiG9w0BCQEWE2V4YW1wbGVjYUBsb2NhbGhvc3QwHhcNMTQwNzI0MTQxOTAyWhcNMjQwNzIxMTQxOTAyWjCBjDELMAkGA1UEBhMCQ1oxFjAUBgNVBAgMDVNvdXRoIE1vcmF2aWExDTALBgNVBAcMBEJybm8xDzANBgNVBAoMBkNFU05FVDEMMAoGA1UECwwDVE1DMRMwEQYDVQQDDApleGFtcGxlIENBMSIwIAYJKoZIhvcNAQkBFhNleGFtcGxlY2FAbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArD3TDHPAMT2Z84orK4lMlarbgooIUCcRZyLe+QM+8KY8Hn+mGaxPEOTSL3ywszqefB/Utm2hPKLHX684iRC14ID9WDGHxPjvoPArhgFhfV+qnPfxKTgxZC12uOj4u1V9y+SkTCocFbRfXVBGpojrBuDHXkDMDEWNvr8/52YCv7bGaiBwUHolcLCUbmtKILCG0RNJyTaJpXQdAeq5Z1SJotpbfYFFtAXB32hVoLug1dzl2tjG9sb1wq3QaDExcbC5w6P65qOkNoyym9ne6QlQagCqVDyFn3vcqkRaTjvZmxauCeUxXgJoXkyWcm0lM1KMHdoTArmchw2Dz0yHHSyDAQIDAQABo1AwTjAdBgNVHQ4EFgQUc1YQIqjZsHVwlea0AB4N+ilNI2gwHwYDVR0jBBgwFoAUc1YQIqjZsHVwlea0AB4N+ilNI2gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAI/1KH60qnw9Xs2RGfi0/IKf5EynXt4bQX8EIyVKwSkYKe04zZxYfLIl/Q2HOPYoFmm3daj5ddr0ZS1i4p4fTUhstjsYWvXs3W/HhVmFUslakkn3PrswhP77fCk6eEJLxdfyJ1C7Uudq2m1isZbKih+XF0mG1LxJaDMocSz4eAya7M5brwjy8DoOmA1TnLQFCVcpn+sCr7VC4wE/JqxyVhBCk/MuGqqM3B1j90bGFZ112ZOecyE0EDSr6IbiRBtmeNbEwOFjKXhNLYdxpBZ9D8A/368OckZkCrVLGuJNxK9UwCVTe8IhotHUqU9EqFDmxdV8oIdU/OzUwwNPA/Bd/9g==</certificate>"
1362                         "</trusted-certificate>"
1363                         "</input>");
1364
1365         printf("Post data:\n%s\n", post_data_xml);
1366
1367         curl_easy_setopt(curl_odl, CURLOPT_POSTFIELDS, post_data_xml);
1368         curl_easy_setopt(curl_odl, CURLOPT_CUSTOMREQUEST, "POST");
1369         curl_easy_setopt(curl_odl, CURLOPT_USERPWD, credentials);
1370
1371         res = curl_easy_perform(curl_odl);
1372         if (res != CURLE_OK)
1373         {
1374                 printf("cURL failed to url=%s\n", url_for_curl);
1375         }
1376
1377         long http_response_code = 0;
1378         curl_easy_getinfo (curl_odl, CURLINFO_RESPONSE_CODE, &http_response_code);
1379         if (http_response_code >= 200 && http_response_code <= 226 && http_response_code != CURLE_ABORTED_BY_CALLBACK)
1380         {
1381                 printf("cURL succeeded to url=%s\n", url_for_curl);
1382         }
1383         else
1384         {
1385                 printf("cURL to url=%s failed with code=%ld\n", url_for_curl, http_response_code);
1386                 return SR_ERR_OPERATION_FAILED;
1387         }
1388
1389         return SR_ERR_OK;
1390 }
1391
1392 int add_key_pair_to_odl(controller_t *controller_list, int controller_list_size)
1393 {
1394         int rc = SR_ERR_OK;
1395
1396         rc = add_keystore_entry_odl(controller_list[0].url_for_keystore_add, controller_list[0].credentials);
1397         if (rc != SR_ERR_OK)
1398         {
1399                 printf("Failed to add keystore entry to ODL.\n");
1400         }
1401
1402         rc = add_private_key_odl(controller_list[0].url_for_private_key_add, controller_list[0].credentials);
1403         if (rc != SR_ERR_OK)
1404         {
1405                 printf("Failed to add private key entry to ODL.\n");
1406         }
1407
1408         rc = add_trusted_ca_odl(controller_list[0].url_for_trusted_ca_add, controller_list[0].credentials);
1409         if (rc != SR_ERR_OK)
1410         {
1411                 printf("Failed to add trusted CA entry to ODL.\n");
1412         }
1413
1414         return SR_ERR_OK;
1415 }
1416
1417 int ves_ip_changed(char *new_ip)
1418 {
1419         char *stringConfiguration = readConfigFileInString();
1420
1421         if (stringConfiguration == NULL)
1422         {
1423                 printf("Could not read configuration file!\n");
1424                 return SR_ERR_OPERATION_FAILED;
1425         }
1426
1427         cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
1428         if (jsonConfig == NULL)
1429         {
1430                 free(stringConfiguration);
1431                 const char *error_ptr = cJSON_GetErrorPtr();
1432                 if (error_ptr != NULL)
1433                 {
1434                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
1435                 }
1436                 return SR_ERR_OPERATION_FAILED;
1437         }
1438         //we don't need the string anymore
1439         free(stringConfiguration);
1440         stringConfiguration = NULL;
1441
1442         cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
1443         if (!cJSON_IsObject(vesDetails))
1444         {
1445                 printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
1446                 cJSON_Delete(jsonConfig);
1447                 return SR_ERR_OPERATION_FAILED;
1448         }
1449
1450         cJSON *vesIp = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-ip");
1451         if (!cJSON_IsString(vesIp))
1452         {
1453                 printf("Configuration JSON is not as expected: ves-endpoint-ip is not a string");
1454                 cJSON_Delete(jsonConfig);
1455                 return SR_ERR_OPERATION_FAILED;
1456         }
1457
1458         //we set the value of the fault-notification-delay-period object
1459         cJSON_ReplaceItemInObject(vesDetails, "ves-endpoint-ip", cJSON_CreateString(new_ip));
1460
1461         //writing the new JSON to the configuration file
1462         stringConfiguration = cJSON_Print(jsonConfig);
1463         writeConfigFile(stringConfiguration);
1464
1465         cJSON_Delete(jsonConfig);
1466
1467         return SR_ERR_OK;
1468 }
1469
1470 int ves_port_changed(int new_port)
1471 {
1472         char *stringConfiguration = readConfigFileInString();
1473
1474         if (stringConfiguration == NULL)
1475         {
1476                 printf("Could not read configuration file!\n");
1477                 return SR_ERR_OPERATION_FAILED;
1478         }
1479
1480         cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
1481         if (jsonConfig == NULL)
1482         {
1483                 free(stringConfiguration);
1484                 const char *error_ptr = cJSON_GetErrorPtr();
1485                 if (error_ptr != NULL)
1486                 {
1487                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
1488                 }
1489                 return SR_ERR_OPERATION_FAILED;
1490         }
1491         //we don't need the string anymore
1492         free(stringConfiguration);
1493         stringConfiguration = NULL;
1494
1495         cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
1496         if (!cJSON_IsObject(vesDetails))
1497         {
1498                 printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
1499                 cJSON_Delete(jsonConfig);
1500                 return SR_ERR_OPERATION_FAILED;
1501         }
1502
1503         cJSON *vesPort = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-port");
1504         if (!cJSON_IsNumber(vesPort))
1505         {
1506                 printf("Configuration JSON is not as expected: ves-endpoint-port is not a number.");
1507                 cJSON_Delete(jsonConfig);
1508                 return SR_ERR_OPERATION_FAILED;
1509         }
1510
1511         //we set the value of the fault-notification-delay-period object
1512         cJSON_SetNumberValue(vesPort, new_port);
1513
1514         //writing the new JSON to the configuration file
1515         stringConfiguration = cJSON_Print(jsonConfig);
1516         writeConfigFile(stringConfiguration);
1517
1518         cJSON_Delete(jsonConfig);
1519
1520         return SR_ERR_OK;
1521 }
1522
1523 int ves_registration_changed(cJSON_bool new_bool)
1524 {
1525         char *stringConfiguration = readConfigFileInString();
1526
1527         if (stringConfiguration == NULL)
1528         {
1529                 printf("Could not read configuration file!\n");
1530                 return SR_ERR_OPERATION_FAILED;
1531         }
1532
1533         cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
1534         if (jsonConfig == NULL)
1535         {
1536                 free(stringConfiguration);
1537                 const char *error_ptr = cJSON_GetErrorPtr();
1538                 if (error_ptr != NULL)
1539                 {
1540                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
1541                 }
1542                 return SR_ERR_OPERATION_FAILED;
1543         }
1544         //we don't need the string anymore
1545         free(stringConfiguration);
1546         stringConfiguration = NULL;
1547
1548         cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
1549         if (!cJSON_IsObject(vesDetails))
1550         {
1551                 printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
1552                 cJSON_Delete(jsonConfig);
1553                 return SR_ERR_OPERATION_FAILED;
1554         }
1555
1556         cJSON *vesRegistration = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-registration");
1557         if (!cJSON_IsBool(vesRegistration))
1558         {
1559                 printf("Configuration JSON is not as expected: ves-registration is not a bool.");
1560                 cJSON_Delete(jsonConfig);
1561                 return SR_ERR_OPERATION_FAILED;
1562         }
1563
1564         //we set the value of the ves-registration object
1565         cJSON_ReplaceItemInObject(vesDetails, "ves-registration", cJSON_CreateBool(new_bool));
1566
1567         //writing the new JSON to the configuration file
1568         stringConfiguration = cJSON_Print(jsonConfig);
1569         writeConfigFile(stringConfiguration);
1570
1571         cJSON_Delete(jsonConfig);
1572
1573         return SR_ERR_OK;
1574 }
1575
1576 int is_netconf_available_changed(cJSON_bool new_bool)
1577 {
1578         char *stringConfiguration = readConfigFileInString();
1579
1580         if (stringConfiguration == NULL)
1581         {
1582                 printf("Could not read configuration file!\n");
1583                 return SR_ERR_OPERATION_FAILED;
1584         }
1585
1586         cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
1587         if (jsonConfig == NULL)
1588         {
1589                 free(stringConfiguration);
1590                 const char *error_ptr = cJSON_GetErrorPtr();
1591                 if (error_ptr != NULL)
1592                 {
1593                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
1594                 }
1595                 return SR_ERR_OPERATION_FAILED;
1596         }
1597         //we don't need the string anymore
1598         free(stringConfiguration);
1599         stringConfiguration = NULL;
1600
1601         cJSON *notifConfig = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
1602         if (!cJSON_IsObject(notifConfig))
1603         {
1604                 printf("Configuration JSON is not as expected: notification-config is not an object");
1605                 cJSON_Delete(jsonConfig);
1606                 return SR_ERR_OPERATION_FAILED;
1607         }
1608
1609         cJSON *isNetconfAvailable = cJSON_GetObjectItemCaseSensitive(notifConfig, "is-netconf-available");
1610         if (!cJSON_IsBool(isNetconfAvailable))
1611         {
1612                 printf("Configuration JSON is not as expected: is-netconf-available is not a bool.");
1613                 cJSON_Delete(jsonConfig);
1614                 return SR_ERR_OPERATION_FAILED;
1615         }
1616
1617         //we set the value of the ves-registration object
1618         cJSON_ReplaceItemInObject(notifConfig, "is-netconf-available", cJSON_CreateBool(new_bool));
1619
1620         //writing the new JSON to the configuration file
1621         stringConfiguration = cJSON_Print(jsonConfig);
1622         writeConfigFile(stringConfiguration);
1623
1624         cJSON_Delete(jsonConfig);
1625
1626         return SR_ERR_OK;
1627 }
1628
1629 int is_ves_available_changed(cJSON_bool new_bool)
1630 {
1631         char *stringConfiguration = readConfigFileInString();
1632
1633         if (stringConfiguration == NULL)
1634         {
1635                 printf("Could not read configuration file!\n");
1636                 return SR_ERR_OPERATION_FAILED;
1637         }
1638
1639         cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
1640         if (jsonConfig == NULL)
1641         {
1642                 free(stringConfiguration);
1643                 const char *error_ptr = cJSON_GetErrorPtr();
1644                 if (error_ptr != NULL)
1645                 {
1646                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
1647                 }
1648                 return SR_ERR_OPERATION_FAILED;
1649         }
1650         //we don't need the string anymore
1651         free(stringConfiguration);
1652         stringConfiguration = NULL;
1653
1654         cJSON *notifConfig = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
1655         if (!cJSON_IsObject(notifConfig))
1656         {
1657                 printf("Configuration JSON is not as expected: notification-config is not an object");
1658                 cJSON_Delete(jsonConfig);
1659                 return SR_ERR_OPERATION_FAILED;
1660         }
1661
1662         cJSON *isVesAvailable = cJSON_GetObjectItemCaseSensitive(notifConfig, "is-ves-available");
1663         if (!cJSON_IsBool(isVesAvailable))
1664         {
1665                 printf("Configuration JSON is not as expected: is-ves-available is not a bool.");
1666                 cJSON_Delete(jsonConfig);
1667                 return SR_ERR_OPERATION_FAILED;
1668         }
1669
1670         //we set the value of the ves-registration object
1671         cJSON_ReplaceItemInObject(notifConfig, "is-ves-available", cJSON_CreateBool(new_bool));
1672
1673         //writing the new JSON to the configuration file
1674         stringConfiguration = cJSON_Print(jsonConfig);
1675         writeConfigFile(stringConfiguration);
1676
1677         cJSON_Delete(jsonConfig);
1678
1679         return SR_ERR_OK;
1680 }