Add NF addressing method as ENV.
[sim/o1-interface.git] / ntsimulator / ntsim-ng / features / ves_file_ready / ves_file_ready.c
1 /*************************************************************************
2 *
3 * Copyright 2020 highstreet technologies GmbH and others
4 *
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
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
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 ***************************************************************************/
17
18 #define _GNU_SOURCE
19
20 #include "ves_file_ready.h"
21 #include "utils/log_utils.h"
22 #include "utils/sys_utils.h"
23 #include "utils/http_client.h"
24 #include "utils/nts_utils.h"
25 #include <stdio.h>
26 #include <assert.h>
27
28 #include <sysrepo.h>
29 #include <sysrepo/values.h>
30
31 #include "core/framework.h"
32 #include "core/session.h"
33 #include "core/xpath.h"
34
35 static int ves_file_ready_invoke_pm_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data);
36 static int ves_file_ready_send_message(sr_session_ctx_t *session, const char *file_location, int port);
37 static cJSON* ves_create_file_ready_fields(const char* file_location);
38 static void ves_file_ready_vsftp_daemon_init(void);
39 static void ves_file_ready_vsftp_daemon_deinit(void);
40
41 static sr_subscription_ctx_t *ves_file_ready_subscription = 0;
42
43 int ves_file_ready_feature_get_status(void) {
44     return (ves_file_ready_subscription != 0);
45 }
46
47 int ves_file_ready_feature_start(sr_session_ctx_t *current_session) {
48     assert(current_session);
49     assert_session();
50
51     if(ves_file_ready_subscription == 0) {
52         int rc = sr_rpc_subscribe(current_session, NTS_NF_RPC_FILE_READY_SCHEMA_XPATH, ves_file_ready_invoke_pm_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &ves_file_ready_subscription);
53         if(rc != SR_ERR_OK) {
54             log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc));
55             return NTS_ERR_FAILED;
56         }
57
58         ves_file_ready_vsftp_daemon_init();
59     }
60
61     return NTS_ERR_OK;
62 }
63
64 int ves_file_ready_feature_stop(void) {
65     assert_session();
66
67     if(ves_file_ready_subscription) {
68         int rc = sr_unsubscribe(ves_file_ready_subscription);
69         if(rc != SR_ERR_OK) {
70             log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc));
71             return NTS_ERR_FAILED;
72         }
73
74         ves_file_ready_vsftp_daemon_deinit();
75         ves_file_ready_subscription = 0;
76     }
77
78     return NTS_ERR_OK;
79 }
80
81 static void ves_file_ready_vsftp_daemon_init(void) {
82     system("/usr/sbin/vsftpd &");
83 }
84
85 static void ves_file_ready_vsftp_daemon_deinit(void) {
86     system("killall -9 vsftpd");
87 }
88
89 static int ves_file_ready_invoke_pm_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) {
90     int ssh_base_port = 0;
91     int tls_base_port = 0;
92     nts_mount_point_addressing_method_t mp = nts_mount_point_addressing_method_get(session);
93     if(mp == UNKNOWN_MAPPING) {
94         log_error("mount-point-addressing-method failed\n");
95         return NTS_ERR_FAILED;
96     }
97     else if(mp == DOCKER_MAPPING) {
98         ssh_base_port = STANDARD_NETCONF_PORT;
99         tls_base_port = ssh_base_port + framework_environment.settings.ssh_connections;
100     }
101     else {
102         ssh_base_port = framework_environment.host.ssh_base_port;
103         tls_base_port = framework_environment.host.tls_base_port;       
104     }
105
106     int failed = 0;
107
108     if((framework_environment.settings.ssh_connections + framework_environment.settings.tls_connections) > 1) {
109         for(int port = ssh_base_port; port < ssh_base_port + framework_environment.settings.ssh_connections; port++) {
110             int rc = ves_file_ready_send_message(session, input[0].data.string_val, port);
111             if(rc != NTS_ERR_OK) {
112                 log_error("ves_file_ready_send_message failed\n");
113                 failed++;
114             }
115         }
116
117         for(int port = tls_base_port; port < tls_base_port + framework_environment.settings.tls_connections; port++) {
118             int rc = ves_file_ready_send_message(session, input[0].data.string_val, port);
119             if(rc != NTS_ERR_OK) {
120                 log_error("ves_file_ready_send_message failed\n");
121                 failed++;
122             }
123         }
124     }
125     else {
126         int rc = ves_file_ready_send_message(session, input[0].data.string_val, 0);
127         if(rc != NTS_ERR_OK) {
128             log_error("ves_file_ready_send_message failed\n");
129             failed++;
130         }
131     }
132     
133
134     *output_cnt = 1;
135     int rc = sr_new_values(*output_cnt, output);
136     if(SR_ERR_OK != rc) {
137         return rc;
138     }
139
140     rc = sr_val_set_xpath(output[0], NTS_NF_RPC_FILE_READY_SCHEMA_XPATH"/status");
141     if(SR_ERR_OK != rc) {
142         return rc;
143     }
144     
145     if(failed != 0) {
146         rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "ERROR");
147     }
148     else {
149         rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
150     }
151
152     return rc;
153 }
154
155 static int ves_file_ready_send_message(sr_session_ctx_t *session, const char *file_location, int port) {
156     assert(session);
157     assert(file_location);
158
159     int rc;
160     static int sequence_number = 0;
161
162     cJSON *post_data_json = cJSON_CreateObject();
163     if(post_data_json == 0) {
164         log_error("could not create cJSON object\n");
165         return NTS_ERR_FAILED;
166     }
167
168     cJSON *event = cJSON_CreateObject();
169     if(event == 0) {
170         log_error("could not create cJSON object\n");
171         cJSON_Delete(post_data_json);
172         return NTS_ERR_FAILED;
173     }
174     
175     if(cJSON_AddItemToObject(post_data_json, "event", event) == 0) {
176         log_error("cJSON_AddItemToObject failed\n");
177         cJSON_Delete(post_data_json);
178         return NTS_ERR_FAILED;
179     }
180
181     cJSON *common_event_header = ves_create_common_event_header("notification", "Notification-gnb_Nokia-FileReady", framework_environment.settings.hostname, port, "Normal", sequence_number++);
182     if(common_event_header == 0) {
183         log_error("could not create cJSON object\n");
184         cJSON_Delete(post_data_json);
185         return NTS_ERR_FAILED;
186     }
187     
188     if(cJSON_AddItemToObject(event, "commonEventHeader", common_event_header) == 0) {
189         log_error("cJSON_AddItemToObject failed\n");
190         cJSON_Delete(post_data_json);
191         return NTS_ERR_FAILED;
192     }
193
194     cJSON *file_ready_fields = ves_create_file_ready_fields(file_location);
195     if(file_ready_fields == 0) {
196         log_error("could not create cJSON object\n");
197         cJSON_Delete(post_data_json);
198         return NTS_ERR_FAILED;
199     }
200     
201     if(cJSON_AddItemToObject(event, "notificationFields", file_ready_fields) == 0) {
202         log_error("cJSON_AddItemToObject failed\n");
203         cJSON_Delete(post_data_json);
204         return NTS_ERR_FAILED;
205     }
206
207     char *post_data = cJSON_PrintUnformatted(post_data_json);
208     cJSON_Delete(post_data_json);
209     if(post_data == 0) {
210         log_error("cJSON_PrintUnformatted failed\n");
211         return NTS_ERR_FAILED;
212     }
213
214
215     ves_details_t *ves_details = ves_endpoint_details_get(session);
216     if(!ves_details) {
217         log_error("ves_endpoint_details_get failed\n");
218         free(post_data);
219         return NTS_ERR_FAILED;
220     }
221     
222     rc = http_request(ves_details->url, ves_details->username, ves_details->password, "POST", post_data, 0, 0);
223     ves_details_free(ves_details);
224     free(post_data);
225     
226     if(rc != NTS_ERR_OK) {
227         log_error("http_request failed\n");
228         return NTS_ERR_FAILED;
229     }
230
231     return NTS_ERR_OK;
232 }
233
234 static cJSON* ves_create_file_ready_fields(const char* file_location) {
235     assert(file_location);
236
237     cJSON *file_ready_fields = cJSON_CreateObject();
238     if(file_ready_fields == 0) {
239         log_error("could not create JSON object\n");
240         return 0;
241     }
242
243     if(cJSON_AddStringToObject(file_ready_fields, "changeIdentifier", "PM_MEAS_FILES") == 0) {
244         log_error("cJSON_AddStringToObject failed\n");
245         cJSON_Delete(file_ready_fields);
246         return 0;
247     }
248
249     if(cJSON_AddStringToObject(file_ready_fields, "changeType", "FileReady") == 0) {
250         log_error("cJSON_AddStringToObject failed\n");
251         cJSON_Delete(file_ready_fields);
252         return 0;
253     }
254
255     if(cJSON_AddStringToObject(file_ready_fields, "notificationFieldsVersion", "2.0") == 0) {
256         log_error("cJSON_AddStringToObject failed\n");
257         cJSON_Delete(file_ready_fields);
258         return 0;
259     }
260
261     cJSON *array_of_named_hash_map = cJSON_CreateArray();
262     if(array_of_named_hash_map == 0) {
263         log_error("could not create JSON object\n");
264         cJSON_Delete(file_ready_fields);
265         return 0;
266     }
267     
268     if(cJSON_AddItemToObject(file_ready_fields, "arrayOfNamedHashMap", array_of_named_hash_map) == 0) {
269         log_error("cJSON_AddStringToObject failed\n");
270         cJSON_Delete(file_ready_fields);
271         return 0;
272     }
273
274     cJSON *additional_fields_entry = cJSON_CreateObject();
275     if(additional_fields_entry == 0) {
276         log_error("could not create JSON object\n");
277         cJSON_Delete(file_ready_fields);
278         return 0;
279     }
280
281     char *filename = strrchr(file_location, '/');
282
283     if(filename == 0) {
284         if(cJSON_AddStringToObject(additional_fields_entry, "name", "dummy_file.tar.gz") == 0) {
285             log_error("cJSON_AddStringToObject failed\n");
286             cJSON_Delete(file_ready_fields);
287             return 0;
288         }
289     }
290     else {
291         if(cJSON_AddStringToObject(additional_fields_entry, "name", filename + 1) == 0) {
292             log_error("cJSON_AddStringToObject failed\n");
293             cJSON_Delete(file_ready_fields);
294             return 0;
295         }
296     }
297
298     cJSON *hash_map = cJSON_CreateObject();
299     if(hash_map == 0) {
300         log_error("could not create JSON object\n");
301         cJSON_Delete(file_ready_fields);
302         return 0;
303     }
304     
305     if(cJSON_AddItemToObject(additional_fields_entry, "hashMap", hash_map) == 0) {
306         log_error("cJSON_AddStringToObject failed\n");
307         cJSON_Delete(file_ready_fields);
308         return 0;
309     }
310
311     if(cJSON_AddStringToObject(hash_map, "location", file_location) == 0) {
312         log_error("cJSON_AddStringToObject failed\n");
313         cJSON_Delete(file_ready_fields);
314         return 0;
315     }
316
317     if(cJSON_AddStringToObject(hash_map, "compression", "gzip") == 0) {
318         log_error("cJSON_AddStringToObject failed\n");
319         cJSON_Delete(file_ready_fields);
320         return 0;
321     }
322
323     if(cJSON_AddStringToObject(hash_map, "fileFormatType", "org.3GPP.32.435#measCollec") == 0) {
324         log_error("cJSON_AddStringToObject failed\n");
325         cJSON_Delete(file_ready_fields);
326         return 0;
327     }
328
329     if(cJSON_AddStringToObject(hash_map, "fileFormatVersion", "V5") == 0) {
330         log_error("cJSON_AddStringToObject failed\n");
331         cJSON_Delete(file_ready_fields);
332         return 0;
333     }
334
335     if(cJSON_AddItemToArray(array_of_named_hash_map, additional_fields_entry) == 0) {
336         log_error("cJSON_AddStringToObject failed\n");
337         cJSON_Delete(file_ready_fields);
338         return 0;
339     }
340
341     return file_ready_fields;
342 }