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