+
+int controller_netconf_call_home_port_changed(int new_port)
+{
+ char *stringConfiguration = readConfigFileInString();
+
+ if (stringConfiguration == NULL)
+ {
+ printf("Could not read configuration file!\n");
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
+ if (jsonConfig == NULL)
+ {
+ free(stringConfiguration);
+ const char *error_ptr = cJSON_GetErrorPtr();
+ if (error_ptr != NULL)
+ {
+ fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
+ }
+ return SR_ERR_OPERATION_FAILED;
+ }
+ //we don't need the string anymore
+ free(stringConfiguration);
+ stringConfiguration = NULL;
+
+ cJSON *controllerDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "controller-details");
+ if (!cJSON_IsObject(controllerDetails))
+ {
+ printf("Configuration JSON is not as expected: controller-details is not an object");
+ cJSON_Delete(jsonConfig);
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ cJSON *netconfCallHomePort = cJSON_GetObjectItemCaseSensitive(controllerDetails, "netconf-call-home-port");
+ if (!cJSON_IsNumber(netconfCallHomePort))
+ {
+ printf("Configuration JSON is not as expected: netconf-call-home-port is not a number.");
+ cJSON_Delete(jsonConfig);
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ //we set the value of the fault-notification-delay-period object
+ cJSON_SetNumberValue(netconfCallHomePort, new_port);
+
+ //writing the new JSON to the configuration file
+ stringConfiguration = cJSON_Print(jsonConfig);
+ writeConfigFile(stringConfiguration);
+
+ if (stringConfiguration != NULL)
+ {
+ free(stringConfiguration);
+ stringConfiguration = NULL;
+ }
+
+ cJSON_Delete(jsonConfig);
+
+ return SR_ERR_OK;
+}
+
+int controller_username_changed(char *new_username)
+{
+ char *stringConfiguration = readConfigFileInString();
+
+ if (stringConfiguration == NULL)
+ {
+ printf("Could not read configuration file!\n");
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
+ if (jsonConfig == NULL)
+ {
+ free(stringConfiguration);
+ const char *error_ptr = cJSON_GetErrorPtr();
+ if (error_ptr != NULL)
+ {
+ fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
+ }
+ return SR_ERR_OPERATION_FAILED;
+ }
+ //we don't need the string anymore
+ free(stringConfiguration);
+ stringConfiguration = NULL;
+
+ cJSON *controllerDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "controller-details");
+ if (!cJSON_IsObject(controllerDetails))
+ {
+ printf("Configuration JSON is not as expected: controller-details is not an object");
+ cJSON_Delete(jsonConfig);
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ cJSON *controllerUsername = cJSON_GetObjectItemCaseSensitive(controllerDetails, "controller-username");
+ if (!cJSON_IsString(controllerUsername))
+ {
+ printf("Configuration JSON is not as expected: controller-username is not a string");
+ cJSON_Delete(jsonConfig);
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ //we set the value of the fault-notification-delay-period object
+ cJSON_ReplaceItemInObject(controllerDetails, "controller-username", cJSON_CreateString(new_username));
+
+ //writing the new JSON to the configuration file
+ stringConfiguration = cJSON_Print(jsonConfig);
+ writeConfigFile(stringConfiguration);
+
+ if (stringConfiguration != NULL)
+ {
+ free(stringConfiguration);
+ stringConfiguration = NULL;
+ }
+
+ cJSON_Delete(jsonConfig);
+
+ return SR_ERR_OK;
+}
+
+int controller_password_changed(char *new_password)
+{
+ char *stringConfiguration = readConfigFileInString();
+
+ if (stringConfiguration == NULL)
+ {
+ printf("Could not read configuration file!\n");
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
+ if (jsonConfig == NULL)
+ {
+ free(stringConfiguration);
+ const char *error_ptr = cJSON_GetErrorPtr();
+ if (error_ptr != NULL)
+ {
+ fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
+ }
+ return SR_ERR_OPERATION_FAILED;
+ }
+ //we don't need the string anymore
+ free(stringConfiguration);
+ stringConfiguration = NULL;
+
+ cJSON *controllerDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "controller-details");
+ if (!cJSON_IsObject(controllerDetails))
+ {
+ printf("Configuration JSON is not as expected: controller-details is not an object");
+ cJSON_Delete(jsonConfig);
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ cJSON *controllerPassword = cJSON_GetObjectItemCaseSensitive(controllerDetails, "controller-password");
+ if (!cJSON_IsString(controllerPassword))
+ {
+ printf("Configuration JSON is not as expected: controller-password is not a string");
+ cJSON_Delete(jsonConfig);
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ //we set the value of the fault-notification-delay-period object
+ cJSON_ReplaceItemInObject(controllerDetails, "controller-password", cJSON_CreateString(new_password));
+
+ //writing the new JSON to the configuration file
+ stringConfiguration = cJSON_Print(jsonConfig);
+ writeConfigFile(stringConfiguration);
+
+ if (stringConfiguration != NULL)
+ {
+ free(stringConfiguration);
+ stringConfiguration = NULL;
+ }
+
+ cJSON_Delete(jsonConfig);
+
+ return SR_ERR_OK;
+}
+
+int netconf_call_home_changed(cJSON_bool new_bool)
+{
+ char *stringConfiguration = readConfigFileInString();
+
+ if (stringConfiguration == NULL)
+ {
+ printf("Could not read configuration file!\n");
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
+ if (jsonConfig == NULL)
+ {
+ free(stringConfiguration);
+ const char *error_ptr = cJSON_GetErrorPtr();
+ if (error_ptr != NULL)
+ {
+ fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
+ }
+ return SR_ERR_OPERATION_FAILED;
+ }
+ //we don't need the string anymore
+ free(stringConfiguration);
+ stringConfiguration = NULL;
+
+ cJSON *netconfCallHome = cJSON_GetObjectItemCaseSensitive(jsonConfig, "netconf-call-home");
+ if (!cJSON_IsBool(netconfCallHome))
+ {
+ printf("Configuration JSON is not as expected: netconf-call-home is not a bool.");
+ cJSON_Delete(jsonConfig);
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ //we set the value of the ves-registration object
+ cJSON_ReplaceItemInObject(jsonConfig, "netconf-call-home", cJSON_CreateBool(new_bool));
+
+ //writing the new JSON to the configuration file
+ stringConfiguration = cJSON_Print(jsonConfig);
+ writeConfigFile(stringConfiguration);
+
+ if (stringConfiguration != NULL)
+ {
+ free(stringConfiguration);
+ stringConfiguration = NULL;
+ }
+
+ cJSON_Delete(jsonConfig);
+
+ return SR_ERR_OK;
+}
+
+static int start_device_notification(char *exec_id)
+{
+ struct MemoryStruct curl_response_mem;
+
+ curl_response_mem.memory = malloc(1); /* will be grown as needed by the realloc above */
+ curl_response_mem.size = 0; /* no data at this point */
+
+ CURLcode res;
+
+ curl_easy_reset(curl);
+ set_curl_common_info();
+
+ char url[500];
+ sprintf(url, "http:/v%s/exec/%s/start", getenv("DOCKER_ENGINE_VERSION"), exec_id);
+
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+
+ cJSON *postDataJson = cJSON_CreateObject();
+
+ if (cJSON_AddFalseToObject(postDataJson, "Detach") == NULL)
+ {
+ printf("Could not create JSON object: Detach\n");
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ if (cJSON_AddFalseToObject(postDataJson, "Tty") == NULL)
+ {
+ printf("Could not create JSON object: Tty\n");
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ char *post_data_string = NULL;
+
+ post_data_string = cJSON_PrintUnformatted(postDataJson);
+
+ printf("Post data JSON:\n%s\n", post_data_string);
+
+ if (postDataJson != NULL)
+ {
+ cJSON_Delete(postDataJson);
+ }
+
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data_string);
+
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
+
+ res = curl_easy_perform(curl);
+
+ if (post_data_string != NULL)
+ {
+ free(post_data_string);
+ }
+
+ if (res != CURLE_OK)
+ {
+ return SR_ERR_OPERATION_FAILED;
+ }
+ else
+ {
+ cJSON *json_response = cJSON_Parse(curl_response_mem.memory);
+ const cJSON *message = NULL;
+
+ printf("%lu bytes retrieved\n", (unsigned long)curl_response_mem.size);
+
+ message = cJSON_GetObjectItemCaseSensitive(json_response, "message");
+
+ if (cJSON_IsString(message) && (message->valuestring != NULL))
+ {
+ printf("Message: \"%s\"\n", message->valuestring);
+ }
+
+ cJSON_Delete(json_response);
+ }
+
+ return SR_ERR_OK;
+}
+
+static int inspect_device_notification_execution(char *exec_id)
+{
+ int rc = SR_ERR_OK;
+
+ struct MemoryStruct curl_response_mem;
+
+ curl_response_mem.memory = malloc(1); /* will be grown as needed by the realloc above */
+ curl_response_mem.size = 0; /* no data at this point */
+
+ CURLcode res;
+
+ curl_easy_reset(curl);
+ set_curl_common_info();
+
+ char url[500];
+ sprintf(url, "http:/v%s/exec/%s/json", getenv("DOCKER_ENGINE_VERSION"), exec_id);
+
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
+
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
+
+ res = curl_easy_perform(curl);
+
+ if (res != CURLE_OK)
+ {
+ rc = SR_ERR_OPERATION_FAILED;
+ }
+ else
+ {
+ cJSON *json_response = cJSON_Parse(curl_response_mem.memory);
+ const cJSON *exit_code = NULL;
+
+ exit_code = cJSON_GetObjectItemCaseSensitive(json_response, "ExitCode");
+
+ if (cJSON_IsNumber(exit_code))
+ {
+ rc = exit_code->valueint;
+ }
+ else
+ {
+ printf("Exit code is not a number!\n");
+ rc = SR_ERR_OPERATION_FAILED;
+ }
+
+ cJSON_Delete(json_response);
+ }
+
+ return rc;
+}
+
+int invoke_device_notification(char *device_id, char *module_name, char *notification_string)
+{
+ int rc = SR_ERR_OK;
+
+ printf("Device-name = %s\nModule-name = %s\nNotification-object = %s\n", device_id, module_name, notification_string);
+
+ struct MemoryStruct curl_response_mem;
+
+ curl_response_mem.memory = malloc(1); /* will be grown as needed by the realloc above */
+ curl_response_mem.size = 0; /* no data at this point */
+
+ CURLcode res;
+
+ curl_easy_reset(curl);
+ set_curl_common_info();
+
+ char url[300];
+ sprintf(url, "http:/v%s/containers/%s/exec", getenv("DOCKER_ENGINE_VERSION"), device_id);
+
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+
+ cJSON *postDataJson = cJSON_CreateObject();
+
+ if (cJSON_AddFalseToObject(postDataJson, "AtttachStdin") == NULL)
+ {
+ printf("Could not create JSON object: AtttachStdin\n");
+ rc = SR_ERR_OPERATION_FAILED;
+ goto cleanup;
+ }
+
+ if (cJSON_AddTrueToObject(postDataJson, "AtttachStdout") == NULL)
+ {
+ printf("Could not create JSON object: AtttachStdout\n");
+ rc = SR_ERR_OPERATION_FAILED;
+ goto cleanup;
+ }
+
+ if (cJSON_AddTrueToObject(postDataJson, "AtttachStderr") == NULL)
+ {
+ printf("Could not create JSON object: AtttachStderr\n");
+ rc = SR_ERR_OPERATION_FAILED;
+ goto cleanup;
+ }
+
+ if (cJSON_AddTrueToObject(postDataJson, "Privileged") == NULL)
+ {
+ printf("Could not create JSON object: Privileged\n");
+ rc = SR_ERR_OPERATION_FAILED;
+ goto cleanup;
+ }
+
+ if (cJSON_AddStringToObject(postDataJson, "User", "root") == NULL)
+ {
+ printf("Could not create JSON object: User\n");
+ rc = SR_ERR_OPERATION_FAILED;
+ goto cleanup;
+ }
+
+ cJSON *cmd_array = cJSON_CreateArray();
+ if (cmd_array == NULL)
+ {
+ printf("Could not create JSON object: Cmd array\n");
+ rc = SR_ERR_OPERATION_FAILED;
+ goto cleanup;
+ }
+
+ cJSON_AddItemToObject(postDataJson, "Cmd", cmd_array);
+
+ cJSON *cmd_string_1 = cJSON_CreateString("sh");
+ cJSON_AddItemToArray(cmd_array, cmd_string_1);
+
+ cJSON *cmd_string_2 = cJSON_CreateString("-c");
+ cJSON_AddItemToArray(cmd_array, cmd_string_2);
+
+ //some notifications require a really long notification object
+ char string_command[1000000];
+ sprintf(string_command, "/usr/local/bin/generic-notifications %s '%s'", module_name, notification_string);
+
+ cJSON *cmd_string_3 = cJSON_CreateString(string_command);
+ cJSON_AddItemToArray(cmd_array, cmd_string_3);
+
+ char *post_data_string = NULL;
+
+ post_data_string = cJSON_PrintUnformatted(postDataJson);
+
+ printf("Post data JSON:\n%s\n", post_data_string);
+
+ if (postDataJson != NULL)
+ {
+ cJSON_Delete(postDataJson);
+ }
+
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data_string);
+
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
+
+ res = curl_easy_perform(curl);
+
+ if (post_data_string != NULL)
+ {
+ free(post_data_string);
+ }
+
+ if (res != CURLE_OK)
+ {
+ rc = SR_ERR_OPERATION_FAILED;
+ goto cleanup;
+ }
+ else
+ {
+ cJSON *json_response = cJSON_Parse(curl_response_mem.memory);
+ const cJSON *exec_id = NULL;
+
+ exec_id = cJSON_GetObjectItemCaseSensitive(json_response, "Id");
+
+ if (cJSON_IsString(exec_id) && (exec_id->valuestring != NULL))
+ {
+ printf("Exec id: \"%s\"\n", exec_id->valuestring);
+
+ rc = start_device_notification(exec_id->valuestring);
+ if (rc != SR_ERR_OK)
+ {
+ printf("Could not start the execution of the notification...\n");
+ }
+
+ sleep(1);
+
+ rc = inspect_device_notification_execution(exec_id->valuestring);
+ }
+
+ cJSON_Delete(json_response);
+ }
+
+cleanup:
+ if (device_id != NULL)
+ {
+ free(device_id);
+ }
+ if (module_name != NULL)
+ {
+ free(module_name);
+ }
+ if (notification_string != NULL)
+ {
+ free(notification_string);
+ }
+
+ return rc;
+}
+
+int pull_docker_image_of_simulated_device()
+{
+ struct MemoryStruct curl_response_mem;
+
+ curl_response_mem.memory = malloc(1); /* will be grown as needed by the realloc above */
+ curl_response_mem.size = 0; /* no data at this point */
+
+ CURLcode res;
+
+ curl_easy_reset(curl);
+ set_curl_common_info();
+
+ char url[300];
+ sprintf(url, "http:/v%s/images/create?fromImage=%s", getenv("DOCKER_ENGINE_VERSION"), getenv("MODELS_IMAGE"));
+
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
+
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
+
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, 300L);
+
+ res = curl_easy_perform(curl);
+
+ if (res != CURLE_OK)
+ {
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ return SR_ERR_OK;
+}
\ No newline at end of file