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