Initial commit
[ta/config-manager.git] / cmframework / src / cmframework / server / cmrestapiv1.py
diff --git a/cmframework/src/cmframework/server/cmrestapiv1.py b/cmframework/src/cmframework/server/cmrestapiv1.py
new file mode 100644 (file)
index 0000000..ebc2913
--- /dev/null
@@ -0,0 +1,507 @@
+# Copyright 2019 Nokia
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import logging
+import json
+
+from cmframework.apis import cmerror
+from cmframework.server import cmrestapi
+from cmframework.server.cmhttperrors import CMHTTPErrors
+
+
+class CMRestAPIV1(cmrestapi.CMRestAPI):
+    def __init__(self, processor):
+        logging.debug('CMRestAPIV1 constructor called')
+        cmrestapi.CMRestAPI.__init__(self, 'v1.0', 'current', '1.0', processor)
+
+    def get_property(self, rpc):
+        """
+            Request: GET http://<cm-vip:port>/cm/v1.0/properties/
+                             <property-name>?snapshot=<snapshot name>
+            Response: {
+                "name": "<name of the property>",
+                "value": "<value of the property>",
+            }
+        """
+
+        logging.debug('get_property called')
+        try:
+            snapshot_name = rpc.req_filter.get('snapshot', None)
+            if isinstance(snapshot_name, list):
+                snapshot_name = snapshot_name[0]
+            prop_name = rpc.req_params['property']
+            value = self.processor.get_property(prop_name, snapshot_name)
+            reply = {}
+            reply['name'] = prop_name
+            reply['value'] = value
+            rpc.rep_status = CMHTTPErrors.get_ok_status()
+            rpc.rep_body = json.dumps(reply)
+        except cmerror.CMError as exp:
+            rpc.rep_status = CMHTTPErrors.get_resource_not_found_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+        except KeyError:
+            rpc.rep_status = CMHTTPErrors.get_resource_not_found_status()
+        except Exception as exp:  # pylint: disable=broad-except
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+
+    def get_properties(self, rpc):
+        """
+            Request: GET http://<cm-vip:port>/cm/v1.0/properties?
+                             prop-name-filter=<filter>&snapshot=<snapshot name>
+            Response: {
+                "properties": [
+                    {
+                        "name": "<name of the property>",
+                        "value": "<value of the property>"
+                    },
+                    {
+                        "name": "<name of the property>",
+                        "value": "<value of the property>"
+                    }
+                    ....
+                ]
+            }
+        """
+
+        logging.debug('get_properties called')
+        try:
+            prop_name_filter = rpc.req_filter.get('prop-name-filter', '')
+            if isinstance(prop_name_filter, list):
+                prop_name_filter = prop_name_filter[0]
+            snapshot_name = rpc.req_filter.get('snapshot', None)
+            if isinstance(snapshot_name, list):
+                snapshot_name = snapshot_name[0]
+            result = self.processor.get_properties(prop_name_filter, snapshot_name)
+            if not bool(result):
+                rpc.rep_status = CMHTTPErrors.get_resource_not_found_status()
+            else:
+                reply = {}
+                items = []
+                for key, value in result.iteritems():
+                    tmp = {}
+                    tmp['name'] = key
+                    tmp['value'] = value
+                    items.append(tmp)
+                reply['properties'] = items
+                rpc.rep_status = CMHTTPErrors.get_ok_status()
+                rpc.rep_body = json.dumps(reply)
+        except cmerror.CMError as exp:
+            rpc.rep_status = CMHTTPErrors.get_resource_not_found_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+        except Exception as exp:  # pylint: disable=broad-except
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+
+    def set_property(self, rpc):
+        """
+            Request: POST http://<cm-vip:port>/cm/v1.0/properties/<property-name>
+                {
+                    "value": "<value of the property>"
+                }
+            Response: http status set correctly
+               {
+                    "change-uuid": "<uuid>"
+               }
+        """
+
+        logging.debug('set_property called')
+        try:
+            if not rpc.req_body:
+                rpc.rep_status = CMHTTPErrors.get_request_not_ok_status()
+            else:
+                request = json.loads(rpc.req_body)
+                name = rpc.req_params['property']
+                value = request['value']
+                uuid_value = self.processor.set_property(name, value)
+                rpc.rep_status = CMHTTPErrors.get_ok_status()
+                reply = {}
+                reply['change-uuid'] = uuid_value
+                rpc.rep_body = json.dumps(reply)
+        except cmerror.CMError as exp:
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+        except KeyError:
+            rpc.rep_status = CMHTTPErrors.get_request_not_ok_status()
+        except Exception as exp:  # pylint: disable=broad-except
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+
+    def set_properties(self, rpc):
+        """
+            Request: POST http://<cm-vip:port>/cm/v1.0/properties
+                {
+                    "overwrite": True|False,
+                    "properties": [
+                        {
+                            "name": "<name of the property>",
+                            "value": "<value of the property>"
+                        },
+                        {
+                            "name": "<name of the property>",
+                            "value": "<value of the property>"
+                        },
+                        ....
+                    ]
+                }
+            Response:
+                {
+                     "change-uuid": "<uuid>"
+                }
+        """
+
+        logging.debug('set_properties called')
+        try:
+            if not rpc.req_body:
+                rpc.rep_status = CMHTTPErrors.get_request_not_ok_status()
+            else:
+                request = json.loads(rpc.req_body)
+                overwrite = False
+                if 'overwrite' in request:
+                    overwrite = request['overwrite']
+                items = request['properties']
+                data = {}
+                for entry in items:
+                    name = entry['name']
+                    value = entry['value']
+                    data[name] = value
+                uuid_value = self.processor.set_properties(data, overwrite)
+                rpc.rep_status = CMHTTPErrors.get_ok_status()
+                reply = {}
+                reply['change-uuid'] = uuid_value
+                rpc.rep_body = json.dumps(reply)
+        except cmerror.CMError as exp:
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+        except KeyError:
+            rpc.rep_status = CMHTTPErrors.get_request_not_ok_status()
+        except Exception as exp:  # pylint: disable=broad-except
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+
+    def delete_property(self, rpc):
+        """
+            Request: DELETE http://<cm-vip:port>/cm/v1.0/properties/<property-name>
+            Response: http response with proper status
+                {
+                    "change-uuid": "<uuid>"
+                }
+        """
+
+        logging.debug('delete_property called')
+        try:
+            prop = rpc.req_params['property']
+            uuid_value = self.processor.delete_property(prop)
+            rpc.rep_status = CMHTTPErrors.get_ok_status()
+            reply = {}
+            reply['change-uuid'] = uuid_value
+            rpc.rep_body = json.dumps(reply)
+        except cmerror.CMError as exp:
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+        except KeyError:
+            rpc.rep_status = CMHTTPErrors.get_request_not_ok_status()
+        except Exception as exp:  # pylint: disable=broad-except
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+
+    def delete_properties(self, rpc):
+        """
+            Request: DELETE http://<cm-vip:port>/cm/v1.0/properties?prop-name-filter=<filter>
+                {
+                    'properties': [ <prop-name>,
+                                    <prop-name>,
+                                    ....
+                                  ]
+                }
+            Response: http response with proper status
+               {
+                    "change-uuid": "<uuid>"
+               }
+        """
+
+        logging.debug('delete_properties called')
+        try:
+            if not rpc.req_filter and not rpc.req_body:
+                rpc.rep_status = CMHTTPErrors.get_request_not_ok_status()
+            else:
+                if rpc.req_filter:
+                    arg = rpc.req_filter.get('prop-name-filter', '')
+                    if isinstance(arg, list):
+                        arg = arg[0]
+                else:
+                    body = json.loads(rpc.req_body)
+                    arg = body['properties']
+                uuid_value = self.processor.delete_properties(arg)
+                rpc.rep_status = CMHTTPErrors.get_ok_status()
+                reply = {}
+                reply['change-uuid'] = uuid_value
+                rpc.rep_body = json.dumps(reply)
+        except cmerror.CMError as exp:
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+        except KeyError:
+            rpc.rep_status = CMHTTPErrors.get_request_not_ok_status()
+        except Exception as exp:  # pylint: disable=broad-except
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+
+    def create_snapshot(self, rpc):
+        """
+            Request: GET http://<cm-vip:port>/cm/v1.0/snapshots/<snapshot name>
+            Response: http response with proper status
+        """
+
+        logging.debug('create snapshot called')
+        try:
+            snapshot_name = rpc.req_params['snapshot']
+            self.processor.create_snapshot(snapshot_name)
+            rpc.rep_status = CMHTTPErrors.get_ok_status()
+        except cmerror.CMError as exp:
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+        except Exception as exp:  # pylint: disable=broad-except
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+
+    def restore_snapshot(self, rpc):
+        """
+            Request: POST http://<cm-vip:port>/cm/v1.0/snapshots/<snapshot name>
+            Response: http response with proper status
+        """
+
+        logging.debug('restore_snapshot called')
+        try:
+            snapshot_name = rpc.req_params['snapshot']
+            self.processor.restore_snapshot(snapshot_name)
+            rpc.rep_status = CMHTTPErrors.get_ok_status()
+        except cmerror.CMError as exp:
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+        except Exception as exp:
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+
+    def delete_snapshot(self, rpc):
+        """
+            Request: DELETE http://<cm-vip:port>/cm/v1.0/snapshots/<snapshot name>
+            Response: http response with proper status
+        """
+
+        logging.debug('delete_snapshot called')
+        try:
+            snapshot_name = rpc.req_params['snapshot']
+            self.processor.delete_snapshot(snapshot_name)
+            rpc.rep_status = CMHTTPErrors.get_ok_status()
+        except cmerror.CMError as exp:
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+        except KeyError as exp:
+            rpc.rep_status = CMHTTPErrors.get_request_not_ok_status()
+        except Exception as exp:
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+
+    def list_snapshots(self, rpc):
+        """
+            Request: GET http://<cm-vip:port>/cm/v1.0/snapshots
+            Response: {
+                "snapshots": [
+                    "<name of the snapshot>",
+                    ....
+                ]
+            }
+        """
+
+        logging.debug('list_snapshots called')
+        try:
+            snapshots = self.processor.list_snapshots()
+            if not bool(snapshots):
+                rpc.rep_status = CMHTTPErrors.get_resource_not_found_status()
+            else:
+                reply = {}
+                reply['snapshots'] = snapshots
+                rpc.rep_status = CMHTTPErrors.get_ok_status()
+                rpc.rep_body = json.dumps(reply)
+        except cmerror.CMError as exp:
+            rpc.rep_status = CMHTTPErrors.get_resource_not_found_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+        except Exception as exp:  # pylint: disable=broad-except
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+
+    def activate(self, rpc):
+        """
+            Request: POST http://<cm-vip:port>/cm/v1.0/activator/<node-name>
+            Response: http response with proper status
+            {
+                "change-uuid": "<uuid>"
+            }
+        """
+
+        logging.debug('activate called')
+        try:
+            node_name = rpc.req_params.get('node', None)
+            uuid_value = self.processor.activate(node_name)
+            rpc.rep_status = CMHTTPErrors.get_ok_status()
+            reply = {}
+            reply['change-uuid'] = uuid_value
+            rpc.rep_body = json.dumps(reply)
+        except cmerror.CMError as exp:
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+        except Exception as exp:  # pylint: disable=broad-except
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+
+    def activate_node(self, rpc):
+        """
+            Request: GET http://<cm-vip:port>/cm/v1.0/activator/agent/<node name>
+            Response: {
+                "name": "<name of the node>",
+                "reboot": "<boolean value indicating whether a reboot is needed>",
+            }
+        """
+
+        logging.debug('activate_node called')
+        try:
+            node_name = rpc.req_params['node']
+            reboot_needed = self.processor.activate_node(node_name)
+            reply = {}
+            reply['name'] = node_name
+            reply['reboot'] = reboot_needed
+            rpc.rep_status = CMHTTPErrors.get_ok_status()
+            rpc.rep_body = json.dumps(reply)
+        except cmerror.CMError as exp:
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+        except Exception as exp:  # pylint: disable=broad-except
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+
+    def set_automatic_activation_state(self, rpc, state):
+        """
+            Request: POST http://<cm-vip:port>/cm/v1.0/activator/disable
+            or       POST http://<cm-vip:port>/cm/v1.0/activator/enable
+            Response: http response with proper status
+        """
+
+        logging.debug('set_automatic_activation_state called')
+        try:
+            self.processor.set_automatic_activation_state(state)
+            rpc.rep_status = CMHTTPErrors.get_ok_status()
+        except cmerror.CMError as exp:
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+        except Exception as exp:  # pylint: disable=broad-except
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+
+    def reboot_node(self, rpc):
+        """
+            Request: GET http://<cm-vip:port>/cm/v1.0/reboot?node-name=<node name>
+            Response: {
+                "node-name": "<name of the node>",
+            }
+        """
+
+        logging.debug('reboot_node called')
+        try:
+            if not rpc.req_filter:
+                rpc.rep_status = CMHTTPErrors.get_request_not_ok_status()
+            else:
+                node_name = rpc.req_filter.get('node-name', None)
+                if isinstance(node_name, list):
+                    node_name = node_name[0]
+                self.processor.reboot_request(node_name)
+                reply = {}
+                reply['node-name'] = node_name
+                rpc.rep_status = CMHTTPErrors.get_ok_status()
+                rpc.rep_body = json.dumps(reply)
+        except cmerror.CMError as exp:
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+        except Exception as exp:  # pylint: disable=broad-except
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+
+    def get_changes_states(self, rpc):
+        """
+            Request: GET http://<cm-vip:port>/cm/v1.0/changes?changd-uuid-filter=<filter>
+            Response: {
+                "<change-uuid>"" : {
+                                    "state": "<state>",
+                                    "failed-plugins": { "plugin-name":"error",  ... }
+                ...
+            }
+        """
+
+        logging.debug('get_changes_states called')
+        try:
+            reply = {}
+            changemonitor = self.processor.changemonitor
+            change_uuid_value = None
+            change_uuid_list = rpc.req_filter.get('change-uuid-filter', None)
+            if change_uuid_list:
+                change_uuid_value = change_uuid_list[0]
+                state = changemonitor.get_change_state(change_uuid_value)
+                reply[change_uuid_value] = {}
+                reply[change_uuid_value]["state"] = state.state
+                reply[change_uuid_value]["failed-plugins"] = state.failed_plugins
+            else:
+                changes = changemonitor.get_all_changes_states()
+                for change_uuid, state in changes.iteritems():
+                    reply[change_uuid] = {}
+                    reply[change_uuid]["state"] = state.state
+                    reply[change_uuid]["failed-plugins"] = state.failed_plugins
+
+            rpc.rep_status = CMHTTPErrors.get_ok_status()
+            rpc.rep_body = json.dumps(reply)
+        except cmerror.CMError as exp:
+            rpc.rep_status = CMHTTPErrors.get_resource_not_found_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)
+        except KeyError:
+            rpc.rep_status = CMHTTPErrors.get_resource_not_found_status()
+        except Exception as exp:  # pylint: disable=broad-except
+            rpc.rep_status = CMHTTPErrors.get_internal_error_status()
+            rpc.rep_status += ','
+            rpc.rep_status += str(exp)