1 /*************************************************************************
3 * Copyright 2020 highstreet technologies GmbH and others
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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 ***************************************************************************/
21 #include "utils/log_utils.h"
22 #include "utils/sys_utils.h"
27 #include "core/framework.h"
28 #include "core/docker.h"
29 #include "core/session.h"
30 #include "utils/nc_client.h"
31 #include "utils/http_client.h"
32 #include "utils/nts_utils.h"
34 static uint16_t manager_start_port = 0;
35 static uint8_t manager_port[65536];
37 void manager_operations_init(void) {
38 manager_start_port = framework_environment.host_base_port;
39 for(int i = 0; i < 65536; i++) {
44 int manager_start_instance(manager_network_function_type *function_type) {
45 assert(function_type);
48 function_type->started_instances++;
49 function_type->instance = (manager_network_function_instance_t *)realloc(function_type->instance, sizeof(manager_network_function_instance_t) * function_type->started_instances);
50 if(function_type->instance == 0) {
51 log_error("realloc failed");
52 function_type->started_instances--;
53 return NTS_ERR_FAILED;
56 manager_network_function_instance_t *instance = &function_type->instance[function_type->started_instances - 1];
57 instance->is_configured = false;
58 instance->is_mounted = false;
60 asprintf(&instance->name, "%s-%d", function_type->docker_instance_name, function_type->started_instances - 1);
62 instance->mount_point_addressing_method = strdup(function_type->mount_point_addressing_method);
63 instance->docker_port = STANDARD_NETCONF_PORT;
64 instance->host_ip = strdup(framework_environment.host_ip);
65 instance->host_port = 0;
67 //find start host port
68 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)) {
69 if(manager_port[i] == 0) {
71 instance->host_port = i;
76 if(instance->host_port == 0) {
77 log_error("no ports available for operation");
79 free(instance->mount_point_addressing_method);
80 free(instance->host_ip);
81 return NTS_ERR_FAILED;
84 int rc = docker_device_start(function_type, instance);
85 if(rc != NTS_ERR_OK) {
86 log_error("docker_device_start failed");
88 free(instance->mount_point_addressing_method);
89 free(instance->host_ip);
90 manager_port[instance->host_port] = 0;
91 return NTS_ERR_FAILED;
97 int manager_config_instance(manager_network_function_type *function_type, manager_network_function_instance_t *instance) {
98 assert(function_type);
101 //first wait for the nc server to be up and running
102 while(check_port_open(instance->docker_ip, instance->docker_port) == false) {
106 //populate sdn-controller and ves-endpoint
107 struct lyd_node *local_tree = 0;
108 int rc = lyd_utils_dup(session_running, "/nts-manager:simulation/sdn-controller", "/nts-network-function:simulation/sdn-controller", &local_tree);
109 if(rc != NTS_ERR_OK) {
110 log_error("lyd_utils_dup failed");
111 return NTS_ERR_FAILED;
114 rc = lyd_utils_dup(session_running, "/nts-manager:simulation/ves-endpoint", "/nts-network-function:simulation/ves-endpoint", &local_tree);
115 if(rc != NTS_ERR_OK) {
116 log_error("lyd_utils_dup failed");
117 lyd_free_withsiblings(local_tree);
118 return NTS_ERR_FAILED;
122 asprintf(&xpath_s, "/nts-manager:simulation/network-functions/network-function[function-type='%s']", function_type->function_type_string);
123 rc = lyd_utils_dup(session_running, xpath_s, "/nts-network-function:simulation/network-function", &local_tree);
125 if(rc != NTS_ERR_OK) {
126 log_error("lyd_utils_dup failed");
127 lyd_free_withsiblings(local_tree);
128 return NTS_ERR_FAILED;
131 nc_client_t *nc_client = nc_client_ssh_connect(instance->docker_ip, instance->docker_port, "netconf", "netconf");
133 log_error("nc_client_ssh_connect");
134 lyd_free_withsiblings(local_tree);
135 return NTS_ERR_FAILED;
138 rc += nc_client_edit_batch(nc_client, local_tree, 1000);
139 lyd_free_withsiblings(local_tree);
140 if(rc != NTS_ERR_OK) {
141 log_error("nc_client_edit_batch failed %d\n", rc);
142 nc_client_disconnect(nc_client);
143 return NTS_ERR_FAILED;
146 if(instance->is_configured == false) {
147 //run datastore-random-populate rpc
148 struct lyd_node *rpc_node = 0;
149 struct lyd_node *rpcout = 0;
150 rpc_node = lyd_new_path(0, session_context, "/nts-network-function:datastore-random-populate", 0, 0, 0);
152 log_error("failed to create rpc node");
153 nc_client_disconnect(nc_client);
154 return NTS_ERR_FAILED;
157 rpcout = nc_client_send_rpc(nc_client, rpc_node, 5000);
159 log_error("datastore-random-populate rpc failed");
160 nc_client_disconnect(nc_client);
161 lyd_free_withsiblings(rpc_node);
162 return NTS_ERR_FAILED;
165 lyd_free_withsiblings(rpcout);
167 lyd_free_withsiblings(rpc_node);
169 //run feature-control rpc
170 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);
172 log_error("failed to create rpc node");
173 nc_client_disconnect(nc_client);
174 return NTS_ERR_FAILED;
177 rpcout = nc_client_send_rpc(nc_client, rpc_node, 1000);
179 log_error("feature-control rpc failed");
180 nc_client_disconnect(nc_client);
181 lyd_free_withsiblings(rpc_node);
182 return NTS_ERR_FAILED;
185 lyd_free_withsiblings(rpcout);
187 lyd_free_withsiblings(rpc_node);
190 instance->is_configured = true;
192 nc_client_disconnect(nc_client);
197 int manager_stop_instance(manager_network_function_type *function_type) {
198 assert(function_type);
200 manager_network_function_instance_t *instance = &function_type->instance[function_type->started_instances - 1];
202 if(instance->is_mounted) {
203 if(manager_unmount_instance(function_type) != NTS_ERR_OK) {
204 log_error("failed to unmount instance");
205 return NTS_ERR_FAILED;
209 int rc = docker_device_stop(instance);
210 if(rc != NTS_ERR_OK) {
211 log_error("docker_device_stop failed");
212 return NTS_ERR_FAILED;
216 manager_port[instance->host_port] = 0;
218 free(instance->mount_point_addressing_method);
219 free(instance->docker_id);
220 free(instance->name);
221 free(instance->docker_ip);
222 free(instance->host_ip);
224 function_type->started_instances--;
225 if(function_type->started_instances) {
226 function_type->instance = (manager_network_function_instance_t *)realloc(function_type->instance, sizeof(manager_network_function_instance_t) * function_type->started_instances);
227 if(function_type->instance == 0) {
228 log_error("realloc failed");
229 return NTS_ERR_FAILED;
233 free(function_type->instance);
234 function_type->instance = 0;
239 int manager_mount_instance(manager_network_function_type *function_type) {
240 assert(function_type);
242 manager_network_function_instance_t *instance = &function_type->instance[function_type->mounted_instances];
244 if(instance->is_mounted == true) {
245 return NTS_ERR_FAILED;
248 controller_details_t *controller;
249 controller = controller_details_get(0);
250 if(controller == 0) {
251 log_error("could not get controller detailes");
252 return NTS_ERR_FAILED;
255 for(int i = 0; i < (framework_environment.ssh_connections + framework_environment.tls_connections); i++) {
258 if(i < framework_environment.ssh_connections) {
261 \"network-topology:netconf-node-topology:username\": \"netconf\",\
262 \"network-topology:netconf-node-topology:password\": \"netconf\"";
268 \"netconf-node-topology:key-based\" : {\
269 \"netconf-node-topology:username\" : \"netconf\",\
270 \"netconf-node-topology:key-id\" : \""KS_KEY_NAME"\"\
274 char *json_template = "\
276 \"network-topology:node\": [{\
277 \"network-topology:node-id\": \"%s\",\
278 \"network-topology:netconf-node-topology:host\": \"%s\",\
279 \"network-topology:netconf-node-topology:port\": \"%d\",\
280 \"network-topology:netconf-node-topology:tcp-only\": \"false\",\
281 \"network-topology:netconf-node-topology:protocol\": {\
282 \"network-topology:netconf-node-topology:name\": \"%s\"\
285 \"network-topology:netconf-node-topology:connection-timeout-millis\": \"20000\",\
286 \"network-topology:netconf-node-topology:default-request-timeout-millis\": \"60000\",\
287 \"network-topology:netconf-node-topology:max-connection-attempts\": \"3\"\
294 if(instance->mount_point_addressing_method[0] == 'd') {
295 ip = instance->docker_ip;
296 port = instance->docker_port + i;
299 ip = instance->host_ip;
300 port = instance->host_port + i;
303 asprintf(&node_id, "%s-%d", instance->name, port);
304 asprintf(&json, json_template, node_id, ip, port, protocol, protocol_data);
307 asprintf(&url, "%s/rests/data/network-topology:network-topology/topology=topology-netconf/node=%s", controller->base_url, node_id);
308 int rc = http_request(url, controller->username, controller->password, "PUT", json, 0, 0);
309 if(rc != NTS_ERR_OK) {
310 log_error("http_request failed");
314 controller_details_free(controller);
315 return NTS_ERR_FAILED;
323 controller_details_free(controller);
325 instance->is_mounted = true;
326 function_type->mounted_instances++;
331 int manager_unmount_instance(manager_network_function_type *function_type) {
332 assert(function_type);
334 manager_network_function_instance_t *instance = &function_type->instance[function_type->mounted_instances - 1];
336 if(instance->is_mounted == false) {
337 log_error("tried to unmount an unmounted instance");
338 return NTS_ERR_FAILED;
341 controller_details_t *controller;
342 controller = controller_details_get(0);
343 if(controller == 0) {
344 log_error("could not get controller detailes");
345 return NTS_ERR_FAILED;
348 for(int i = 0; i < (framework_environment.ssh_connections + framework_environment.tls_connections); i++) {
350 if(function_type->mount_point_addressing_method[0] == 'd') {
351 port = instance->docker_port + i;
354 port = instance->host_port + i;
357 asprintf(&node_id, "%s-%d", instance->name, port);
360 asprintf(&url, "%s/rests/data/network-topology:network-topology/topology=topology-netconf/node=%s", controller->base_url, node_id);
361 int rc = http_request(url, controller->username, controller->password, "DELETE", "", 0, 0);
362 if(rc != NTS_ERR_OK) {
363 log_error("http_request failed");
366 controller_details_free(controller);
367 return NTS_ERR_FAILED;
374 controller_details_free(controller);
376 function_type->mounted_instances--;
377 function_type->instance[function_type->mounted_instances].is_mounted = false;