X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=ntsimulator%2Fsrc%2Fsoftware-management-oran%2Fsw-management-rpc.c;fp=ntsimulator%2Fsrc%2Fsoftware-management-oran%2Fsw-management-rpc.c;h=1540596e68ac266e935f94ae91c4266ea5e03e69;hb=1f1479ff8ce3a268acb7b70a32bb789d859a915b;hp=0000000000000000000000000000000000000000;hpb=34ec819462d5f81ceeb723e47467bf50a8454f34;p=sim%2Fo1-interface.git diff --git a/ntsimulator/src/software-management-oran/sw-management-rpc.c b/ntsimulator/src/software-management-oran/sw-management-rpc.c new file mode 100644 index 0000000..1540596 --- /dev/null +++ b/ntsimulator/src/software-management-oran/sw-management-rpc.c @@ -0,0 +1,519 @@ +/** + * @file sw-management-rpc.c + * @author Rastislav Szabo , Lukas Macko , + * Milan Lenco + * @brief Example usage of RPC API. + * + * @copyright + * Copyright 2016 Cisco Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include + +#include "sysrepo.h" +#include "sysrepo/values.h" + +#include "utils.h" + +#define LINE_BUFSIZE 128 + +volatile int exit_application = 0; + +pthread_mutex_t lock; + +static int sw_download_error_count, sw_install_error_count, sw_activate_error_count; + +void call_software_management_script(char *script_name) +{ + char line[LINE_BUFSIZE]; + int linenr; + FILE *pipe; + + /* Get a pipe where the output from the scripts comes in */ + char script[200]; + sprintf(script, "/opt/dev/%s", script_name); + + pipe = popen(script, "r"); + if (pipe == NULL) { /* check for errors */ + printf("Could not open script.\n"); + return; /* return with exit code indicating error */ + } + + /* Read script output from the pipe line by line */ + linenr = 1; + while (fgets(line, LINE_BUFSIZE, pipe) != NULL) { + printf("Script output line %d: %s", linenr, line); + ++linenr; + } + + /* Once here, out of the loop, the script has ended. */ + pclose(pipe); /* Close the pipe */ + return; /* return with exit code indicating success. */ +} + +struct sw_download_struct +{ + sr_session_ctx_t *sess; + char *filename; +}; + +void* sw_download_notification_send(void *arguments) +{ + // create the values to be sent in the notification + struct sw_download_struct *args = (struct sw_download_struct *)arguments; + int rc = SR_ERR_OK; + + sw_download_error_count++; + + sr_val_t *notif = NULL; + size_t current_num_of_values_notif = 0; + + CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif); + + char *trunc_filename; + trunc_filename = strrchr(args->filename, '/'); + + sr_val_build_xpath(¬if[current_num_of_values_notif - 1], "%s", "/o-ran-software-management:download-event/file-name"); + if (trunc_filename != NULL) + { + sr_val_set_str_data(¬if[current_num_of_values_notif - 1], SR_STRING_T, trunc_filename + 1); + + if (strcmp(trunc_filename+1, "reset") == 0) + { + call_software_management_script("edit-config-demo-start.sh"); + } + else + { + call_software_management_script("edit-config-after-download.sh"); + } + } + else + { + sr_val_set_str_data(¬if[current_num_of_values_notif - 1], SR_STRING_T, args->filename); + if (strcmp(args->filename, "reset") == 0) + { + call_software_management_script("edit-config-demo-start.sh"); + } + else + { + call_software_management_script("edit-config-after-download.sh"); + } + } + + if (args->filename != NULL) + { + free(args->filename); + } + + CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif); + + sr_val_build_xpath(¬if[current_num_of_values_notif - 1], "%s", "/o-ran-software-management:download-event/status"); + //every 5 RPCs we send an error + if (sw_download_error_count % 5 == 0) + { + sr_val_set_str_data(¬if[current_num_of_values_notif - 1], SR_ENUM_T, "AUTHENTICATION_ERROR"); + } + else + { + sr_val_set_str_data(¬if[current_num_of_values_notif - 1], SR_ENUM_T, "COMPLETED"); + } + + + // wait 5 seconds before sending the notification + sleep(5); + + /* send notification for event_notif_sub(_tree)_example */ + printf(">>> Sending event notification for '/o-ran-software-management:download-event'...\n"); + rc = sr_event_notif_send(args->sess, "/o-ran-software-management:download-event", notif, current_num_of_values_notif, SR_EV_NOTIF_DEFAULT); + if (SR_ERR_NOT_FOUND == rc) { + printf("No application subscribed for '/o-ran-software-management:download-event', skipping.\n"); + rc = SR_ERR_OK; + } + sr_free_values(notif, current_num_of_values_notif); + + return NULL; +} + +struct sw_install_struct +{ + sr_session_ctx_t *sess; + char *slot_name; +}; + +void* sw_install_notification_send(void *arguments) +{ + // create the values to be sent in the notification + struct sw_install_struct *args = (struct sw_install_struct *)arguments; + int rc = SR_ERR_OK; + sw_install_error_count++; + + sr_val_t *notif = NULL; + size_t current_num_of_values_notif = 0; + + CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif); + + sr_val_build_xpath(¬if[current_num_of_values_notif - 1], "%s", "/o-ran-software-management:install-event/slot-name"); + sr_val_set_str_data(¬if[current_num_of_values_notif - 1], SR_STRING_T, args->slot_name); + + if (args->slot_name != NULL) + { + free(args->slot_name); + } + + CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif); + + sr_val_build_xpath(¬if[current_num_of_values_notif - 1], "%s", "/o-ran-software-management:install-event/status"); + + //every 5 RPCs we send an error + if (sw_install_error_count % 5 == 0) + { + sr_val_set_str_data(¬if[current_num_of_values_notif - 1], SR_ENUM_T, "INTEGRITY_ERROR"); + } + else + { + sr_val_set_str_data(¬if[current_num_of_values_notif - 1], SR_ENUM_T, "COMPLETED"); + } + + // wait 5 seconds before sending the notification + sleep(5); + + /* send notification for event_notif_sub(_tree)_example */ + printf(">>> Sending event notification for '/o-ran-software-management:install-event'...\n"); + rc = sr_event_notif_send(args->sess, "/o-ran-software-management:install-event", notif, current_num_of_values_notif, SR_EV_NOTIF_DEFAULT); + if (SR_ERR_NOT_FOUND == rc) { + printf("No application subscribed for '/o-ran-software-management:install-event', skipping.\n"); + rc = SR_ERR_OK; + } + sr_free_values(notif, current_num_of_values_notif); + + return NULL; +} + +struct sw_activate_struct +{ + sr_session_ctx_t *sess; + char *slot_name; +}; + +void* sw_activate_notification_send(void *arguments) +{ + // create the values to be sent in the notification + struct sw_activate_struct *args = (struct sw_activate_struct *)arguments; + int rc = SR_ERR_OK; + sw_activate_error_count++; + + sr_val_t *notif = NULL; + size_t current_num_of_values_notif = 0; + + CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif); + + sr_val_build_xpath(¬if[current_num_of_values_notif - 1], "%s", "/o-ran-software-management:activation-event/slot-name"); + sr_val_set_str_data(¬if[current_num_of_values_notif - 1], SR_STRING_T, args->slot_name); + + if (args->slot_name != NULL) + { + free(args->slot_name); + } + + CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif); + + sr_val_build_xpath(¬if[current_num_of_values_notif - 1], "%s", "/o-ran-software-management:activation-event/status"); + //every 5 RPCs we send an error + if (sw_activate_error_count % 5 == 0) + { + sr_val_set_str_data(¬if[current_num_of_values_notif - 1], SR_ENUM_T, "APPLICATION_ERROR"); + } + else + { + sr_val_set_str_data(¬if[current_num_of_values_notif - 1], SR_ENUM_T, "COMPLETED"); + + call_software_management_script("edit-config-after-activate.sh"); + } + + CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif); + + sr_val_build_xpath(¬if[current_num_of_values_notif - 1], "%s", "/o-ran-software-management:activation-event/return-code"); + notif[current_num_of_values_notif - 1].type = SR_UINT8_T; + notif[current_num_of_values_notif - 1].data.uint8_val = 200; + + // wait 5 seconds before sending the notification + sleep(5); + + /* send notification for event_notif_sub(_tree)_example */ + printf(">>> Sending event notification for '/o-ran-software-management:activation-event'...\n"); + rc = sr_event_notif_send(args->sess, "/o-ran-software-management:activation-event", notif, current_num_of_values_notif, SR_EV_NOTIF_DEFAULT); + if (SR_ERR_NOT_FOUND == rc) { + printf("No application subscribed for '/o-ran-software-management:activation-event', skipping.\n"); + rc = SR_ERR_OK; + } + sr_free_values(notif, current_num_of_values_notif); + + return NULL; +} + +static int +sw_download_rpc_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt, + sr_val_t **output, size_t *output_cnt, void *private_ctx) +{ + int rc = SR_ERR_OK; + sr_session_ctx_t *session = (sr_session_ctx_t *)private_ctx; + + /** + * Here you would actually run the operation against the provided input values + * and obtained the output values. + */ + + /* allocate output values */ + rc = sr_new_values(2, output); + if (SR_ERR_OK != rc) { + return rc; + } + + rc = sr_val_set_xpath(&(*output)[0], "/o-ran-software-management:software-download/status"); + if (SR_ERR_OK != rc) { + return rc; + } + (*output)[0].type = SR_ENUM_T; + (*output)[0].data.enum_val = "STARTED"; + + rc = sr_val_set_xpath(&(*output)[1], "/o-ran-software-management:software-download/notification-timeout"); + if (SR_ERR_OK != rc) { + return rc; + } + (*output)[1].type = SR_INT32_T; + (*output)[1].data.int32_val = 10; + + /* inform sysrepo about the number of output values */ + *output_cnt = 2; + + struct sw_download_struct *args = (struct sw_download_struct *)malloc(sizeof(struct sw_download_struct)); + args->sess = session; + args->filename = strdup(input[0].data.string_val); + + pthread_t sw_download_thread; + if(pthread_create(&sw_download_thread, NULL, &sw_download_notification_send, (void *)args)) + { + fprintf(stderr, "Could not create thread for SW Download thread\n"); + return SR_ERR_OPERATION_FAILED; + } + + /** + * Do not deallocate input values! + * They will get freed automatically by sysrepo. + */ + return rc; +} + +static int +sw_install_rpc_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt, + sr_val_t **output, size_t *output_cnt, void *private_ctx) +{ + int rc = SR_ERR_OK; + sr_session_ctx_t *session = (sr_session_ctx_t *)private_ctx; + + /** + * Here you would actually run the operation against the provided input values + * and obtained the output values. + */ + + /* allocate output values */ + rc = sr_new_values(1, output); + if (SR_ERR_OK != rc) { + return rc; + } + + rc = sr_val_set_xpath(&(*output)[0], "/o-ran-software-management:software-install/status"); + if (SR_ERR_OK != rc) { + return rc; + } + (*output)[0].type = SR_ENUM_T; + (*output)[0].data.enum_val = "STARTED"; + + /* inform sysrepo about the number of output values */ + *output_cnt = 1; + + struct sw_install_struct *args = (struct sw_install_struct *)malloc(sizeof(struct sw_install_struct)); + args->sess = session; + args->slot_name = strdup(input[0].data.string_val); + + pthread_t sw_install_thread; + if(pthread_create(&sw_install_thread, NULL, &sw_install_notification_send, (void *)args)) + { + fprintf(stderr, "Could not create thread for SW Install thread\n"); + return SR_ERR_OPERATION_FAILED; + } + + /** + * Do not deallocate input values! + * They will get freed automatically by sysrepo. + */ + return rc; +} + +static int +sw_activate_rpc_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt, + sr_val_t **output, size_t *output_cnt, void *private_ctx) +{ + int rc = SR_ERR_OK; + sr_session_ctx_t *session = (sr_session_ctx_t *)private_ctx; + + /** + * Here you would actually run the operation against the provided input values + * and obtained the output values. + */ + + /* allocate output values */ + rc = sr_new_values(2, output); + if (SR_ERR_OK != rc) { + return rc; + } + + rc = sr_val_set_xpath(&(*output)[0], "/o-ran-software-management:software-activate/status"); + if (SR_ERR_OK != rc) { + return rc; + } + (*output)[0].type = SR_ENUM_T; + (*output)[0].data.enum_val = "STARTED"; + + rc = sr_val_set_xpath(&(*output)[1], "/o-ran-software-management:software-activate/notification-timeout"); + if (SR_ERR_OK != rc) { + return rc; + } + (*output)[1].type = SR_INT32_T; + (*output)[1].data.int32_val = 10; + + /* inform sysrepo about the number of output values */ + *output_cnt = 2; + + struct sw_activate_struct *args = (struct sw_activate_struct *)malloc(sizeof(struct sw_activate_struct)); + args->sess = session; + args->slot_name = strdup(input[0].data.string_val); + + pthread_t sw_activate_thread; + if(pthread_create(&sw_activate_thread, NULL, &sw_activate_notification_send, (void *)args)) + { + fprintf(stderr, "Could not create thread for SW Activate thread\n"); + return SR_ERR_OPERATION_FAILED; + } + + /** + * Do not deallocate input values! + * They will get freed automatically by sysrepo. + */ + return rc; +} + +static void +sigint_handler(int signum) +{ + exit_application = 1; +} + +static int +rpc_handler(sr_session_ctx_t *session) +{ + sr_subscription_ctx_t *subscription = NULL; + int rc = SR_ERR_OK; + + /* subscribe for handling software-download RPC */ + rc = sr_rpc_subscribe(session, "/o-ran-software-management:software-download", sw_download_rpc_cb, + (void *)session, SR_SUBSCR_DEFAULT, &subscription); + if (SR_ERR_OK != rc) { + fprintf(stderr, "Error by sr_rpc_subscribe: %s\n", sr_strerror(rc)); + goto cleanup; + } + + /* subscribe for handling software-install RPC */ + rc = sr_rpc_subscribe(session, "/o-ran-software-management:software-install", sw_install_rpc_cb, + (void *)session, SR_SUBSCR_DEFAULT, &subscription); + if (SR_ERR_OK != rc) { + fprintf(stderr, "Error by sr_rpc_subscribe: %s\n", sr_strerror(rc)); + goto cleanup; + } + + /* subscribe for handling software-activate RPC */ + rc = sr_rpc_subscribe(session, "/o-ran-software-management:software-activate", sw_activate_rpc_cb, + (void *)session, SR_SUBSCR_DEFAULT, &subscription); + if (SR_ERR_OK != rc) { + fprintf(stderr, "Error by sr_rpc_subscribe: %s\n", sr_strerror(rc)); + goto cleanup; + } + + printf("\n\n ========== SUBSCRIBED FOR HANDLING RPC ==========\n\n"); + + /* loop until ctrl-c is pressed / SIGINT is received */ + signal(SIGINT, sigint_handler); + signal(SIGPIPE, SIG_IGN); + while (!exit_application) { + sleep(1000); /* or do some more useful work... */ + } + + printf("Application exit requested, exiting.\n"); + +cleanup: + if (NULL != subscription) { + sr_unsubscribe(session, subscription); + } + return rc; +} + +int +main(int argc, char **argv) +{ + sr_conn_ctx_t *connection = NULL; + sr_session_ctx_t *session = NULL; + int rc = SR_ERR_OK; + + setbuf(stdout, NULL); + + if (pthread_mutex_init(&lock, NULL) != 0) + { + printf("Mutex init failed...\n"); + goto cleanup; + } + + /* connect to sysrepo */ + rc = sr_connect("sw_management_rpc_app", SR_CONN_DEFAULT, &connection); + if (SR_ERR_OK != rc) { + fprintf(stderr, "Error by sr_connect: %s\n", sr_strerror(rc)); + goto cleanup; + } + + /* start session */ + rc = sr_session_start(connection, SR_DS_RUNNING, SR_SESS_DEFAULT, &session); + if (SR_ERR_OK != rc) { + fprintf(stderr, "Error by sr_session_start: %s\n", sr_strerror(rc)); + goto cleanup; + } + + /* run as a RPC handler */ + printf("This application will be an RPC handler for 'software-download' operation of 'o-ran-software-management'.\n"); + rc = rpc_handler(session); + +cleanup: + if (NULL != session) { + sr_session_stop(session); + } + if (NULL != connection) { + sr_disconnect(connection); + } + return rc; +}