X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=ntsimulator%2Fntsim-ng%2Fcore%2Fapp%2Fmanager_operations.c;fp=ntsimulator%2Fntsim-ng%2Fcore%2Fapp%2Fmanager_operations.c;h=3d2245c793fc54a0b85d228792d65cc6be88f360;hb=f1d5c9198acde7a7ce296490087cad37e008f688;hp=0000000000000000000000000000000000000000;hpb=f2d8f1002fa93848c80a88e5658db4816cba3020;p=sim%2Fo1-interface.git diff --git a/ntsimulator/ntsim-ng/core/app/manager_operations.c b/ntsimulator/ntsim-ng/core/app/manager_operations.c new file mode 100644 index 0000000..3d2245c --- /dev/null +++ b/ntsimulator/ntsim-ng/core/app/manager_operations.c @@ -0,0 +1,356 @@ +/************************************************************************* +* +* Copyright 2020 highstreet technologies GmbH and others +* +* 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. +***************************************************************************/ + +#define _GNU_SOURCE + +#include "manager.h" +#include "utils/log_utils.h" +#include "utils/sys_utils.h" +#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]; + +void manager_operations_init(void) { + manager_start_port = framework_environment.host_base_port; + for(int i = 0; i < 65536; i++) { + manager_port[i] = 0; + } +} + +int manager_start_instance(manager_network_function_type *function_type) { + assert(function_type); + assert_session(); + + 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; + } + + 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(instance->host_port == 0) { + log_error("no ports available for operation"); + return NTS_ERR_FAILED; + } + + int rc = docker_device_start(function_type, instance); + if(rc != NTS_ERR_OK) { + log_error("docker_device_start failed"); + return NTS_ERR_FAILED; + } + + 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); + + //first wait for the nc server to be up and running + while(check_port_open(instance->docker_ip, instance->docker_port) == false) { + usleep(10000); + } + + //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; + } + + 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"); + return NTS_ERR_FAILED; + } + + 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); + if(rc != NTS_ERR_OK) { + log_error("lyd_utils_dup failed"); + return NTS_ERR_FAILED; + } + free(xpath_s); + + 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"); + return NTS_ERR_FAILED; + } + + rc += nc_client_edit_batch(nc_client, local_tree, 1000); + if(rc != NTS_ERR_OK) { + log_error("nc_client_edit_batch failed %d\n", rc); + return NTS_ERR_FAILED; + } + lyd_free_withsiblings(local_tree); + + + 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"); + return NTS_ERR_FAILED; + } + + rpcout = nc_client_send_rpc(nc_client, rpc_node, 5000); + if(rpcout == 0) { + log_error("datastore-random-populate rpc failed"); + 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", 0, 0); + if(rpc_node == 0) { + log_error("failed to create rpc node"); + return NTS_ERR_FAILED; + } + + rpcout = nc_client_send_rpc(nc_client, rpc_node, 1000); + if(rpcout == 0) { + log_error("feature-control rpc failed"); + return NTS_ERR_FAILED; + } + else { + lyd_free_withsiblings(rpcout); + } + lyd_free_withsiblings(rpc_node); + } + + instance->is_configured = true; + + nc_client_disconnect(nc_client); + + return NTS_ERR_OK; +} + +int manager_stop_instance(manager_network_function_type *function_type) { + assert(function_type); + + manager_network_function_instance_t *instance = &function_type->instance[function_type->started_instances - 1]; + + if(instance->is_mounted) { + if(manager_unmount_instance(function_type) != NTS_ERR_OK) { + return NTS_ERR_FAILED; + } + } + + int rc = docker_device_stop(instance); + if(rc != NTS_ERR_OK) { + log_error("docker_device_stop failed"); + return NTS_ERR_FAILED; + } + + //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; + } + } + else { + free(function_type->instance); + function_type->instance = 0; + } + return NTS_ERR_OK; +} + +int manager_mount_instance(manager_network_function_type *function_type) { + assert(function_type); + + manager_network_function_instance_t *instance = &function_type->instance[function_type->mounted_instances]; + + if(instance->is_mounted == true) { + 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; + } + + 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\""; + + } + else { + protocol = "TLS"; + protocol_data = "\ + \"netconf-node-topology:key-based\" : {\ + \"netconf-node-topology:username\" : \"netconf\",\ + \"netconf-node-topology:key-id\" : \""KS_KEY_NAME"\"\ + }"; + } + + 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); + + 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"); + return NTS_ERR_FAILED; + } + + free(url); + free(node_id); + free(json); + } + + controller_details_free(controller); + + instance->is_mounted = true; + function_type->mounted_instances++; + + return NTS_ERR_OK; +} + +int manager_unmount_instance(manager_network_function_type *function_type) { + assert(function_type); + + manager_network_function_instance_t *instance = &function_type->instance[function_type->mounted_instances - 1]; + + 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; + } + + 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; + } + 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"); + return NTS_ERR_FAILED; + } + + free(url); + free(node_id); + } + + controller_details_free(controller); + + function_type->mounted_instances--; + function_type->instance[function_type->mounted_instances].is_mounted = false; + + return NTS_ERR_OK; +}