Initial commit
[ta/config-manager.git] / cmframework / src / cmframework / server / cmrestapiv1.py
1 # Copyright 2019 Nokia
2
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 import logging
15 import json
16
17 from cmframework.apis import cmerror
18 from cmframework.server import cmrestapi
19 from cmframework.server.cmhttperrors import CMHTTPErrors
20
21
22 class CMRestAPIV1(cmrestapi.CMRestAPI):
23     def __init__(self, processor):
24         logging.debug('CMRestAPIV1 constructor called')
25         cmrestapi.CMRestAPI.__init__(self, 'v1.0', 'current', '1.0', processor)
26
27     def get_property(self, rpc):
28         """
29             Request: GET http://<cm-vip:port>/cm/v1.0/properties/
30                              <property-name>?snapshot=<snapshot name>
31             Response: {
32                 "name": "<name of the property>",
33                 "value": "<value of the property>",
34             }
35         """
36
37         logging.debug('get_property called')
38         try:
39             snapshot_name = rpc.req_filter.get('snapshot', None)
40             if isinstance(snapshot_name, list):
41                 snapshot_name = snapshot_name[0]
42             prop_name = rpc.req_params['property']
43             value = self.processor.get_property(prop_name, snapshot_name)
44             reply = {}
45             reply['name'] = prop_name
46             reply['value'] = value
47             rpc.rep_status = CMHTTPErrors.get_ok_status()
48             rpc.rep_body = json.dumps(reply)
49         except cmerror.CMError as exp:
50             rpc.rep_status = CMHTTPErrors.get_resource_not_found_status()
51             rpc.rep_status += ','
52             rpc.rep_status += str(exp)
53         except KeyError:
54             rpc.rep_status = CMHTTPErrors.get_resource_not_found_status()
55         except Exception as exp:  # pylint: disable=broad-except
56             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
57             rpc.rep_status += ','
58             rpc.rep_status += str(exp)
59
60     def get_properties(self, rpc):
61         """
62             Request: GET http://<cm-vip:port>/cm/v1.0/properties?
63                              prop-name-filter=<filter>&snapshot=<snapshot name>
64             Response: {
65                 "properties": [
66                     {
67                         "name": "<name of the property>",
68                         "value": "<value of the property>"
69                     },
70                     {
71                         "name": "<name of the property>",
72                         "value": "<value of the property>"
73                     }
74                     ....
75                 ]
76             }
77         """
78
79         logging.debug('get_properties called')
80         try:
81             prop_name_filter = rpc.req_filter.get('prop-name-filter', '')
82             if isinstance(prop_name_filter, list):
83                 prop_name_filter = prop_name_filter[0]
84             snapshot_name = rpc.req_filter.get('snapshot', None)
85             if isinstance(snapshot_name, list):
86                 snapshot_name = snapshot_name[0]
87             result = self.processor.get_properties(prop_name_filter, snapshot_name)
88             if not bool(result):
89                 rpc.rep_status = CMHTTPErrors.get_resource_not_found_status()
90             else:
91                 reply = {}
92                 items = []
93                 for key, value in result.iteritems():
94                     tmp = {}
95                     tmp['name'] = key
96                     tmp['value'] = value
97                     items.append(tmp)
98                 reply['properties'] = items
99                 rpc.rep_status = CMHTTPErrors.get_ok_status()
100                 rpc.rep_body = json.dumps(reply)
101         except cmerror.CMError as exp:
102             rpc.rep_status = CMHTTPErrors.get_resource_not_found_status()
103             rpc.rep_status += ','
104             rpc.rep_status += str(exp)
105         except Exception as exp:  # pylint: disable=broad-except
106             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
107             rpc.rep_status += ','
108             rpc.rep_status += str(exp)
109
110     def set_property(self, rpc):
111         """
112             Request: POST http://<cm-vip:port>/cm/v1.0/properties/<property-name>
113                 {
114                     "value": "<value of the property>"
115                 }
116             Response: http status set correctly
117                {
118                     "change-uuid": "<uuid>"
119                }
120         """
121
122         logging.debug('set_property called')
123         try:
124             if not rpc.req_body:
125                 rpc.rep_status = CMHTTPErrors.get_request_not_ok_status()
126             else:
127                 request = json.loads(rpc.req_body)
128                 name = rpc.req_params['property']
129                 value = request['value']
130                 uuid_value = self.processor.set_property(name, value)
131                 rpc.rep_status = CMHTTPErrors.get_ok_status()
132                 reply = {}
133                 reply['change-uuid'] = uuid_value
134                 rpc.rep_body = json.dumps(reply)
135         except cmerror.CMError as exp:
136             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
137             rpc.rep_status += ','
138             rpc.rep_status += str(exp)
139         except KeyError:
140             rpc.rep_status = CMHTTPErrors.get_request_not_ok_status()
141         except Exception as exp:  # pylint: disable=broad-except
142             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
143             rpc.rep_status += ','
144             rpc.rep_status += str(exp)
145
146     def set_properties(self, rpc):
147         """
148             Request: POST http://<cm-vip:port>/cm/v1.0/properties
149                 {
150                     "overwrite": True|False,
151                     "properties": [
152                         {
153                             "name": "<name of the property>",
154                             "value": "<value of the property>"
155                         },
156                         {
157                             "name": "<name of the property>",
158                             "value": "<value of the property>"
159                         },
160                         ....
161                     ]
162                 }
163             Response:
164                 {
165                      "change-uuid": "<uuid>"
166                 }
167         """
168
169         logging.debug('set_properties called')
170         try:
171             if not rpc.req_body:
172                 rpc.rep_status = CMHTTPErrors.get_request_not_ok_status()
173             else:
174                 request = json.loads(rpc.req_body)
175                 overwrite = False
176                 if 'overwrite' in request:
177                     overwrite = request['overwrite']
178                 items = request['properties']
179                 data = {}
180                 for entry in items:
181                     name = entry['name']
182                     value = entry['value']
183                     data[name] = value
184                 uuid_value = self.processor.set_properties(data, overwrite)
185                 rpc.rep_status = CMHTTPErrors.get_ok_status()
186                 reply = {}
187                 reply['change-uuid'] = uuid_value
188                 rpc.rep_body = json.dumps(reply)
189         except cmerror.CMError as exp:
190             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
191             rpc.rep_status += ','
192             rpc.rep_status += str(exp)
193         except KeyError:
194             rpc.rep_status = CMHTTPErrors.get_request_not_ok_status()
195         except Exception as exp:  # pylint: disable=broad-except
196             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
197             rpc.rep_status += ','
198             rpc.rep_status += str(exp)
199
200     def delete_property(self, rpc):
201         """
202             Request: DELETE http://<cm-vip:port>/cm/v1.0/properties/<property-name>
203             Response: http response with proper status
204                 {
205                     "change-uuid": "<uuid>"
206                 }
207         """
208
209         logging.debug('delete_property called')
210         try:
211             prop = rpc.req_params['property']
212             uuid_value = self.processor.delete_property(prop)
213             rpc.rep_status = CMHTTPErrors.get_ok_status()
214             reply = {}
215             reply['change-uuid'] = uuid_value
216             rpc.rep_body = json.dumps(reply)
217         except cmerror.CMError as exp:
218             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
219             rpc.rep_status += ','
220             rpc.rep_status += str(exp)
221         except KeyError:
222             rpc.rep_status = CMHTTPErrors.get_request_not_ok_status()
223         except Exception as exp:  # pylint: disable=broad-except
224             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
225             rpc.rep_status += ','
226             rpc.rep_status += str(exp)
227
228     def delete_properties(self, rpc):
229         """
230             Request: DELETE http://<cm-vip:port>/cm/v1.0/properties?prop-name-filter=<filter>
231                 {
232                     'properties': [ <prop-name>,
233                                     <prop-name>,
234                                     ....
235                                   ]
236                 }
237             Response: http response with proper status
238                {
239                     "change-uuid": "<uuid>"
240                }
241         """
242
243         logging.debug('delete_properties called')
244         try:
245             if not rpc.req_filter and not rpc.req_body:
246                 rpc.rep_status = CMHTTPErrors.get_request_not_ok_status()
247             else:
248                 if rpc.req_filter:
249                     arg = rpc.req_filter.get('prop-name-filter', '')
250                     if isinstance(arg, list):
251                         arg = arg[0]
252                 else:
253                     body = json.loads(rpc.req_body)
254                     arg = body['properties']
255                 uuid_value = self.processor.delete_properties(arg)
256                 rpc.rep_status = CMHTTPErrors.get_ok_status()
257                 reply = {}
258                 reply['change-uuid'] = uuid_value
259                 rpc.rep_body = json.dumps(reply)
260         except cmerror.CMError as exp:
261             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
262             rpc.rep_status += ','
263             rpc.rep_status += str(exp)
264         except KeyError:
265             rpc.rep_status = CMHTTPErrors.get_request_not_ok_status()
266         except Exception as exp:  # pylint: disable=broad-except
267             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
268             rpc.rep_status += ','
269             rpc.rep_status += str(exp)
270
271     def create_snapshot(self, rpc):
272         """
273             Request: GET http://<cm-vip:port>/cm/v1.0/snapshots/<snapshot name>
274             Response: http response with proper status
275         """
276
277         logging.debug('create snapshot called')
278         try:
279             snapshot_name = rpc.req_params['snapshot']
280             self.processor.create_snapshot(snapshot_name)
281             rpc.rep_status = CMHTTPErrors.get_ok_status()
282         except cmerror.CMError as exp:
283             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
284             rpc.rep_status += ','
285             rpc.rep_status += str(exp)
286         except Exception as exp:  # pylint: disable=broad-except
287             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
288             rpc.rep_status += ','
289             rpc.rep_status += str(exp)
290
291     def restore_snapshot(self, rpc):
292         """
293             Request: POST http://<cm-vip:port>/cm/v1.0/snapshots/<snapshot name>
294             Response: http response with proper status
295         """
296
297         logging.debug('restore_snapshot called')
298         try:
299             snapshot_name = rpc.req_params['snapshot']
300             self.processor.restore_snapshot(snapshot_name)
301             rpc.rep_status = CMHTTPErrors.get_ok_status()
302         except cmerror.CMError as exp:
303             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
304             rpc.rep_status += ','
305             rpc.rep_status += str(exp)
306         except Exception as exp:
307             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
308             rpc.rep_status += ','
309             rpc.rep_status += str(exp)
310
311     def delete_snapshot(self, rpc):
312         """
313             Request: DELETE http://<cm-vip:port>/cm/v1.0/snapshots/<snapshot name>
314             Response: http response with proper status
315         """
316
317         logging.debug('delete_snapshot called')
318         try:
319             snapshot_name = rpc.req_params['snapshot']
320             self.processor.delete_snapshot(snapshot_name)
321             rpc.rep_status = CMHTTPErrors.get_ok_status()
322         except cmerror.CMError as exp:
323             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
324             rpc.rep_status += ','
325             rpc.rep_status += str(exp)
326         except KeyError as exp:
327             rpc.rep_status = CMHTTPErrors.get_request_not_ok_status()
328         except Exception as exp:
329             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
330             rpc.rep_status += ','
331             rpc.rep_status += str(exp)
332
333     def list_snapshots(self, rpc):
334         """
335             Request: GET http://<cm-vip:port>/cm/v1.0/snapshots
336             Response: {
337                 "snapshots": [
338                     "<name of the snapshot>",
339                     ....
340                 ]
341             }
342         """
343
344         logging.debug('list_snapshots called')
345         try:
346             snapshots = self.processor.list_snapshots()
347             if not bool(snapshots):
348                 rpc.rep_status = CMHTTPErrors.get_resource_not_found_status()
349             else:
350                 reply = {}
351                 reply['snapshots'] = snapshots
352                 rpc.rep_status = CMHTTPErrors.get_ok_status()
353                 rpc.rep_body = json.dumps(reply)
354         except cmerror.CMError as exp:
355             rpc.rep_status = CMHTTPErrors.get_resource_not_found_status()
356             rpc.rep_status += ','
357             rpc.rep_status += str(exp)
358         except Exception as exp:  # pylint: disable=broad-except
359             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
360             rpc.rep_status += ','
361             rpc.rep_status += str(exp)
362
363     def activate(self, rpc):
364         """
365             Request: POST http://<cm-vip:port>/cm/v1.0/activator/<node-name>
366             Response: http response with proper status
367             {
368                 "change-uuid": "<uuid>"
369             }
370         """
371
372         logging.debug('activate called')
373         try:
374             node_name = rpc.req_params.get('node', None)
375             uuid_value = self.processor.activate(node_name)
376             rpc.rep_status = CMHTTPErrors.get_ok_status()
377             reply = {}
378             reply['change-uuid'] = uuid_value
379             rpc.rep_body = json.dumps(reply)
380         except cmerror.CMError as exp:
381             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
382             rpc.rep_status += ','
383             rpc.rep_status += str(exp)
384         except Exception as exp:  # pylint: disable=broad-except
385             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
386             rpc.rep_status += ','
387             rpc.rep_status += str(exp)
388
389     def activate_node(self, rpc):
390         """
391             Request: GET http://<cm-vip:port>/cm/v1.0/activator/agent/<node name>
392             Response: {
393                 "name": "<name of the node>",
394                 "reboot": "<boolean value indicating whether a reboot is needed>",
395             }
396         """
397
398         logging.debug('activate_node called')
399         try:
400             node_name = rpc.req_params['node']
401             reboot_needed = self.processor.activate_node(node_name)
402             reply = {}
403             reply['name'] = node_name
404             reply['reboot'] = reboot_needed
405             rpc.rep_status = CMHTTPErrors.get_ok_status()
406             rpc.rep_body = json.dumps(reply)
407         except cmerror.CMError as exp:
408             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
409             rpc.rep_status += ','
410             rpc.rep_status += str(exp)
411         except Exception as exp:  # pylint: disable=broad-except
412             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
413             rpc.rep_status += ','
414             rpc.rep_status += str(exp)
415
416     def set_automatic_activation_state(self, rpc, state):
417         """
418             Request: POST http://<cm-vip:port>/cm/v1.0/activator/disable
419             or       POST http://<cm-vip:port>/cm/v1.0/activator/enable
420             Response: http response with proper status
421         """
422
423         logging.debug('set_automatic_activation_state called')
424         try:
425             self.processor.set_automatic_activation_state(state)
426             rpc.rep_status = CMHTTPErrors.get_ok_status()
427         except cmerror.CMError as exp:
428             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
429             rpc.rep_status += ','
430             rpc.rep_status += str(exp)
431         except Exception as exp:  # pylint: disable=broad-except
432             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
433             rpc.rep_status += ','
434             rpc.rep_status += str(exp)
435
436     def reboot_node(self, rpc):
437         """
438             Request: GET http://<cm-vip:port>/cm/v1.0/reboot?node-name=<node name>
439             Response: {
440                 "node-name": "<name of the node>",
441             }
442         """
443
444         logging.debug('reboot_node called')
445         try:
446             if not rpc.req_filter:
447                 rpc.rep_status = CMHTTPErrors.get_request_not_ok_status()
448             else:
449                 node_name = rpc.req_filter.get('node-name', None)
450                 if isinstance(node_name, list):
451                     node_name = node_name[0]
452                 self.processor.reboot_request(node_name)
453                 reply = {}
454                 reply['node-name'] = node_name
455                 rpc.rep_status = CMHTTPErrors.get_ok_status()
456                 rpc.rep_body = json.dumps(reply)
457         except cmerror.CMError as exp:
458             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
459             rpc.rep_status += ','
460             rpc.rep_status += str(exp)
461         except Exception as exp:  # pylint: disable=broad-except
462             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
463             rpc.rep_status += ','
464             rpc.rep_status += str(exp)
465
466     def get_changes_states(self, rpc):
467         """
468             Request: GET http://<cm-vip:port>/cm/v1.0/changes?changd-uuid-filter=<filter>
469             Response: {
470                 "<change-uuid>"" : {
471                                     "state": "<state>",
472                                     "failed-plugins": { "plugin-name":"error",  ... }
473                 ...
474             }
475         """
476
477         logging.debug('get_changes_states called')
478         try:
479             reply = {}
480             changemonitor = self.processor.changemonitor
481             change_uuid_value = None
482             change_uuid_list = rpc.req_filter.get('change-uuid-filter', None)
483             if change_uuid_list:
484                 change_uuid_value = change_uuid_list[0]
485                 state = changemonitor.get_change_state(change_uuid_value)
486                 reply[change_uuid_value] = {}
487                 reply[change_uuid_value]["state"] = state.state
488                 reply[change_uuid_value]["failed-plugins"] = state.failed_plugins
489             else:
490                 changes = changemonitor.get_all_changes_states()
491                 for change_uuid, state in changes.iteritems():
492                     reply[change_uuid] = {}
493                     reply[change_uuid]["state"] = state.state
494                     reply[change_uuid]["failed-plugins"] = state.failed_plugins
495
496             rpc.rep_status = CMHTTPErrors.get_ok_status()
497             rpc.rep_body = json.dumps(reply)
498         except cmerror.CMError as exp:
499             rpc.rep_status = CMHTTPErrors.get_resource_not_found_status()
500             rpc.rep_status += ','
501             rpc.rep_status += str(exp)
502         except KeyError:
503             rpc.rep_status = CMHTTPErrors.get_resource_not_found_status()
504         except Exception as exp:  # pylint: disable=broad-except
505             rpc.rep_status = CMHTTPErrors.get_internal_error_status()
506             rpc.rep_status += ','
507             rpc.rep_status += str(exp)