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"
28 #include "core/framework.h"
29 #include "core/docker.h"
30 #include "core/session.h"
31 #include "core/xpath.h"
32 #include "core/nc_config.h"
33 #include "utils/nc_client.h"
34 #include "utils/http_client.h"
35 #include "utils/nts_utils.h"
37 int manager_actions_start(manager_context_t *ctx) {
40 int started_instances = ctx->started_instances;
41 char instance_name[512];
42 sprintf(instance_name, "%s-%d", ctx->docker_instance_name, started_instances);
44 uint16_t netconf_ssh_port = framework_environment.host.ssh_base_port;
45 uint16_t netconf_tls_port = framework_environment.host.tls_base_port;
46 uint16_t ftp_port = framework_environment.host.ftp_base_port;
47 uint16_t sftp_port = framework_environment.host.sftp_base_port;
49 if(framework_environment.settings.ssh_connections) {
50 while((netconf_ssh_port) && (manager_port[netconf_ssh_port] != MANAGER_PROTOCOL_UNUSED)) {
54 for(int i = 0; i < framework_environment.settings.ssh_connections; i++) {
55 if(manager_port[i + netconf_ssh_port] != MANAGER_PROTOCOL_UNUSED) {
56 log_error("no ports available for operation for ssh\n");
57 manager_sr_notif_send_instance_changed("start FAILED - no ports available for ssh", ctx->function_type, instance_name, 0);
58 return NTS_ERR_FAILED;
62 for(int i = 0; i < framework_environment.settings.ssh_connections; i++) {
63 manager_port[i + netconf_ssh_port] = MANAGER_PROTOCOL_NETCONF_SSH;
67 if(framework_environment.settings.tls_connections) {
68 while((netconf_tls_port) && (manager_port[netconf_tls_port] != MANAGER_PROTOCOL_UNUSED)) {
72 for(int i = 0; i < framework_environment.settings.tls_connections; i++) {
73 if(manager_port[i + netconf_tls_port] != MANAGER_PROTOCOL_UNUSED) {
74 log_error("no ports available for operation for tls\n");
75 manager_sr_notif_send_instance_changed("start FAILED - no ports available for tls", ctx->function_type, instance_name, 0);
77 for(int i = 0; i < framework_environment.settings.ssh_connections; i++) {
78 manager_port[i + netconf_ssh_port] = MANAGER_PROTOCOL_UNUSED;
80 return NTS_ERR_FAILED;
84 for(int i = 0; i < framework_environment.settings.tls_connections; i++) {
85 manager_port[i + netconf_tls_port] = MANAGER_PROTOCOL_NETCONF_TLS;
89 if(framework_environment.settings.ftp_connections) {
90 while((ftp_port) && (manager_port[ftp_port] != MANAGER_PROTOCOL_UNUSED)) {
94 for(int i = 0; i < framework_environment.settings.ftp_connections; i++) {
95 if(manager_port[i + ftp_port] != MANAGER_PROTOCOL_UNUSED) {
96 log_error("no ports available for operation for ftp\n");
97 manager_sr_notif_send_instance_changed("start FAILED - no ports available for ftp", ctx->function_type, instance_name, 0);
99 for(int i = 0; i < framework_environment.settings.ssh_connections; i++) {
100 manager_port[i + netconf_ssh_port] = MANAGER_PROTOCOL_UNUSED;
103 for(int i = 0; i < framework_environment.settings.tls_connections; i++) {
104 manager_port[i + netconf_tls_port] = MANAGER_PROTOCOL_UNUSED;
106 return NTS_ERR_FAILED;
110 for(int i = 0; i < framework_environment.settings.ftp_connections; i++) {
111 manager_port[i + ftp_port] = MANAGER_PROTOCOL_FTP;
115 if(framework_environment.settings.sftp_connections) {
116 while((sftp_port) && (manager_port[sftp_port] != MANAGER_PROTOCOL_UNUSED)) {
120 for(int i = 0; i < framework_environment.settings.sftp_connections; i++) {
121 if(manager_port[i + sftp_port] != MANAGER_PROTOCOL_UNUSED) {
122 log_error("no ports available for operation for sftp\n");
123 manager_sr_notif_send_instance_changed("start FAILED - no ports available for sftp", ctx->function_type, instance_name, 0);
125 for(int i = 0; i < framework_environment.settings.ssh_connections; i++) {
126 manager_port[i + netconf_ssh_port] = MANAGER_PROTOCOL_UNUSED;
129 for(int i = 0; i < framework_environment.settings.tls_connections; i++) {
130 manager_port[i + netconf_tls_port] = MANAGER_PROTOCOL_UNUSED;
133 for(int i = 0; i < framework_environment.settings.ftp_connections; i++) {
134 manager_port[i + ftp_port] = MANAGER_PROTOCOL_UNUSED;
136 return NTS_ERR_FAILED;
140 for(int i = 0; i < framework_environment.settings.sftp_connections; i++) {
141 manager_port[i + sftp_port] = MANAGER_PROTOCOL_SFTP;
145 ctx->instance = (manager_network_function_instance_t *)realloc(ctx->instance, sizeof(manager_network_function_instance_t) * (started_instances + 1));
146 if(ctx->instance == 0) {
147 log_error("realloc failed\n");
148 manager_sr_notif_send_instance_changed("start FAILED - realloc error", ctx->function_type, instance_name, 0);
149 for(int i = 0; i < framework_environment.settings.ssh_connections; i++) {
150 manager_port[i + netconf_ssh_port] = MANAGER_PROTOCOL_UNUSED;
153 for(int i = 0; i < framework_environment.settings.tls_connections; i++) {
154 manager_port[i + netconf_tls_port] = MANAGER_PROTOCOL_UNUSED;
157 for(int i = 0; i < framework_environment.settings.ftp_connections; i++) {
158 manager_port[i + ftp_port] = MANAGER_PROTOCOL_UNUSED;
161 for(int i = 0; i < framework_environment.settings.sftp_connections; i++) {
162 manager_port[i + sftp_port] = MANAGER_PROTOCOL_UNUSED;
164 return NTS_ERR_FAILED;
167 manager_network_function_instance_t *instance = &ctx->instance[started_instances];
168 instance->is_init = false;
169 instance->is_configured = false;
170 instance->is_mounted = false;
171 instance->mount_point_addressing_method = strdup(ctx->mount_point_addressing_method);
173 int rc = docker_start(instance_name, ctx->docker_version_tag, ctx->docker->image, ctx->docker_repository, netconf_ssh_port, netconf_tls_port, ftp_port, sftp_port, &instance->container);
174 if(rc != NTS_ERR_OK) {
175 log_error("docker_start failed\n");
176 manager_sr_notif_send_instance_changed("start FAILED - Docker start error", ctx->function_type, instance_name, 0);
177 for(int i = 0; i < framework_environment.settings.ssh_connections; i++) {
178 manager_port[i + netconf_ssh_port] = MANAGER_PROTOCOL_UNUSED;
181 for(int i = 0; i < framework_environment.settings.tls_connections; i++) {
182 manager_port[i + netconf_tls_port] = MANAGER_PROTOCOL_UNUSED;
185 for(int i = 0; i < framework_environment.settings.ftp_connections; i++) {
186 manager_port[i + ftp_port] = MANAGER_PROTOCOL_UNUSED;
189 for(int i = 0; i < framework_environment.settings.sftp_connections; i++) {
190 manager_port[i + sftp_port] = MANAGER_PROTOCOL_UNUSED;
192 return NTS_ERR_FAILED;
195 ctx->started_instances++;
196 manager_sr_notif_send_instance_changed("start SUCCESS", ctx->function_type, instance_name, instance);
197 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET" started (%s); ports host(docker): ", instance_name, instance->mount_point_addressing_method);
198 if(framework_environment.settings.ssh_connections > 1) {
199 log_add(1, "NETCONF SSH: %d-%d(%d-%d)", instance->container.host_netconf_ssh_port, (instance->container.host_netconf_ssh_port + framework_environment.settings.ssh_connections - 1), instance->container.docker_netconf_ssh_port, (instance->container.docker_netconf_ssh_port + framework_environment.settings.ssh_connections - 1));
201 else if(framework_environment.settings.ssh_connections == 1) {
202 log_add(1, "NETCONF SSH: %d(%d)", instance->container.host_netconf_ssh_port, instance->container.docker_netconf_ssh_port);
205 log_add(1, "NETCONF SSH: disabled");
208 if(framework_environment.settings.tls_connections > 1) {
209 log_add(1, " | NETCONF TLS: %d-%d(%d-%d)", instance->container.host_netconf_tls_port, (instance->container.host_netconf_tls_port + framework_environment.settings.tls_connections - 1), instance->container.docker_netconf_tls_port, (instance->container.docker_netconf_tls_port + framework_environment.settings.tls_connections - 1));
211 else if(framework_environment.settings.tls_connections == 1) {
212 log_add(1, " | NETCONF TLS: %d(%d)", instance->container.host_netconf_tls_port, instance->container.docker_netconf_tls_port);
215 log_add(1, " | NETCONF TLS: disabled");
218 if(framework_environment.settings.ftp_connections > 1) {
219 log_add(1, " | FTP: %d-%d(%d-%d)", instance->container.host_ftp_port, (instance->container.host_ftp_port + framework_environment.settings.ftp_connections - 1), instance->container.docker_ftp_port, (instance->container.docker_ftp_port + framework_environment.settings.ftp_connections - 1));
221 else if(framework_environment.settings.ftp_connections == 1) {
222 log_add(1, " | FTP: %d(%d)", instance->container.host_ftp_port, instance->container.docker_ftp_port);
225 log_add(1, " | FTP: disabled");
228 if(framework_environment.settings.sftp_connections > 1) {
229 log_add(1, " | SFTP: %d-%d(%d-%d)", instance->container.host_sftp_port, (instance->container.host_sftp_port + framework_environment.settings.sftp_connections - 1), instance->container.docker_sftp_port, (instance->container.docker_sftp_port + framework_environment.settings.sftp_connections - 1));
231 else if(framework_environment.settings.sftp_connections == 1) {
232 log_add(1, " | SFTP: %d(%d)", instance->container.host_sftp_port, instance->container.docker_sftp_port);
235 log_add(1, " | SFTP: disabled");
244 int manager_actions_config_instance(manager_context_t *ctx, manager_network_function_instance_t *instance) {
248 //first wait for the nc server to be up and running
250 while(check_port_open(instance->container.docker_ip, CLIENT_CONFIG_TLS_PORT) == false) {
254 log_error("manager_actions_config_instance() could not connect to %s, as port is not open\n", instance->container.name);
255 return NTS_ERR_FAILED;
259 //populate sdn-controller and ves-endpoint
260 struct lyd_node *local_tree = 0;
261 int rc = lyd_utils_dup(session_running, NTS_MANAGER_SDN_CONTROLLER_CONFIG_XPATH, NTS_NF_SDN_CONTROLLER_CONFIG_XPATH, &local_tree);
262 if(rc != NTS_ERR_OK) {
263 log_error("lyd_utils_dup failed\n");
264 manager_sr_notif_send_instance_changed("config FAILED - libyang", ctx->function_type, instance->container.name, instance);
265 return NTS_ERR_FAILED;
268 rc = lyd_utils_dup(session_running, NTS_MANAGER_VES_ENDPOINT_CONFIG_XPATH, NTS_NF_VES_ENDPOINT_CONFIG_XPATH, &local_tree);
269 if(rc != NTS_ERR_OK) {
270 log_error("lyd_utils_dup failed\n");
271 manager_sr_notif_send_instance_changed("config FAILED - libyang", ctx->function_type, instance->container.name, instance);
272 lyd_free_withsiblings(local_tree);
273 return NTS_ERR_FAILED;
277 sprintf(xpath_s, NTS_MANAGER_FUNCTION_LIST_SCHEMA_XPATH"[function-type='%s']", ctx->function_type);
278 rc = lyd_utils_dup(session_running, xpath_s, NTS_NF_NETWORK_FUNCTION_SCHEMA_XPATH, &local_tree);
279 if(rc != NTS_ERR_OK) {
280 log_error("lyd_utils_dup failed\n");
281 manager_sr_notif_send_instance_changed("config FAILED - libyang", ctx->function_type, instance->container.name, instance);
282 lyd_free_withsiblings(local_tree);
283 return NTS_ERR_FAILED;
286 nc_client_t *nc_client = nc_client_tls_connect(instance->container.docker_ip, CLIENT_CONFIG_TLS_PORT);
287 // nc_client_t *nc_client = nc_client_ssh_connect(instance->container.docker_ip, instance->container.docker_port, "netconf", "netconf!");
289 log_error("nc_client_tls_connect\n");
290 manager_sr_notif_send_instance_changed("config FAILED - netconf client connect", ctx->function_type, instance->container.name, instance);
291 lyd_free_withsiblings(local_tree);
292 return NTS_ERR_FAILED;
295 rc += nc_client_edit_batch(nc_client, local_tree, 5000);
296 lyd_free_withsiblings(local_tree);
297 if(rc != NTS_ERR_OK) {
298 log_error("nc_client_edit_batch failed %d\n", rc);
299 manager_sr_notif_send_instance_changed("config FAILED - netconf edit batch", ctx->function_type, instance->container.name, instance);
300 nc_client_disconnect(nc_client);
301 return NTS_ERR_FAILED;
304 if(instance->is_init == false) {
305 //run datastore-populate rpc
306 struct lyd_node *rpc_node = 0;
307 struct lyd_node *rpcout = 0;
308 rpc_node = lyd_new_path(0, session_context, NTS_NF_RPC_POPULATE_SCHEMA_XPATH, 0, 0, 0);
310 log_error("failed to create rpc node\n");
311 manager_sr_notif_send_instance_changed("config FAILED - populate RPC", ctx->function_type, instance->container.name, instance);
312 nc_client_disconnect(nc_client);
313 return NTS_ERR_FAILED;
316 rpcout = nc_client_send_rpc(nc_client, rpc_node, 10000);
318 log_error("datastore-populate rpc failed\n");
319 manager_sr_notif_send_instance_changed("config FAILED - datastore populate RPC", ctx->function_type, instance->container.name, instance);
320 nc_client_disconnect(nc_client);
321 lyd_free_withsiblings(rpc_node);
322 return NTS_ERR_FAILED;
325 lyd_free_withsiblings(rpcout);
327 lyd_free_withsiblings(rpc_node);
329 //run feature-control rpc
330 rpc_node = lyd_new_path(0, session_context, NTS_NF_RPC_FEATURE_CONTROL_SCHEMA_XPATH"/start-features", "ves-file-ready ves-heartbeat ves-pnf-registration manual-notification-generation netconf-call-home web-cut-through", 0, 0);
332 log_error("failed to create rpc node\n");
333 manager_sr_notif_send_instance_changed("config FAILED - feature-control RPC", ctx->function_type, instance->container.name, instance);
334 nc_client_disconnect(nc_client);
335 return NTS_ERR_FAILED;
338 rpcout = nc_client_send_rpc(nc_client, rpc_node, 10000);
340 log_error("feature-control rpc failed\n");
341 manager_sr_notif_send_instance_changed("config FAILED - feature-control RPC", ctx->function_type, instance->container.name, instance);
342 nc_client_disconnect(nc_client);
343 lyd_free_withsiblings(rpc_node);
344 return NTS_ERR_FAILED;
347 lyd_free_withsiblings(rpcout);
349 lyd_free_withsiblings(rpc_node);
352 instance->is_init = true;
353 instance->is_configured = true;
354 nc_client_disconnect(nc_client);
355 manager_sr_notif_send_instance_changed("config SUCCESS", ctx->function_type, instance->container.name, instance);
356 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET" configured via netconf\n", instance->container.name);
361 int manager_actions_stop(manager_context_t *ctx) {
364 manager_network_function_instance_t *instance = &ctx->instance[ctx->started_instances - 1];
365 char instance_name[512];
366 strcpy(instance_name, instance->container.name);
368 if(instance->is_mounted) {
369 if(manager_actions_unmount(ctx) != NTS_ERR_OK) {
370 log_error("failed to unmount instance\n");
374 int rc = docker_stop(&instance->container);
375 if(rc != NTS_ERR_OK) {
376 log_error("docker_device_stop failed\n");
377 manager_sr_notif_send_instance_changed("stop FAILED - Docker error", ctx->function_type, instance_name, 0);
378 return NTS_ERR_FAILED;
382 for(int i = 0; i < framework_environment.settings.ssh_connections; i++) {
383 manager_port[i + ctx->instance[ctx->started_instances - 1].container.host_netconf_ssh_port] = MANAGER_PROTOCOL_UNUSED;
386 for(int i = 0; i < framework_environment.settings.tls_connections; i++) {
387 manager_port[i + ctx->instance[ctx->started_instances - 1].container.host_netconf_tls_port] = MANAGER_PROTOCOL_UNUSED;
390 for(int i = 0; i < framework_environment.settings.ftp_connections; i++) {
391 manager_port[i + ctx->instance[ctx->started_instances - 1].container.host_ftp_port] = MANAGER_PROTOCOL_UNUSED;
394 for(int i = 0; i < framework_environment.settings.sftp_connections; i++) {
395 manager_port[i + ctx->instance[ctx->started_instances - 1].container.host_sftp_port] = MANAGER_PROTOCOL_UNUSED;
398 free(instance->mount_point_addressing_method);
400 if(ctx->started_instances > 1) {
401 ctx->instance = (manager_network_function_instance_t *)realloc(ctx->instance, sizeof(manager_network_function_instance_t) * ctx->started_instances);
402 if(ctx->instance == 0) {
403 log_error("realloc failed\n");
404 manager_sr_notif_send_instance_changed("stop FAILED - realloc", ctx->function_type, instance_name, 0);
405 return NTS_ERR_FAILED;
412 ctx->started_instances--;
413 manager_sr_notif_send_instance_changed("stop SUCCESS", ctx->function_type, instance_name, 0);
414 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET" stopped\n", instance_name);
420 int manager_actions_mount(manager_context_t *ctx) {
423 manager_network_function_instance_t *instance = &ctx->instance[ctx->mounted_instances];
425 if(instance->is_mounted == true) {
426 manager_sr_notif_send_instance_changed("mount SUCCESS - already mounted", ctx->function_type, instance->container.name, instance);
430 controller_details_t *controller;
431 controller = controller_details_get(0);
432 if(controller == 0) {
433 log_error("could not get controller details\n");
434 manager_sr_notif_send_instance_changed("mount FAILED - no controller details", ctx->function_type, instance->container.name, instance);
435 return NTS_ERR_FAILED;
438 for(int i = 0; i < (framework_environment.settings.ssh_connections + framework_environment.settings.tls_connections); i++) {
444 if(instance->mount_point_addressing_method[0] == 'd') {
445 ip = instance->container.docker_ip;
448 ip = instance->container.host_ip;
452 if(i < framework_environment.settings.ssh_connections) {
455 \"network-topology:netconf-node-topology:username\": \"netconf\",\
456 \"network-topology:netconf-node-topology:password\": \"netconf!\"";
458 if(instance->mount_point_addressing_method[0] == 'd') {
459 port = instance->container.docker_netconf_ssh_port + i;
462 port = instance->container.host_netconf_ssh_port + i;
468 \"netconf-node-topology:key-based\" : {\
469 \"netconf-node-topology:username\" : \"netconf\",\
470 \"netconf-node-topology:key-id\" : \""KS_KEY_NAME"\"\
473 if(instance->mount_point_addressing_method[0] == 'd') {
474 port = instance->container.docker_netconf_tls_port + i - framework_environment.settings.ssh_connections;
477 port = instance->container.host_netconf_tls_port + i - framework_environment.settings.ssh_connections;
481 char *json_template = "\
483 \"network-topology:node\": [{\
484 \"network-topology:node-id\": \"%s\",\
485 \"network-topology:netconf-node-topology:host\": \"%s\",\
486 \"network-topology:netconf-node-topology:port\": \"%d\",\
487 \"network-topology:netconf-node-topology:tcp-only\": \"false\",\
488 \"network-topology:netconf-node-topology:protocol\": {\
489 \"network-topology:netconf-node-topology:name\": \"%s\"\
492 \"network-topology:netconf-node-topology:connection-timeout-millis\": \"20000\",\
493 \"network-topology:netconf-node-topology:default-request-timeout-millis\": \"60000\",\
494 \"network-topology:netconf-node-topology:max-connection-attempts\": \"3\"\
500 if(framework_environment.settings.ssh_connections + framework_environment.settings.tls_connections > 1) {
501 sprintf(node_id, "%s-%d", instance->container.name, port);
504 sprintf(node_id, "%s", instance->container.name);
506 sprintf(json, json_template, node_id, ip, port, protocol, protocol_data);
509 sprintf(url, "%s/rests/data/network-topology:network-topology/topology=topology-netconf/node=%s", controller->base_url, node_id);
510 int rc = http_request(url, controller->username, controller->password, "PUT", json, 0, 0);
511 if(rc != NTS_ERR_OK) {
512 log_error("http_request failed\n");
513 controller_details_free(controller);
514 manager_sr_notif_send_instance_changed("mount FAILED - REST request", ctx->function_type, instance->container.name, instance);
515 return NTS_ERR_FAILED;
519 controller_details_free(controller);
521 instance->is_mounted = true;
522 ctx->mounted_instances++;
523 manager_sr_notif_send_instance_changed("mount SUCCESS", ctx->function_type, instance->container.name, instance);
524 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET" mounted\n", instance->container.name);
529 int manager_actions_unmount(manager_context_t *ctx) {
532 int ret = NTS_ERR_OK;
534 manager_network_function_instance_t *instance = &ctx->instance[ctx->mounted_instances - 1];
536 if(instance->is_mounted == false) {
537 log_error("tried to unmount an unmounted instance\n");
538 manager_sr_notif_send_instance_changed("unmount FAILED - already unmounted", ctx->function_type, instance->container.name, instance);
542 controller_details_t *controller;
543 controller = controller_details_get(0);
544 if(controller == 0) {
545 log_error("could not get controller details\n");
546 manager_sr_notif_send_instance_changed("unmount FAILED - no controller details", ctx->function_type, instance->container.name, instance);
547 return NTS_ERR_FAILED;
550 for(int i = 0; i < (framework_environment.settings.ssh_connections + framework_environment.settings.tls_connections); i++) {
552 if(i < framework_environment.settings.ssh_connections) {
553 if(instance->mount_point_addressing_method[0] == 'd') {
554 port = instance->container.docker_netconf_ssh_port + i;
557 port = instance->container.host_netconf_ssh_port + i;
561 if(instance->mount_point_addressing_method[0] == 'd') {
562 port = instance->container.docker_netconf_tls_port + i - framework_environment.settings.ssh_connections;
565 port = instance->container.host_netconf_tls_port + i - framework_environment.settings.ssh_connections;
569 if(framework_environment.settings.ssh_connections + framework_environment.settings.tls_connections > 1) {
570 sprintf(node_id, "%s-%d", instance->container.name, port);
573 sprintf(node_id, "%s", instance->container.name);
577 sprintf(url, "%s/rests/data/network-topology:network-topology/topology=topology-netconf/node=%s", controller->base_url, node_id);
578 int rc = http_request(url, controller->username, controller->password, "DELETE", "", 0, 0);
579 if(rc != NTS_ERR_OK) {
580 log_error("http_request failed\n");
581 manager_sr_notif_send_instance_changed("unmount FAILED - REST request", ctx->function_type, instance->container.name, instance);
582 ret = NTS_ERR_FAILED;
586 controller_details_free(controller);
588 ctx->mounted_instances--;
589 ctx->instance[ctx->mounted_instances].is_mounted = false;
590 manager_sr_notif_send_instance_changed("unmount SUCCESS", ctx->function_type, instance->container.name, instance);
591 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET" unmounted\n", instance->container.name);