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 return NTS_ERR_FAILED;
55 manager_network_function_instance_t *instance = &function_type->instance[function_type->started_instances - 1];
56 instance->is_configured = false;
57 instance->is_mounted = false;
59 asprintf(&instance->name, "%s-%d", function_type->docker_instance_name, function_type->started_instances - 1);
61 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");
78 return NTS_ERR_FAILED;
81 int rc = docker_device_start(function_type, instance);
82 if(rc != NTS_ERR_OK) {
83 log_error("docker_device_start failed");
84 return NTS_ERR_FAILED;
90 int manager_config_instance(manager_network_function_type *function_type, manager_network_function_instance_t *instance) {
91 assert(function_type);
94 //first wait for the nc server to be up and running
95 while(check_port_open(instance->docker_ip, instance->docker_port) == false) {
99 //populate sdn-controller and ves-endpoint
100 struct lyd_node *local_tree = 0;
101 int rc = lyd_utils_dup(session_running, "/nts-manager:simulation/sdn-controller", "/nts-network-function:simulation/sdn-controller", &local_tree);
102 if(rc != NTS_ERR_OK) {
103 log_error("lyd_utils_dup failed");
104 return NTS_ERR_FAILED;
107 rc = lyd_utils_dup(session_running, "/nts-manager:simulation/ves-endpoint", "/nts-network-function:simulation/ves-endpoint", &local_tree);
108 if(rc != NTS_ERR_OK) {
109 log_error("lyd_utils_dup failed");
110 return NTS_ERR_FAILED;
114 asprintf(&xpath_s, "/nts-manager:simulation/network-functions/network-function[function-type='%s']", function_type->function_type_string);
115 rc = lyd_utils_dup(session_running, xpath_s, "/nts-network-function:simulation/network-function", &local_tree);
116 if(rc != NTS_ERR_OK) {
117 log_error("lyd_utils_dup failed");
118 return NTS_ERR_FAILED;
122 nc_client_t *nc_client = nc_client_ssh_connect(instance->docker_ip, instance->docker_port, "netconf", "netconf");
124 log_error("nc_client_ssh_connect");
125 return NTS_ERR_FAILED;
128 rc += nc_client_edit_batch(nc_client, local_tree, 1000);
129 if(rc != NTS_ERR_OK) {
130 log_error("nc_client_edit_batch failed %d\n", rc);
131 return NTS_ERR_FAILED;
133 lyd_free_withsiblings(local_tree);
136 if(instance->is_configured == false) {
137 //run datastore-random-populate rpc
138 struct lyd_node *rpc_node = 0;
139 struct lyd_node *rpcout = 0;
140 rpc_node = lyd_new_path(0, session_context, "/nts-network-function:datastore-random-populate", 0, 0, 0);
142 log_error("failed to create rpc node");
143 return NTS_ERR_FAILED;
146 rpcout = nc_client_send_rpc(nc_client, rpc_node, 5000);
148 log_error("datastore-random-populate rpc failed");
149 return NTS_ERR_FAILED;
152 lyd_free_withsiblings(rpcout);
154 lyd_free_withsiblings(rpc_node);
156 //run feature-control rpc
157 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);
159 log_error("failed to create rpc node");
160 return NTS_ERR_FAILED;
163 rpcout = nc_client_send_rpc(nc_client, rpc_node, 1000);
165 log_error("feature-control rpc failed");
166 return NTS_ERR_FAILED;
169 lyd_free_withsiblings(rpcout);
171 lyd_free_withsiblings(rpc_node);
174 instance->is_configured = true;
176 nc_client_disconnect(nc_client);
181 int manager_stop_instance(manager_network_function_type *function_type) {
182 assert(function_type);
184 manager_network_function_instance_t *instance = &function_type->instance[function_type->started_instances - 1];
186 if(instance->is_mounted) {
187 if(manager_unmount_instance(function_type) != NTS_ERR_OK) {
188 return NTS_ERR_FAILED;
192 int rc = docker_device_stop(instance);
193 if(rc != NTS_ERR_OK) {
194 log_error("docker_device_stop failed");
195 return NTS_ERR_FAILED;
199 manager_port[instance->host_port] = 0;
201 free(instance->mount_point_addressing_method);
202 free(instance->docker_id);
203 free(instance->name);
204 free(instance->docker_ip);
205 free(instance->host_ip);
207 function_type->started_instances--;
208 if(function_type->started_instances) {
209 function_type->instance = (manager_network_function_instance_t *)realloc(function_type->instance, sizeof(manager_network_function_instance_t) * function_type->started_instances);
210 if(function_type->instance == 0) {
211 log_error("realloc failed");
212 return NTS_ERR_FAILED;
216 free(function_type->instance);
217 function_type->instance = 0;
222 int manager_mount_instance(manager_network_function_type *function_type) {
223 assert(function_type);
225 manager_network_function_instance_t *instance = &function_type->instance[function_type->mounted_instances];
227 if(instance->is_mounted == true) {
228 return NTS_ERR_FAILED;
231 controller_details_t *controller;
232 controller = controller_details_get(0);
233 if(controller == 0) {
234 log_error("could not get controller detailes");
235 return NTS_ERR_FAILED;
238 for(int i = 0; i < (framework_environment.ssh_connections + framework_environment.tls_connections); i++) {
241 if(i < framework_environment.ssh_connections) {
244 \"network-topology:netconf-node-topology:username\": \"netconf\",\
245 \"network-topology:netconf-node-topology:password\": \"netconf\"";
251 \"netconf-node-topology:key-based\" : {\
252 \"netconf-node-topology:username\" : \"netconf\",\
253 \"netconf-node-topology:key-id\" : \""KS_KEY_NAME"\"\
257 char *json_template = "\
259 \"network-topology:node\": [{\
260 \"network-topology:node-id\": \"%s\",\
261 \"network-topology:netconf-node-topology:host\": \"%s\",\
262 \"network-topology:netconf-node-topology:port\": \"%d\",\
263 \"network-topology:netconf-node-topology:tcp-only\": \"false\",\
264 \"network-topology:netconf-node-topology:protocol\": {\
265 \"network-topology:netconf-node-topology:name\": \"%s\"\
268 \"network-topology:netconf-node-topology:connection-timeout-millis\": \"20000\",\
269 \"network-topology:netconf-node-topology:default-request-timeout-millis\": \"60000\",\
270 \"network-topology:netconf-node-topology:max-connection-attempts\": \"3\"\
277 if(instance->mount_point_addressing_method[0] == 'd') {
278 ip = instance->docker_ip;
279 port = instance->docker_port + i;
282 ip = instance->host_ip;
283 port = instance->host_port + i;
286 asprintf(&node_id, "%s-%d", instance->name, port);
287 asprintf(&json, json_template, node_id, ip, port, protocol, protocol_data);
290 asprintf(&url, "%s/rests/data/network-topology:network-topology/topology=topology-netconf/node=%s", controller->base_url, node_id);
291 int rc = http_request(url, controller->username, controller->password, "PUT", json, 0, 0);
292 if(rc != NTS_ERR_OK) {
293 log_error("http_request failed");
294 return NTS_ERR_FAILED;
302 controller_details_free(controller);
304 instance->is_mounted = true;
305 function_type->mounted_instances++;
310 int manager_unmount_instance(manager_network_function_type *function_type) {
311 assert(function_type);
313 manager_network_function_instance_t *instance = &function_type->instance[function_type->mounted_instances - 1];
315 if(instance->is_mounted == false) {
316 log_error("tried to unmount an unmounted instance");
317 return NTS_ERR_FAILED;
320 controller_details_t *controller;
321 controller = controller_details_get(0);
322 if(controller == 0) {
323 log_error("could not get controller detailes");
324 return NTS_ERR_FAILED;
327 for(int i = 0; i < (framework_environment.ssh_connections + framework_environment.tls_connections); i++) {
329 if(function_type->mount_point_addressing_method[0] == 'd') {
330 port = instance->docker_port + i;
333 port = instance->host_port + i;
336 asprintf(&node_id, "%s-%d", instance->name, port);
339 asprintf(&url, "%s/rests/data/network-topology:network-topology/topology=topology-netconf/node=%s", controller->base_url, node_id);
340 int rc = http_request(url, controller->username, controller->password, "DELETE", "", 0, 0);
341 if(rc != NTS_ERR_OK) {
342 log_error("http_request failed");
343 return NTS_ERR_FAILED;
350 controller_details_free(controller);
352 function_type->mounted_instances--;
353 function_type->instance[function_type->mounted_instances].is_mounted = false;