X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?p=sim%2Fo1-interface.git;a=blobdiff_plain;f=ntsimulator%2Fntsim-ng%2Fcore%2Fapp%2Fmanager_operations.c;h=c847a6ccae888decd443ee0354521f143fa84883;hp=e382b025af8992ed5eff5cf315f842962969f25f;hb=3bbf9d8a3c81afebcffb2b926cef219336dd53d6;hpb=312a154cc4d60a09596fba8fd1259345e048cdc2 diff --git a/ntsimulator/ntsim-ng/core/app/manager_operations.c b/ntsimulator/ntsim-ng/core/app/manager_operations.c index e382b02..c847a6c 100644 --- a/ntsimulator/ntsim-ng/core/app/manager_operations.c +++ b/ntsimulator/ntsim-ng/core/app/manager_operations.c @@ -23,357 +23,347 @@ #include #include #include +#include #include "core/framework.h" -#include "core/docker.h" #include "core/session.h" -#include "utils/nc_client.h" -#include "utils/http_client.h" -#include "utils/nts_utils.h" -static uint16_t manager_start_port = 0; -static uint8_t manager_port[65536]; +static manager_operation_t *manager_operations; +static pthread_mutex_t manager_operations_mutex; +static sem_t manager_operations_sem; -void manager_operations_init(void) { - manager_start_port = framework_environment.host_base_port; - for(int i = 0; i < 65536; i++) { - manager_port[i] = 0; - } -} +manager_protocol_type_t manager_port[65536]; -int manager_start_instance(manager_network_function_type *function_type) { - assert(function_type); - assert_session(); +static int manager_operations_execute(manager_operation_t *oper); - function_type->started_instances++; - function_type->instance = (manager_network_function_instance_t *)realloc(function_type->instance, sizeof(manager_network_function_instance_t) * function_type->started_instances); - if(function_type->instance == 0) { - log_error("realloc failed"); - function_type->started_instances--; - return NTS_ERR_FAILED; +int manager_operations_init(void) { + manager_operations = 0; + if(pthread_mutex_init(&manager_operations_mutex, NULL) != 0) { + log_error("mutex init has failed\n"); + return NTS_ERR_FAILED; } - manager_network_function_instance_t *instance = &function_type->instance[function_type->started_instances - 1]; - instance->is_configured = false; - instance->is_mounted = false; - - asprintf(&instance->name, "%s-%d", function_type->docker_instance_name, function_type->started_instances - 1); - - instance->mount_point_addressing_method = strdup(function_type->mount_point_addressing_method); - instance->docker_port = STANDARD_NETCONF_PORT; - instance->host_ip = strdup(framework_environment.host_ip); - instance->host_port = 0; - - //find start host port - for(int i = manager_start_port; i < 65536 - (framework_environment.ssh_connections + framework_environment.tls_connections + framework_environment.ftp_connections + framework_environment.sftp_connections); i += (framework_environment.ssh_connections + framework_environment.tls_connections + framework_environment.ftp_connections + framework_environment.sftp_connections)) { - if(manager_port[i] == 0) { - manager_port[i] = 1; - instance->host_port = i; - break; - } + if(sem_init(&manager_operations_sem, 0, 0) != 0) { + log_error("sem init has failed\n"); + return NTS_ERR_FAILED; } - if(instance->host_port == 0) { - log_error("no ports available for operation"); - free(instance->name); - free(instance->mount_point_addressing_method); - free(instance->host_ip); - function_type->started_instances--; - return NTS_ERR_FAILED; + //checkAL ar fi misto sa stim ce porturi sunt si ce porturi nu sunt available... + for(int i = 0; i < 1000; i++) { + manager_port[i] = MANAGER_PROTOCOL_UNAVAILABLE; } - int rc = docker_device_start(function_type, instance); - if(rc != NTS_ERR_OK) { - log_error("docker_device_start failed"); - free(instance->name); - free(instance->mount_point_addressing_method); - free(instance->host_ip); - manager_port[instance->host_port] = 0; - function_type->started_instances--; - return NTS_ERR_FAILED; + for(int i = 1000; i < 65536; i++) { + manager_port[i] = MANAGER_PROTOCOL_UNUSED; } return NTS_ERR_OK; } -int manager_config_instance(manager_network_function_type *function_type, manager_network_function_instance_t *instance) { - assert(function_type); - assert(instance); +void manager_operations_loop(void) { + int rc; + + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += 1; + + if(sem_timedwait(&manager_operations_sem, &ts) == 0) { + int retries = 10; + while(retries) { + rc = sr_lock(session_running, NTS_MANAGER_MODULE); + if(rc == SR_ERR_OK) { + break; + } + else { + sleep(1); + } + retries--; + } - //first wait for the nc server to be up and running - while(check_port_open(instance->docker_ip, instance->docker_port) == false) { - usleep(10000); - } + if(retries == 0) { + log_error("sr_lock failed\n"); + //checkAL ce facem acum ? + } - //populate sdn-controller and ves-endpoint - struct lyd_node *local_tree = 0; - int rc = lyd_utils_dup(session_running, "/nts-manager:simulation/sdn-controller", "/nts-network-function:simulation/sdn-controller", &local_tree); - if(rc != NTS_ERR_OK) { - log_error("lyd_utils_dup failed"); - return NTS_ERR_FAILED; + pthread_mutex_lock(&manager_operations_mutex); + + const char *status = "SUCCESS"; + char errmsg[256]; + errmsg[0] = 0; + + while(manager_operations) { + //pop operation from list + manager_operation_t *oper = manager_operations; + manager_operations = manager_operations->next; + + //if operation is RPC first update any *other* fields + + rc = manager_operations_execute(oper); + if(rc != NTS_ERR_OK) { + log_error("manager_operations_execute failed\n"); + status = "FAILED"; + strcpy(errmsg, oper->errmsg); + manager_operations_free_oper(oper); + break; + } + + manager_operations_free_oper(oper); + } + + for(int i = 0; i < docker_context_count; i++) { + //do any reconfig necesarry + for(int j = 0; j < manager_context[i].started_instances; j++) { + if(manager_context[i].instance[j].is_configured == false) { + rc = manager_actions_config_instance(&manager_context[i], &manager_context[i].instance[j]); + if(rc != NTS_ERR_OK) { + status = "reconfig FAILED"; + sprintf(errmsg, "reconfig FAILED - instance %s", manager_context[i].instance[j].container.name); + log_error("%s\n", errmsg); + } + } + } + } + + rc = manager_sr_on_last_operation_status(status, errmsg); + if(rc != NTS_ERR_OK) { + log_error("manager_sr_on_last_operation_status failed\n"); + } + + pthread_mutex_unlock(&manager_operations_mutex); + rc = sr_unlock(session_running, NTS_MANAGER_MODULE); //release datastore + if(rc != SR_ERR_OK) { + log_error("sr_unlock failed\n"); + } } +} - rc = lyd_utils_dup(session_running, "/nts-manager:simulation/ves-endpoint", "/nts-network-function:simulation/ves-endpoint", &local_tree); - if(rc != NTS_ERR_OK) { - log_error("lyd_utils_dup failed"); - lyd_free_withsiblings(local_tree); - return NTS_ERR_FAILED; +void manager_operations_free(void) { + //terminate all containers + for(int i = 0; i < docker_context_count; i++) { + while(manager_context[i].started_instances) { + manager_actions_stop(&manager_context[i]); + } } - char *xpath_s = 0; - asprintf(&xpath_s, "/nts-manager:simulation/network-functions/network-function[function-type='%s']", function_type->function_type_string); - rc = lyd_utils_dup(session_running, xpath_s, "/nts-network-function:simulation/network-function", &local_tree); - free(xpath_s); - if(rc != NTS_ERR_OK) { - log_error("lyd_utils_dup failed"); - lyd_free_withsiblings(local_tree); - return NTS_ERR_FAILED; - } + sem_destroy(&manager_operations_sem); + pthread_mutex_destroy(&manager_operations_mutex); +} - nc_client_t *nc_client = nc_client_ssh_connect(instance->docker_ip, instance->docker_port, "netconf", "netconf"); - if(nc_client == 0) { - log_error("nc_client_ssh_connect"); - lyd_free_withsiblings(local_tree); - return NTS_ERR_FAILED; +manager_operation_t *manager_operations_new_oper(manager_operation_type_t type) { + manager_operation_t *new_oper = malloc(sizeof(manager_operation_t)); + if(new_oper == 0) { + log_error("malloc failed\n"); + return 0; } - rc += nc_client_edit_batch(nc_client, local_tree, 1000); - lyd_free_withsiblings(local_tree); - if(rc != NTS_ERR_OK) { - log_error("nc_client_edit_batch failed %d\n", rc); - nc_client_disconnect(nc_client); - return NTS_ERR_FAILED; - } + new_oper->type = type; + + new_oper->ft_index = -1; + new_oper->function_type = 0; + + new_oper->started_instances = -1; + new_oper->mounted_instances = -1; - if(instance->is_configured == false) { - //run datastore-random-populate rpc - struct lyd_node *rpc_node = 0; - struct lyd_node *rpcout = 0; - rpc_node = lyd_new_path(0, session_context, "/nts-network-function:datastore-random-populate", 0, 0, 0); - if(rpc_node == 0) { - log_error("failed to create rpc node"); - nc_client_disconnect(nc_client); - return NTS_ERR_FAILED; - } + new_oper->docker_instance_name = 0; + new_oper->docker_version_tag = 0; + new_oper->docker_repository = 0; - rpcout = nc_client_send_rpc(nc_client, rpc_node, 5000); - if(rpcout == 0) { - log_error("datastore-random-populate rpc failed"); - nc_client_disconnect(nc_client); - lyd_free_withsiblings(rpc_node); - return NTS_ERR_FAILED; - } - else { - lyd_free_withsiblings(rpcout); - } - lyd_free_withsiblings(rpc_node); - - //run feature-control rpc - rpc_node = lyd_new_path(0, session_context, "/nts-network-function:feature-control/features", "ves-file-ready ves-heartbeat ves-pnf-registration manual-notification-generation netconf-call-home web-cut-through", 0, 0); - if(rpc_node == 0) { - log_error("failed to create rpc node"); - nc_client_disconnect(nc_client); - return NTS_ERR_FAILED; - } + new_oper->mount_point_addressing_method = 0; - rpcout = nc_client_send_rpc(nc_client, rpc_node, 1000); - if(rpcout == 0) { - log_error("feature-control rpc failed"); - nc_client_disconnect(nc_client); - lyd_free_withsiblings(rpc_node); - return NTS_ERR_FAILED; - } - else { - lyd_free_withsiblings(rpcout); - } - lyd_free_withsiblings(rpc_node); - } + new_oper->fault_generation.delay_period = 0; + new_oper->fault_generation.delay_period_count = -1; - instance->is_configured = true; + new_oper->netconf.faults_enabled = -1; + new_oper->netconf.call_home = -1; - nc_client_disconnect(nc_client); + new_oper->ves.faults_enabled = -1; + new_oper->ves.pnf_registration = -1; + new_oper->ves.heartbeat_period = -1; - return NTS_ERR_OK; + new_oper->errmsg = 0; + new_oper->next = 0; + + return new_oper; } -int manager_stop_instance(manager_network_function_type *function_type) { - assert(function_type); +int manager_operations_free_oper(manager_operation_t *oper) { + assert(oper); - manager_network_function_instance_t *instance = &function_type->instance[function_type->started_instances - 1]; + free(oper->function_type); + free(oper->docker_instance_name); + free(oper->docker_repository); + free(oper->docker_version_tag); + free(oper->mount_point_addressing_method); + free(oper->errmsg); - if(instance->is_mounted) { - if(manager_unmount_instance(function_type) != NTS_ERR_OK) { - log_error("failed to unmount instance"); - } - } + free(oper); + return NTS_ERR_OK; +} - int rc = docker_device_stop(instance); - if(rc != NTS_ERR_OK) { - log_error("docker_device_stop failed"); - return NTS_ERR_FAILED; - } +int manager_operations_begin(void) { + return pthread_mutex_lock(&manager_operations_mutex); +} - //clear unused ports - manager_port[instance->host_port] = 0; - - free(instance->mount_point_addressing_method); - free(instance->docker_id); - free(instance->name); - free(instance->docker_ip); - free(instance->host_ip); - - function_type->started_instances--; - if(function_type->started_instances) { - function_type->instance = (manager_network_function_instance_t *)realloc(function_type->instance, sizeof(manager_network_function_instance_t) * function_type->started_instances); - if(function_type->instance == 0) { - log_error("realloc failed"); - return NTS_ERR_FAILED; - } +int manager_operations_add(manager_operation_t *oper) { + assert(oper); + + if(manager_operations == 0) { + manager_operations = oper; } else { - free(function_type->instance); - function_type->instance = 0; + manager_operation_t *h = manager_operations; + while(h->next) { + h = h->next; + } + h->next = oper; } + return NTS_ERR_OK; } -int manager_mount_instance(manager_network_function_type *function_type) { - assert(function_type); +void manager_operations_finish_and_execute(void) { + pthread_mutex_unlock(&manager_operations_mutex); + sem_post(&manager_operations_sem); +} - manager_network_function_instance_t *instance = &function_type->instance[function_type->mounted_instances]; +void manager_operations_finish_with_error(void) { + while(manager_operations) { + manager_operation_t *h = manager_operations->next; + manager_operations_free_oper(manager_operations); + manager_operations = h; + } + pthread_mutex_unlock(&manager_operations_mutex); + sem_post(&manager_operations_sem); +} - if(instance->is_mounted == true) { - return NTS_ERR_FAILED; + + +int manager_operations_validate(manager_operation_t *oper) { + assert(oper); + + //prepopulate unset values + if(oper->docker_instance_name == 0) { + oper->docker_instance_name = strdup(manager_context[oper->ft_index].docker_instance_name); } - controller_details_t *controller; - controller = controller_details_get(0); - if(controller == 0) { - log_error("could not get controller detailes"); - return NTS_ERR_FAILED; + if(oper->docker_repository == 0) { + oper->docker_repository = strdup(manager_context[oper->ft_index].docker_repository); } - for(int i = 0; i < (framework_environment.ssh_connections + framework_environment.tls_connections); i++) { - char *protocol; - char *protocol_data; - if(i < framework_environment.ssh_connections) { - protocol = "SSH"; - protocol_data = "\ - \"network-topology:netconf-node-topology:username\": \"netconf\",\ - \"network-topology:netconf-node-topology:password\": \"netconf\""; + if(oper->docker_version_tag == 0) { + oper->docker_version_tag = strdup(manager_context[oper->ft_index].docker_version_tag); + } - } - else { - protocol = "TLS"; - protocol_data = "\ - \"netconf-node-topology:key-based\" : {\ - \"netconf-node-topology:username\" : \"netconf\",\ - \"netconf-node-topology:key-id\" : \""KS_KEY_NAME"\"\ - }"; - } + if(oper->started_instances == -1) { + oper->started_instances = manager_context[oper->ft_index].started_instances; + } - char *json_template = "\ - {\ - \"network-topology:node\": [{\ - \"network-topology:node-id\": \"%s\",\ - \"network-topology:netconf-node-topology:host\": \"%s\",\ - \"network-topology:netconf-node-topology:port\": \"%d\",\ - \"network-topology:netconf-node-topology:tcp-only\": \"false\",\ - \"network-topology:netconf-node-topology:protocol\": {\ - \"network-topology:netconf-node-topology:name\": \"%s\"\ - },\ - %s,\ - \"network-topology:netconf-node-topology:connection-timeout-millis\": \"20000\",\ - \"network-topology:netconf-node-topology:default-request-timeout-millis\": \"60000\",\ - \"network-topology:netconf-node-topology:max-connection-attempts\": \"3\"\ - }]\ - }"; - - char *json = 0; - uint16_t port = 0; - char *ip = 0; - if(instance->mount_point_addressing_method[0] == 'd') { - ip = instance->docker_ip; - port = instance->docker_port + i; - } - else { - ip = instance->host_ip; - port = instance->host_port + i; - } - char *node_id = 0; - asprintf(&node_id, "%s-%d", instance->name, port); - asprintf(&json, json_template, node_id, ip, port, protocol, protocol_data); + if(oper->mounted_instances == -1) { + oper->mounted_instances = manager_context[oper->ft_index].mounted_instances; + } - char *url = 0; - asprintf(&url, "%s/rests/data/network-topology:network-topology/topology=topology-netconf/node=%s", controller->base_url, node_id); - int rc = http_request(url, controller->username, controller->password, "PUT", json, 0, 0); - if(rc != NTS_ERR_OK) { - log_error("http_request failed"); - free(url); - free(node_id); - free(json); - controller_details_free(controller); - return NTS_ERR_FAILED; + //check docker image if exists + bool found = false; + for(int i = 0; i < docker_context[oper->ft_index].available_images_count; i++) { + if(strcmp(docker_context[oper->ft_index].available_images[i].repo, oper->docker_repository) == 0) { + if(strcmp(docker_context[oper->ft_index].available_images[i].tag, oper->docker_version_tag) == 0) { + found = true; + break; + } } - - free(url); - free(node_id); - free(json); } - controller_details_free(controller); - - instance->is_mounted = true; - function_type->mounted_instances++; + if(found == false) { + log_error("could not find image: %s/%s:%s\n", oper->docker_repository, docker_context[oper->ft_index].image, oper->docker_version_tag); + return NTS_ERR_FAILED; + } return NTS_ERR_OK; } -int manager_unmount_instance(manager_network_function_type *function_type) { - assert(function_type); - int ret = NTS_ERR_OK; - - manager_network_function_instance_t *instance = &function_type->instance[function_type->mounted_instances - 1]; +static int manager_operations_execute(manager_operation_t *oper) { + assert(oper); + + int k = oper->ft_index; + int rc; + + //operation --> actions + if(manager_context[k].started_instances > oper->started_instances) { + //stop instances + while(manager_context[k].started_instances > oper->started_instances) { + + rc = manager_actions_stop(&manager_context[k]); + if(rc != NTS_ERR_OK) { + asprintf(&oper->errmsg, "stop FAILED - function-type %s", manager_context[k].function_type); + log_error("%s\n", oper->errmsg); + + return NTS_ERR_FAILED; + } + + rc = manager_sr_update_context(&manager_context[k]); + if(rc != NTS_ERR_OK) { + log_error("manager_sr_update_context failed\n"); + } + } - if(instance->is_mounted == false) { - log_error("tried to unmount an unmounted instance"); - return NTS_ERR_FAILED; } - - controller_details_t *controller; - controller = controller_details_get(0); - if(controller == 0) { - log_error("could not get controller detailes"); - return NTS_ERR_FAILED; + else if(manager_context[k].started_instances < oper->started_instances) { + //start instances + while(manager_context[k].started_instances < oper->started_instances) { + + rc = manager_actions_start(&manager_context[k]); + if(rc != NTS_ERR_OK) { + asprintf(&oper->errmsg, "start FAILED - function-type %s", manager_context[k].function_type); + log_error("%s\n", oper->errmsg); + return NTS_ERR_FAILED; + } + + rc = manager_sr_update_context(&manager_context[k]); + if(rc != NTS_ERR_OK) { + log_error("manager_sr_update_context failed\n"); + } + + rc = manager_actions_config_instance(&manager_context[k], &manager_context[k].instance[manager_context[k].started_instances - 1]); + if(rc != NTS_ERR_OK) { + asprintf(&oper->errmsg, "config FAILED - instance %s", manager_context[k].instance[manager_context[k].started_instances - 1].container.name); + log_error("%s\n", oper->errmsg); + } + } } - for(int i = 0; i < (framework_environment.ssh_connections + framework_environment.tls_connections); i++) { - uint16_t port = 0; - if(function_type->mount_point_addressing_method[0] == 'd') { - port = instance->docker_port + i; + if(manager_context[k].mounted_instances > oper->mounted_instances) { + //unmount instances + while(manager_context[k].mounted_instances > oper->mounted_instances) { + rc = manager_actions_unmount(&manager_context[k]); + if(rc != NTS_ERR_OK) { + asprintf(&oper->errmsg, "unmount FAILED - instance %s", manager_context[k].instance[manager_context[k].mounted_instances - 1].container.name); + log_error("%s\n", oper->errmsg); + return NTS_ERR_FAILED; + } + + rc = manager_sr_update_context(&manager_context[k]); + if(rc != NTS_ERR_OK) { + log_error("manager_sr_update_context failed\n"); + } } - else { - port = instance->host_port + i; - } - char *node_id = 0; - asprintf(&node_id, "%s-%d", instance->name, port); - char *url = 0; - asprintf(&url, "%s/rests/data/network-topology:network-topology/topology=topology-netconf/node=%s", controller->base_url, node_id); - int rc = http_request(url, controller->username, controller->password, "DELETE", "", 0, 0); - if(rc != NTS_ERR_OK) { - log_error("http_request failed"); - ret = NTS_ERR_FAILED; + } + else if(manager_context[k].mounted_instances < oper->mounted_instances) { + //mount instances + while(manager_context[k].mounted_instances < oper->mounted_instances) { + rc = manager_actions_mount(&manager_context[k]); + if(rc != NTS_ERR_OK) { + asprintf(&oper->errmsg, "mount FAILED - instance %s", manager_context[k].instance[manager_context[k].mounted_instances].container.name); + log_error("%s\n", oper->errmsg); + return NTS_ERR_FAILED; + } + + rc = manager_sr_update_context(&manager_context[k]); + if(rc != NTS_ERR_OK) { + log_error("manager_sr_update_context failed\n"); + } } - - free(url); - free(node_id); } - controller_details_free(controller); - - function_type->mounted_instances--; - function_type->instance[function_type->mounted_instances].is_mounted = false; - - return ret; + return NTS_ERR_OK; }