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