Пример #1
0
class TestRequestParser(unittest.TestCase):
    def dummyFunc0(self):
        self.call_func0 += 1
        return Response(101, None)

    def dummyFunc1(self, body, *mached):
        self.call_func1 += 1
        self.func1_body = body
        return Response(102, None)

    def setUp(self):
        self.call_func0 = 0
        self.call_func1 = 0
        self.func1_body = None
        self.target = RequestParser()

    def tearDown(self):
        pass

    def test_constructor(self):
        self.assertEqual(self.target._RequestParser__rules, [])

    def test_add_rule(self):
        self.target.add_rule([{
            "pattern": "(param1)",
            "method": "GET",
            "func": self.dummyFunc0,
            "params": 0
        }])
        self.target.add_rule([{
            "pattern": "(param2)",
            "method": "PUT",
            "func": self.dummyFunc1,
            "params": 1
        }])
        self.assertEqual(self.target._RequestParser__rules, [{
            "pattern": "(param1)",
            "method": "GET",
            "func": self.dummyFunc0,
            "params": 0
        }, {
            "pattern": "(param2)",
            "method": "PUT",
            "func": self.dummyFunc1,
            "params": 1
        }])

    def test_action(self):
        self.target.add_rule([{
            "pattern": "(param1)",
            "method": "GET",
            "func": self.dummyFunc0,
            "params": 0
        }, {
            "pattern": "(param2)",
            "method": "PUT",
            "func": self.dummyFunc1,
            "params": 1
        }])
        request = Request("id1", "GET", "path/to/param1", None)
        response = self.target.action(request)
        self.assertEqual(self.call_func0, 1)
        self.assertEqual(response.status_code, 101)

    def test_action_with_param_attribute_params_is_1(self):
        self.target.add_rule([{
            "pattern": "(param1)",
            "method": "GET",
            "func": self.dummyFunc0,
            "params": 0
        }, {
            "pattern": "(param2)",
            "method": "PUT",
            "func": self.dummyFunc1,
            "params": 1
        }])
        request = Request("id1", "PUT", "path/to/param2", "body")
        response = self.target.action(request)
        self.assertEqual(self.call_func1, 1)
        self.assertEqual(self.func1_body, "body")
        self.assertEqual(response.status_code, 102)

    def test_action_with_param_attribute_params_is_1_and_null_body_request(
            self):
        self.target.add_rule([{
            "pattern": "(param1)",
            "method": "GET",
            "func": self.dummyFunc0,
            "params": 0
        }, {
            "pattern": "(param2)",
            "method": "PUT",
            "func": self.dummyFunc1,
            "params": 1
        }])
        request = Request("id1", "PUT", "path/to/param2", None)
        response = self.target.action(request)
        self.assertEqual(self.call_func1, 1)
        self.assertEqual(self.func1_body, "param2")
        self.assertEqual(response.status_code, 102)

    def test_action_with_param_attribute_params_is_2(self):
        self.target.add_rule([{
            "pattern": "(param1)",
            "method": "GET",
            "func": self.dummyFunc0,
            "params": 0
        }, {
            "pattern": "(param2)",
            "method": "PUT",
            "func": self.dummyFunc1,
            "params": 2
        }])
        request = Request("id1", "PUT", "path/to/param2", "body")
        response = self.target.action(request)
        self.assertEqual(self.call_func1, 1)
        self.assertEqual(self.func1_body, "body")
        self.assertEqual(response.status_code, 102)

    def test_action_with_param_attribute_params_is_2_and_null_body_request(
            self):
        self.target.add_rule([{
            "pattern": "(param1)",
            "method": "GET",
            "func": self.dummyFunc0,
            "params": 0
        }, {
            "pattern": "(param2)",
            "method": "PUT",
            "func": self.dummyFunc1,
            "params": 2
        }])
        request = Request("id1", "PUT", "path/to/param2", None)
        response = self.target.action(request)
        self.assertEqual(self.call_func1, 1)
        self.assertEqual(self.func1_body, "param2")
        self.assertEqual(response.status_code, 102)

    def test_action_with_pattern_mached_but_method_not_matched(self):
        self.target.add_rule([{
            "pattern": "(param1)",
            "method": "GET",
            "func": self.dummyFunc0,
            "params": 0
        }, {
            "pattern": "(param2)",
            "method": "PUT",
            "func": self.dummyFunc1,
            "params": 1
        }])
        request = Request("id1", "GET", "path/to/param2", "body")
        response = self.target.action(request)
        self.assertEqual(self.call_func0, 0)
        self.assertEqual(self.call_func1, 0)
        self.assertEqual(self.func1_body, None)
        self.assertEqual(response.status_code, 405)

    def test_action_with_pattern_not_matched(self):
        self.target.add_rule([{
            "pattern": "(param1)",
            "method": "GET",
            "func": self.dummyFunc0,
            "params": 0
        }, {
            "pattern": "(param2)",
            "method": "PUT",
            "func": self.dummyFunc1,
            "params": 1
        }])
        request = Request("id1", "GET", "path/to/param3", "body")
        response = self.target.action(request)
        self.assertEqual(self.call_func0, 0)
        self.assertEqual(self.call_func1, 0)
        self.assertEqual(self.func1_body, None)
        self.assertEqual(response.status_code, 404)
Пример #2
0
class RemoteObject(object):
    DESCRIPTION = ""
    CONNECTION_TYPES = ""

    def __init__(self, arg1, arg2, arg3=None):
        if arg3 is None:
            object_id = arg1
            dispatcher = arg2
        else:
            object_id = arg1
            baseUrl = arg2
            dispatcher = arg3
        self._object_property = ObjectProperty(self.__class__.__name__,
                                               object_id)
        self._object_property.set_state(ObjectProperty.State.INITIALIZING)
        self.__set_description()
        self.__set_connection_types()
        self._object_settings = {}

        self.dispatcher = dispatcher
        if self.dispatcher is None:
            return
        self.dispatcher.add_local_object(self)
        self._event_subscription = EventSubscription(object_id)
        self.__parser = RequestParser()
        self.__add_rules()

    def on_initialize(self, obj_prop):
        return True

    def on_finalize(self):
        logging.debug("on_finalize ObjectID:" + self.object_id)
        self.dispatcher.remove_local_object(self)

    @property
    def object_id(self):
        return self._object_property.object_id

    @property
    def object_property(self):
        return self._object_property

    @property
    def object_settings(self):
        return self._object_settings

    @property
    def state(self):
        return self._object_property.state

    def set_state(self, state):
        prop = self.object_property
        prop.set_state(state)
        return self._do_put_property(prop.packed_object())

    def __set_description(self):
        self._object_property.set_property(ObjectProperty.DESCRIPTION,
                                           self.DESCRIPTION)

    def __set_connection_types(self):
        self._object_property.set_property(ObjectProperty.CONNECTION_TYPES,
                                           self.CONNECTION_TYPES)

    def _request_sync(self, object_id, method, path, body=None):
        return self.dispatcher.request_sync(Request(object_id,
                                                    method,
                                                    path,
                                                    body))

    def _request(self, object_id, method, path, body=None):
        resp = Response(Response.StatusCode.INTERNAL_SERVER_ERROR, None)
        try:
            resp = self._request_sync(object_id, method, path, body)
        except:
            logging.error("Exception: Request to " + object_id
                          + " Method:" + method
                          + " Path:" + path)
            logging.error(traceback.format_exc())

        return resp

    def _publish_event_async(self, event_type, body):
        return self.dispatcher.publish_event_async(Event(self.object_id,
                                                         event_type,
                                                         body))

    def _apply_event_subscription(self):
        return self.dispatcher.subscribe_event(self._event_subscription)

    def __add_rules(self):
        rules = []
        rules.append({RequestParser.PATTERN: r"^property/?$",
                      RequestParser.METHOD: Request.Method.GET,
                      RequestParser.FUNC: self._do_get_property,
                      RequestParser.PARAMS: 0})
        rules.append({RequestParser.PATTERN: r"^property/?$",
                      RequestParser.METHOD: Request.Method.PUT,
                      RequestParser.FUNC: self._do_put_property,
                      RequestParser.PARAMS: 1})
        rules.append({RequestParser.PATTERN: r"^settings/?$",
                      RequestParser.METHOD: Request.Method.GET,
                      RequestParser.FUNC: self._do_get_settings,
                      RequestParser.PARAMS: 0})
        rules.append({RequestParser.PATTERN: r"^settings/?$",
                      RequestParser.METHOD: Request.Method.PUT,
                      RequestParser.FUNC: self._do_put_settings,
                      RequestParser.PARAMS: 1})
        self.__parser.add_rule(rules)

    def dispatch_request(self, request):
        try:
            resp = self.__parser.action(request)
            if resp.status_code == Response.StatusCode.NOT_FOUND:
                resp = self._on_request(request)
        except:
            logging.error("Exception: Receive Request"
                          + " Method:" + request.method
                          + " Path:" + request.path)
            logging.error(traceback.format_exc())
            resp = Response(Response.StatusCode.INTERNAL_SERVER_ERROR, None)

        return resp

    def dispatch_event(self, event):
        self._do_post_event(event)

    def _do_get_property(self):
        logging.debug("Receive GET Property ObjectID:" + self.object_id)
        return Response(Response.StatusCode.OK, self._object_property)

    def _do_put_property(self, body):
        logging.debug("Receive PUT Property ObjectID:" + self.object_id)
        # check State Change to Finalizing
        for k, v in body.items():
            if k == ObjectProperty.OBJECT_STATE:
                oldValue = self._object_property.get_property(k)
                self.on_state_changed(oldValue, v)

        # update Property
        if not(self._object_property.equals(body)):
            self._object_property.put_property(body)

        return Response(Response.StatusCode.OK, self._object_property)

    def _do_get_settings(self):
        logging.debug("Receive GET Settings ObjectID:" + self.object_id)
        return Response(Response.StatusCode.OK, self._object_settings)

    def _do_put_settings(self, body):
        logging.debug("Receive PUT Settings ObjectID:" + self.object_id)
        if body != self._object_settings:
            old = copy.deepcopy(self._object_settings)
            # delete
            for k in old.keys():
                if k not in body:
                    del self._object_settings[k]

            # add or update
            for k, v in body.items():
                self._object_settings[k] = v

            self.on_settings_changed(ObjectSettingChanged.Action.UPDATE,
                                     old,
                                     self._object_settings)

        return Response(Response.StatusCode.OK, self._object_settings)

    def _do_post_event(self, event):
        self.on_event(event)

    def on_state_changed(self, old_state, new_state):
        if old_state != ObjectProperty.State.FINALIZING:
            if new_state == ObjectProperty.State.FINALIZING:
                self.on_finalize()

    def on_settings_changed(self, action, prev, curr):
        event_body = {ObjectSettingChanged.ACTION: action,
                      ObjectSettingChanged.PREV: prev,
                      ObjectSettingChanged.CURR: curr}
        self._publish_event_async(ObjectSettingChanged.TYPE,
                                  event_body)

    def _on_request(self, request):
        return Response(Response.StatusCode.BAD_REQUEST, None)

    def on_event(self, event):

        # for example: method_name = "_do_event_topologychanged"
        method_name = "_do_event_" + event.event_type.lower()
        if hasattr(self, method_name):
            method = getattr(self, method_name)
            if callable(method):
                method(event)
                return
        return
class RemoteObjectManager(RemoteObject):

    # FIXME
    DESCRIPTION = "python's RemoteObjectManager"
    REMOTE_OBJECT_TYPES = "remote_object_types"

    def __init__(self, object_id, dispatcher):
        RemoteObject.__init__(self, object_id, dispatcher)
        self.remote_object_classes = {}
        self.remote_objects = {}
        self.dispatcher = dispatcher
        self._parser = RequestParser()
        self._add_rules()
        self._object_property.set_property(
            RemoteObjectManager.REMOTE_OBJECT_TYPES, "")

    def register_remote_objects(self, remote_objects):
        for remote_object in remote_objects:
            remote_object_name = remote_object.__name__
            logging.debug("Register RemoteObject Type:%s", remote_object_name)

            self.remote_object_classes[remote_object_name] = remote_object

        types = ",".join(self.remote_object_classes.keys())
        self._object_property.set_property(
            RemoteObjectManager.REMOTE_OBJECT_TYPES, types)

    def _add_rules(self):
        rules = []
        rules.append({
            RequestParser.PATTERN: r"^remote_object_types/?$",
            RequestParser.METHOD: Request.Method.GET,
            RequestParser.FUNC: self._do_get_remote_object_types,
            RequestParser.PARAMS: 0
        })
        rules.append({
            RequestParser.PATTERN: r"^remote_objects/?$",
            RequestParser.METHOD: Request.Method.GET,
            RequestParser.FUNC: self._do_get_remote_objects,
            RequestParser.PARAMS: 0
        })
        rules.append({
            RequestParser.PATTERN: r"^remote_objects/" + "([a-zA-Z0-9_-]+)/?$",
            RequestParser.METHOD: Request.Method.PUT,
            RequestParser.FUNC: self._do_put_remote_object,
            RequestParser.PARAMS: 2
        })
        rules.append({
            RequestParser.PATTERN: r"^remote_objects/" + "([a-zA-Z0-9_-]+)/?$",
            RequestParser.METHOD: Request.Method.GET,
            RequestParser.FUNC: self._do_get_remote_object,
            RequestParser.PARAMS: 1
        })
        rules.append({
            RequestParser.PATTERN: r"^remote_objects/" + "([a-zA-Z0-9_-]+)/?$",
            RequestParser.METHOD: Request.Method.DELETE,
            RequestParser.FUNC: self._do_delete_remote_object,
            RequestParser.PARAMS: 1
        })
        self._parser.add_rule(rules)

    def _on_request(self, request):
        return self._parser.action(request)

    def _do_get_remote_object_types(self):
        return Response(Response.StatusCode.OK,
                        self.remote_object_classes.keys())

    def _do_get_remote_objects(self):
        body = {}
        for object_id in self.remote_objects:
            body[object_id] = \
                self.remote_objects[object_id].object_property.packed_object()
        return Response(Response.StatusCode.OK, body)

    def _do_get_remote_object(self, object_id):
        if object_id in self.remote_objects:
            return Response(Response.StatusCode.OK,
                            self.remote_objects[object_id].object_property)
        return Response(Response.StatusCode.NOT_FOUND, None)

    def _do_put_remote_object(self, obj_prop, object_id):
        remote_object_type = obj_prop[ObjectProperty.OBJECT_TYPE]

        if remote_object_type not in self.remote_object_classes:
            return Response(Response.StatusCode.BAD_REQUEST, None)
        elif object_id in self.remote_objects:
            return Response(Response.StatusCode.CONFLICT, None)

        remote_object_class = self.remote_object_classes[remote_object_type]
        self.remote_objects[object_id] = remote_object_class(
            object_id, self.dispatcher)

        if self.remote_objects[object_id].on_initialize(obj_prop):
            self.remote_objects[object_id].set_state(
                ObjectProperty.State.RUNNING)
        else:
            self.remote_objects[object_id].set_state(
                ObjectProperty.State.ERROR)

        logging.debug("Created RemoteObject Type:%s ID:%s", remote_object_type,
                      object_id)
        return Response(Response.StatusCode.CREATED,
                        self.remote_objects[object_id].object_property)

    def _do_delete_remote_object(self, object_id):
        if object_id in self.remote_objects:
            remote_object = self.remote_objects[object_id]
            prev = copy.deepcopy(
                remote_object._object_property).packed_object()
            remote_object.on_finalize()
            del self.remote_objects[object_id]
            logging.debug("Deleted RemoteObject ID:%s", object_id)

        return Response(Response.StatusCode.OK, None)
Пример #4
0
class ComponentManager(RemoteObject):

    # FIXME
    DESCRIPTION = "ComponentManager for python"

    def __init__(self, object_id, dispatcher):
        RemoteObject.__init__(self, object_id, dispatcher)
        self.component_classes = {}
        self.components = {}
        self.dispatcher = dispatcher
        self.__parser = RequestParser()
        self.__add_rules()
        self._object_property.set_state(ObjectProperty.State.RUNNING)

    def register_to_system_manager(self):
        logging.debug("object_property of ComponentManager %s is %s",
                      self.object_id,
                      self._object_property.packed_object())

        self.__register_component_managers()
        path = "component_managers/%s" % self.object_id
        resp = self._request(self.dispatcher.system_manager_id,
                             Request.Method.PUT,
                             path,
                             self._object_property)
        if resp.is_error(Request.Method.PUT):
            logging.error("Failed registration to SystemManager.")
            self._object_property.set_state(ObjectProperty.State.ERROR)
            return

        self.__register_event_manager()
        self.__subscribe_event()
        logging.info("Complete registration to SystemManager.")

    def __register_component_managers(self):
        resp = self._request(self.dispatcher.system_manager_id,
                             Request.Method.GET,
                             "component_managers",
                             None)
        if resp.is_error(Request.Method.GET):
            logging.error("Failed get component_managers from SystemManager.")
            self._object_property.set_state(ObjectProperty.State.ERROR)
            return

        for component_manager in resp.body:
            self.__register_other_component_manager(component_manager)

    def __register_other_component_manager(self, component_manager):
        object_id = component_manager[ObjectProperty.OBJECT_ID]
        if object_id == self.object_id:
            return

        logging.info("Register Other Component Manager ID:%s", object_id)
        self.dispatcher.add_remote_client(object_id)

    def __unregister_component_manager(self, object_id):
        self.dispatcher.remove_remote_client(object_id)

    def __register_event_manager(self):
        resp = self._request(self.dispatcher.system_manager_id,
                             Request.Method.GET,
                             "objects/%s" % self.dispatcher.event_manager_id,
                             None)
        if resp.is_error(Request.Method.GET):
            self._object_property.set_state(ObjectProperty.State.ERROR)
            return

        self.dispatcher.add_remote_client(self.dispatcher.event_manager_id)

    def __subscribe_event(self):
        self._event_subscription.add_filter(
            self.dispatcher.system_manager_id,
            ComponentManagerChanged.TYPE)
        self._apply_event_subscription()

    def register_component_type(self, component):
        component_name = component.__name__
        logging.info("Register Component Type:%s", component_name)

        self.component_classes[component_name] = component
        component_types = \
            self._object_property.get_property(ObjectProperty.COMPONENT_TYPES)
        if component_types:
            component_types += (",%s" % component_name)
        else:
            component_types = "%s" % component_name
        self._object_property.set_property(ObjectProperty.COMPONENT_TYPES,
                                           component_types)

    def __add_rules(self):
        rules = []
        rules.append({RequestParser.PATTERN: r"^component_types/?$",
                      RequestParser.METHOD: Request.Method.GET,
                      RequestParser.FUNC: self._do_get_component_types,
                      RequestParser.PARAMS: 0})
        rules.append({RequestParser.PATTERN: r"^components/?$",
                      RequestParser.METHOD: Request.Method.GET,
                      RequestParser.FUNC: self._do_get_components,
                      RequestParser.PARAMS: 0})
        rules.append({RequestParser.PATTERN: r"^components/"
                      + "([a-zA-Z0-9_-]+)/?$",
                      RequestParser.METHOD: Request.Method.PUT,
                      RequestParser.FUNC: self._do_put_component,
                      RequestParser.PARAMS: 2})
        rules.append({RequestParser.PATTERN: r"^components/"
                      + "([a-zA-Z0-9_-]+)/?$",
                      RequestParser.METHOD: Request.Method.GET,
                      RequestParser.FUNC: self._do_get_component,
                      RequestParser.PARAMS: 1})
        rules.append({RequestParser.PATTERN: r"^components/"
                      + "([a-zA-Z0-9_-]+)/?$",
                      RequestParser.METHOD: Request.Method.DELETE,
                      RequestParser.FUNC: self._do_delete_component,
                      RequestParser.PARAMS: 1})
        self.__parser.add_rule(rules)

    def _on_request(self, request):
        return self.__parser.action(request)

    def _do_get_component(self, object_id):
        if object_id in self.components:
            return Response(Response.StatusCode.OK,
                            self.components[object_id].object_property)
        return Response(Response.StatusCode.NOT_FOUND, None)

    def _do_put_component(self, obj_prop, object_id):
        component_type = obj_prop[ObjectProperty.OBJECT_TYPE]

        if component_type not in self.component_classes:
            return Response(Response.StatusCode.BAD_REQUEST, None)
        elif object_id in self.components:
            return Response(Response.StatusCode.CONFLICT, None)

        component_class = self.component_classes[component_type]
        self.components[object_id] = component_class(object_id,
                                                     self.dispatcher)
        if self.components[object_id].on_initialize(obj_prop):
            self.components[object_id].\
                _object_property.set_state(ObjectProperty.State.RUNNING)
        else:
            self.components[object_id].\
                _object_property.set_state(ObjectProperty.State.ERROR)
        curr = self.components[object_id].object_property.packed_object()
        self._do_component_changed(ComponentChanged.Action.ADD,
                                   None,
                                   curr)

        logging.info("Created Component Type:%s ID:%s",
                     component_type, object_id)
        return Response(Response.StatusCode.CREATED,
                        self.components[object_id].object_property)

    def _do_delete_component(self, object_id):
        if object_id in self.components:
            component = self.components[object_id]
            prev = copy.deepcopy(component._object_property).packed_object()
            component.on_finalize()
            del self.components[object_id]
            self._do_component_changed(ComponentChanged.Action.DELETE,
                                       prev,
                                       None)
            logging.info("Deleted Component ID:%s", object_id)

        return Response(Response.StatusCode.OK, None)

    def _do_get_components(self):
        body = {}
        for object_id in self.components:
            body[object_id] = \
                self.components[object_id].object_property.packed_object()
        return Response(Response.StatusCode.OK, body)

    def _do_get_component_types(self):
        comp_types = {}
        try:
            for type_name, clazz in self.component_classes.items():
                comp_id = "%s_%s" % (self.object_id, type_name)
                component = clazz(comp_id, None)
                obj_prop = component.object_property

                type = obj_prop.get_property(ObjectProperty.OBJECT_TYPE)
                super_type = obj_prop.get_property(ObjectProperty.OBJECT_SUPER_TYPE)

                connection_types = {}
                connection_types_str = obj_prop.get_property(
                    ObjectProperty.CONNECTION_TYPES)
                conn_type_list = connection_types_str.split(",")
                for type_elem in conn_type_list:
                    type_elem_list = type_elem.split(":")
                    if len(type_elem_list) == 2:
                        connection_types[type_elem_list[0]] = type_elem_list[1]

                description = obj_prop.get_property(ObjectProperty.DESCRIPTION)

                target = ComponentType(type, super_type,
                                       connection_types, description)
                comp_types[type_name] = target.packed_object()

        except Exception, e:
            return Response(Response.StatusCode.INTERNAL_SERVER_ERROR,
                            str(e))

        return Response(Response.StatusCode.OK, comp_types)
Пример #5
0
class RemoteObjectManager(RemoteObject):

    # FIXME
    DESCRIPTION = "python's RemoteObjectManager"
    REMOTE_OBJECT_TYPES = "remote_object_types"

    def __init__(self, object_id, dispatcher):
        RemoteObject.__init__(self, object_id, dispatcher)
        self.remote_object_classes = {}
        self.remote_objects = {}
        self.dispatcher = dispatcher
        self._parser = RequestParser()
        self._add_rules()
        self._object_property.set_property(RemoteObjectManager.REMOTE_OBJECT_TYPES, "")

    def register_remote_objects(self, remote_objects):
        for remote_object in remote_objects:
            remote_object_name = remote_object.__name__
            logging.debug("Register RemoteObject Type:%s", remote_object_name)

            self.remote_object_classes[remote_object_name] = remote_object

        types = ",".join(self.remote_object_classes.keys())
        self._object_property.set_property(RemoteObjectManager.REMOTE_OBJECT_TYPES, types)

    def _add_rules(self):
        rules = []
        rules.append(
            {
                RequestParser.PATTERN: r"^remote_object_types/?$",
                RequestParser.METHOD: Request.Method.GET,
                RequestParser.FUNC: self._do_get_remote_object_types,
                RequestParser.PARAMS: 0,
            }
        )
        rules.append(
            {
                RequestParser.PATTERN: r"^remote_objects/?$",
                RequestParser.METHOD: Request.Method.GET,
                RequestParser.FUNC: self._do_get_remote_objects,
                RequestParser.PARAMS: 0,
            }
        )
        rules.append(
            {
                RequestParser.PATTERN: r"^remote_objects/" + "([a-zA-Z0-9_-]+)/?$",
                RequestParser.METHOD: Request.Method.PUT,
                RequestParser.FUNC: self._do_put_remote_object,
                RequestParser.PARAMS: 2,
            }
        )
        rules.append(
            {
                RequestParser.PATTERN: r"^remote_objects/" + "([a-zA-Z0-9_-]+)/?$",
                RequestParser.METHOD: Request.Method.GET,
                RequestParser.FUNC: self._do_get_remote_object,
                RequestParser.PARAMS: 1,
            }
        )
        rules.append(
            {
                RequestParser.PATTERN: r"^remote_objects/" + "([a-zA-Z0-9_-]+)/?$",
                RequestParser.METHOD: Request.Method.DELETE,
                RequestParser.FUNC: self._do_delete_remote_object,
                RequestParser.PARAMS: 1,
            }
        )
        self._parser.add_rule(rules)

    def _on_request(self, request):
        return self._parser.action(request)

    def _do_get_remote_object_types(self):
        return Response(Response.StatusCode.OK, self.remote_object_classes.keys())

    def _do_get_remote_objects(self):
        body = {}
        for object_id in self.remote_objects:
            body[object_id] = self.remote_objects[object_id].object_property.packed_object()
        return Response(Response.StatusCode.OK, body)

    def _do_get_remote_object(self, object_id):
        if object_id in self.remote_objects:
            return Response(Response.StatusCode.OK, self.remote_objects[object_id].object_property)
        return Response(Response.StatusCode.NOT_FOUND, None)

    def _do_put_remote_object(self, obj_prop, object_id):
        remote_object_type = obj_prop[ObjectProperty.OBJECT_TYPE]

        if remote_object_type not in self.remote_object_classes:
            return Response(Response.StatusCode.BAD_REQUEST, None)
        elif object_id in self.remote_objects:
            return Response(Response.StatusCode.CONFLICT, None)

        remote_object_class = self.remote_object_classes[remote_object_type]
        self.remote_objects[object_id] = remote_object_class(object_id, self.dispatcher)

        if self.remote_objects[object_id].on_initialize(obj_prop):
            self.remote_objects[object_id].set_state(ObjectProperty.State.RUNNING)
        else:
            self.remote_objects[object_id].set_state(ObjectProperty.State.ERROR)

        logging.debug("Created RemoteObject Type:%s ID:%s", remote_object_type, object_id)
        return Response(Response.StatusCode.CREATED, self.remote_objects[object_id].object_property)

    def _do_delete_remote_object(self, object_id):
        if object_id in self.remote_objects:
            remote_object = self.remote_objects[object_id]
            prev = copy.deepcopy(remote_object._object_property).packed_object()
            remote_object.on_finalize()
            del self.remote_objects[object_id]
            logging.debug("Deleted RemoteObject ID:%s", object_id)

        return Response(Response.StatusCode.OK, None)
Пример #6
0
class RemoteObject(object):
    DESCRIPTION = ""
    CONNECTION_TYPES = ""

    def __init__(self, arg1, arg2, arg3=None):
        if arg3 is None:
            object_id = arg1
            dispatcher = arg2
        else:
            object_id = arg1
            baseUrl = arg2
            dispatcher = arg3
        self._object_property = ObjectProperty(self.__class__.__name__,
                                               object_id)
        self._object_property.set_state(ObjectProperty.State.INITIALIZING)
        self.__set_description()
        self.__set_connection_types()
        self._object_settings = {}

        self.dispatcher = dispatcher
        if self.dispatcher is None:
            return
        self.dispatcher.add_local_object(self)
        self._event_subscription = EventSubscription(object_id)
        self.__parser = RequestParser()
        self.__add_rules()

    def on_initialize(self, obj_prop):
        return True

    def on_finalize(self):
        logging.debug("on_finalize ObjectID:" + self.object_id)
        self.dispatcher.remove_local_object(self)

    @property
    def object_id(self):
        return self._object_property.object_id

    @property
    def object_property(self):
        return self._object_property

    @property
    def object_settings(self):
        return self._object_settings

    @property
    def state(self):
        return self._object_property.state

    def set_state(self, state):
        prop = self.object_property
        prop.set_state(state)
        return self._do_put_property(prop.packed_object())

    def __set_description(self):
        self._object_property.set_property(ObjectProperty.DESCRIPTION,
                                           self.DESCRIPTION)

    def __set_connection_types(self):
        self._object_property.set_property(ObjectProperty.CONNECTION_TYPES,
                                           self.CONNECTION_TYPES)

    def _request_sync(self, object_id, method, path, body=None):
        return self.dispatcher.request_sync(
            Request(object_id, method, path, body))

    def _request(self, object_id, method, path, body=None):
        resp = Response(Response.StatusCode.INTERNAL_SERVER_ERROR, None)
        try:
            resp = self._request_sync(object_id, method, path, body)
        except:
            logging.error("Exception: Request to " + object_id + " Method:" +
                          method + " Path:" + path)
            logging.error(traceback.format_exc())

        return resp

    def _publish_event_async(self, event_type, body):
        return self.dispatcher.publish_event_async(
            Event(self.object_id, event_type, body))

    def _apply_event_subscription(self):
        return self.dispatcher.subscribe_event(self._event_subscription)

    def __add_rules(self):
        rules = []
        rules.append({
            RequestParser.PATTERN: r"^property/?$",
            RequestParser.METHOD: Request.Method.GET,
            RequestParser.FUNC: self._do_get_property,
            RequestParser.PARAMS: 0
        })
        rules.append({
            RequestParser.PATTERN: r"^property/?$",
            RequestParser.METHOD: Request.Method.PUT,
            RequestParser.FUNC: self._do_put_property,
            RequestParser.PARAMS: 1
        })
        rules.append({
            RequestParser.PATTERN: r"^settings/?$",
            RequestParser.METHOD: Request.Method.GET,
            RequestParser.FUNC: self._do_get_settings,
            RequestParser.PARAMS: 0
        })
        rules.append({
            RequestParser.PATTERN: r"^settings/?$",
            RequestParser.METHOD: Request.Method.PUT,
            RequestParser.FUNC: self._do_put_settings,
            RequestParser.PARAMS: 1
        })
        self.__parser.add_rule(rules)

    def dispatch_request(self, request):
        try:
            resp = self.__parser.action(request)
            if resp.status_code == Response.StatusCode.NOT_FOUND:
                resp = self._on_request(request)
        except:
            logging.error("Exception: Receive Request" + " Method:" +
                          request.method + " Path:" + request.path)
            logging.error(traceback.format_exc())
            resp = Response(Response.StatusCode.INTERNAL_SERVER_ERROR, None)

        return resp

    def dispatch_event(self, event):
        self._do_post_event(event)

    def _do_get_property(self):
        logging.debug("Receive GET Property ObjectID:" + self.object_id)
        return Response(Response.StatusCode.OK, self._object_property)

    def _do_put_property(self, body):
        logging.debug("Receive PUT Property ObjectID:" + self.object_id)
        # check State Change to Finalizing
        for k, v in body.items():
            if k == ObjectProperty.OBJECT_STATE:
                oldValue = self._object_property.get_property(k)
                self.on_state_changed(oldValue, v)

        # update Property
        if not (self._object_property.equals(body)):
            self._object_property.put_property(body)

        return Response(Response.StatusCode.OK, self._object_property)

    def _do_get_settings(self):
        logging.debug("Receive GET Settings ObjectID:" + self.object_id)
        return Response(Response.StatusCode.OK, self._object_settings)

    def _do_put_settings(self, body):
        logging.debug("Receive PUT Settings ObjectID:" + self.object_id)
        if body != self._object_settings:
            old = copy.deepcopy(self._object_settings)
            # delete
            for k in old.keys():
                if k not in body:
                    del self._object_settings[k]

            # add or update
            for k, v in body.items():
                self._object_settings[k] = v

            self.on_settings_changed(ObjectSettingChanged.Action.UPDATE, old,
                                     self._object_settings)

        return Response(Response.StatusCode.OK, self._object_settings)

    def _do_post_event(self, event):
        self.on_event(event)

    def on_state_changed(self, old_state, new_state):
        if old_state != ObjectProperty.State.FINALIZING:
            if new_state == ObjectProperty.State.FINALIZING:
                self.on_finalize()

    def on_settings_changed(self, action, prev, curr):
        event_body = {
            ObjectSettingChanged.ACTION: action,
            ObjectSettingChanged.PREV: prev,
            ObjectSettingChanged.CURR: curr
        }
        self._publish_event_async(ObjectSettingChanged.TYPE, event_body)

    def _on_request(self, request):
        return Response(Response.StatusCode.BAD_REQUEST, None)

    def on_event(self, event):

        # for example: method_name = "_do_event_topologychanged"
        method_name = "_do_event_" + event.event_type.lower()
        if hasattr(self, method_name):
            method = getattr(self, method_name)
            if callable(method):
                method(event)
                return
        return
Пример #7
0
class ComponentManager(RemoteObject):

    # FIXME
    DESCRIPTION = "ComponentManager for python"

    def __init__(self, object_id, dispatcher):
        RemoteObject.__init__(self, object_id, dispatcher)
        self.component_classes = {}
        self.components = {}
        self.dispatcher = dispatcher
        self.__parser = RequestParser()
        self.__add_rules()
        self._object_property.set_state(ObjectProperty.State.RUNNING)

    def register_to_system_manager(self):
        logging.debug("object_property of ComponentManager %s is %s",
                      self.object_id, self._object_property.packed_object())

        self.__register_component_managers()
        path = "component_managers/%s" % self.object_id
        resp = self._request(self.dispatcher.system_manager_id,
                             Request.Method.PUT, path, self._object_property)
        if resp.is_error(Request.Method.PUT):
            logging.error("Failed registration to SystemManager.")
            self._object_property.set_state(ObjectProperty.State.ERROR)
            return

        self.__register_event_manager()
        self.__subscribe_event()
        logging.info("Complete registration to SystemManager.")

    def __register_component_managers(self):
        resp = self._request(self.dispatcher.system_manager_id,
                             Request.Method.GET, "component_managers", None)
        if resp.is_error(Request.Method.GET):
            logging.error("Failed get component_managers from SystemManager.")
            self._object_property.set_state(ObjectProperty.State.ERROR)
            return

        for component_manager in resp.body:
            self.__register_other_component_manager(component_manager)

    def __register_other_component_manager(self, component_manager):
        object_id = component_manager[ObjectProperty.OBJECT_ID]
        if object_id == self.object_id:
            return

        logging.info("Register Other Component Manager ID:%s", object_id)
        self.dispatcher.add_remote_client(object_id)

    def __unregister_component_manager(self, object_id):
        self.dispatcher.remove_remote_client(object_id)

    def __register_event_manager(self):
        resp = self._request(self.dispatcher.system_manager_id,
                             Request.Method.GET,
                             "objects/%s" % self.dispatcher.event_manager_id,
                             None)
        if resp.is_error(Request.Method.GET):
            self._object_property.set_state(ObjectProperty.State.ERROR)
            return

        self.dispatcher.add_remote_client(self.dispatcher.event_manager_id)

    def __subscribe_event(self):
        self._event_subscription.add_filter(self.dispatcher.system_manager_id,
                                            ComponentManagerChanged.TYPE)
        self._apply_event_subscription()

    def register_component_type(self, component):
        component_name = component.__name__
        logging.info("Register Component Type:%s", component_name)

        self.component_classes[component_name] = component
        component_types = \
            self._object_property.get_property(ObjectProperty.COMPONENT_TYPES)
        if component_types:
            component_types += (",%s" % component_name)
        else:
            component_types = "%s" % component_name
        self._object_property.set_property(ObjectProperty.COMPONENT_TYPES,
                                           component_types)

    def __add_rules(self):
        rules = []
        rules.append({
            RequestParser.PATTERN: r"^component_types/?$",
            RequestParser.METHOD: Request.Method.GET,
            RequestParser.FUNC: self._do_get_component_types,
            RequestParser.PARAMS: 0
        })
        rules.append({
            RequestParser.PATTERN: r"^components/?$",
            RequestParser.METHOD: Request.Method.GET,
            RequestParser.FUNC: self._do_get_components,
            RequestParser.PARAMS: 0
        })
        rules.append({
            RequestParser.PATTERN: r"^components/" + "([a-zA-Z0-9_-]+)/?$",
            RequestParser.METHOD: Request.Method.PUT,
            RequestParser.FUNC: self._do_put_component,
            RequestParser.PARAMS: 2
        })
        rules.append({
            RequestParser.PATTERN: r"^components/" + "([a-zA-Z0-9_-]+)/?$",
            RequestParser.METHOD: Request.Method.GET,
            RequestParser.FUNC: self._do_get_component,
            RequestParser.PARAMS: 1
        })
        rules.append({
            RequestParser.PATTERN: r"^components/" + "([a-zA-Z0-9_-]+)/?$",
            RequestParser.METHOD: Request.Method.DELETE,
            RequestParser.FUNC: self._do_delete_component,
            RequestParser.PARAMS: 1
        })
        self.__parser.add_rule(rules)

    def _on_request(self, request):
        return self.__parser.action(request)

    def _do_get_component(self, object_id):
        if object_id in self.components:
            return Response(Response.StatusCode.OK,
                            self.components[object_id].object_property)
        return Response(Response.StatusCode.NOT_FOUND, None)

    def _do_put_component(self, obj_prop, object_id):
        component_type = obj_prop[ObjectProperty.OBJECT_TYPE]

        if component_type not in self.component_classes:
            return Response(Response.StatusCode.BAD_REQUEST, None)
        elif object_id in self.components:
            return Response(Response.StatusCode.CONFLICT, None)

        component_class = self.component_classes[component_type]
        self.components[object_id] = component_class(object_id,
                                                     self.dispatcher)
        if self.components[object_id].on_initialize(obj_prop):
            self.components[object_id].\
                _object_property.set_state(ObjectProperty.State.RUNNING)
        else:
            self.components[object_id].\
                _object_property.set_state(ObjectProperty.State.ERROR)
        curr = self.components[object_id].object_property.packed_object()
        self._do_component_changed(ComponentChanged.Action.ADD, None, curr)

        logging.info("Created Component Type:%s ID:%s", component_type,
                     object_id)
        return Response(Response.StatusCode.CREATED,
                        self.components[object_id].object_property)

    def _do_delete_component(self, object_id):
        if object_id in self.components:
            component = self.components[object_id]
            prev = copy.deepcopy(component._object_property).packed_object()
            component.on_finalize()
            del self.components[object_id]
            self._do_component_changed(ComponentChanged.Action.DELETE, prev,
                                       None)
            logging.info("Deleted Component ID:%s", object_id)

        return Response(Response.StatusCode.OK, None)

    def _do_get_components(self):
        body = {}
        for object_id in self.components:
            body[object_id] = \
                self.components[object_id].object_property.packed_object()
        return Response(Response.StatusCode.OK, body)

    def _do_get_component_types(self):
        comp_types = {}
        try:
            for type_name, clazz in self.component_classes.items():
                comp_id = "%s_%s" % (self.object_id, type_name)
                component = clazz(comp_id, None)
                obj_prop = component.object_property

                type = obj_prop.get_property(ObjectProperty.OBJECT_TYPE)
                super_type = obj_prop.get_property(
                    ObjectProperty.OBJECT_SUPER_TYPE)

                connection_types = {}
                connection_types_str = obj_prop.get_property(
                    ObjectProperty.CONNECTION_TYPES)
                conn_type_list = connection_types_str.split(",")
                for type_elem in conn_type_list:
                    type_elem_list = type_elem.split(":")
                    if len(type_elem_list) == 2:
                        connection_types[type_elem_list[0]] = type_elem_list[1]

                description = obj_prop.get_property(ObjectProperty.DESCRIPTION)

                target = ComponentType(type, super_type, connection_types,
                                       description)
                comp_types[type_name] = target.packed_object()

        except Exception, e:
            return Response(Response.StatusCode.INTERNAL_SERVER_ERROR, str(e))

        return Response(Response.StatusCode.OK, comp_types)
Пример #8
0
class TestRequestParser(unittest.TestCase):

    def dummyFunc0(self):
        self.call_func0 += 1
        return Response(101, None)
    
    def dummyFunc1(self, body, *mached):
        self.call_func1 += 1
        self.func1_body = body
        return Response(102, None)

    def setUp(self):
        self.call_func0 = 0
        self.call_func1 = 0
        self.func1_body = None
        self.target = RequestParser()

    def tearDown(self):
        pass

    def test_constructor(self):
        self.assertEqual(self.target._RequestParser__rules, [])

    def test_add_rule(self):
        self.target.add_rule([{"pattern": "(param1)", "method": "GET",
                               "func": self.dummyFunc0, "params": 0}])
        self.target.add_rule([{"pattern": "(param2)", "method": "PUT",
                               "func": self.dummyFunc1, "params": 1}])
        self.assertEqual(self.target._RequestParser__rules,
                         [{"pattern": "(param1)", "method": "GET",
                           "func": self.dummyFunc0, "params": 0},
                          {"pattern": "(param2)", "method": "PUT",
                           "func": self.dummyFunc1, "params": 1}])

    def test_action(self):
        self.target.add_rule([{"pattern": "(param1)", "method": "GET",
                               "func": self.dummyFunc0, "params": 0},
                              {"pattern": "(param2)", "method": "PUT",
                               "func": self.dummyFunc1, "params": 1}])
        request = Request("id1", "GET", "path/to/param1", None)
        response = self.target.action(request)
        self.assertEqual(self.call_func0, 1)
        self.assertEqual(response.status_code, 101)
        
    def test_action_with_param_attribute_params_is_1(self):
        self.target.add_rule([{"pattern": "(param1)", "method": "GET",
                               "func": self.dummyFunc0, "params": 0},
                              {"pattern": "(param2)", "method": "PUT",
                               "func": self.dummyFunc1, "params": 1}])
        request = Request("id1", "PUT", "path/to/param2", "body")
        response = self.target.action(request)
        self.assertEqual(self.call_func1, 1)
        self.assertEqual(self.func1_body, "body")
        self.assertEqual(response.status_code, 102)

    def test_action_with_param_attribute_params_is_1_and_null_body_request(self):
        self.target.add_rule([{"pattern": "(param1)", "method": "GET",
                               "func": self.dummyFunc0, "params": 0},
                              {"pattern": "(param2)", "method": "PUT",
                               "func": self.dummyFunc1, "params": 1}])
        request = Request("id1", "PUT", "path/to/param2", None)
        response = self.target.action(request)
        self.assertEqual(self.call_func1, 1)
        self.assertEqual(self.func1_body, "param2")
        self.assertEqual(response.status_code, 102)

    def test_action_with_param_attribute_params_is_2(self):
        self.target.add_rule([{"pattern": "(param1)", "method": "GET",
                               "func": self.dummyFunc0, "params": 0},
                              {"pattern": "(param2)", "method": "PUT",
                               "func": self.dummyFunc1, "params": 2}])
        request = Request("id1", "PUT", "path/to/param2", "body")
        response = self.target.action(request)
        self.assertEqual(self.call_func1, 1)
        self.assertEqual(self.func1_body, "body")
        self.assertEqual(response.status_code, 102)

    def test_action_with_param_attribute_params_is_2_and_null_body_request(self):
        self.target.add_rule([{"pattern": "(param1)", "method": "GET",
                               "func": self.dummyFunc0, "params": 0},
                              {"pattern": "(param2)", "method": "PUT",
                               "func": self.dummyFunc1, "params": 2}])
        request = Request("id1", "PUT", "path/to/param2", None)
        response = self.target.action(request)
        self.assertEqual(self.call_func1, 1)
        self.assertEqual(self.func1_body, "param2")
        self.assertEqual(response.status_code, 102)

    def test_action_with_pattern_mached_but_method_not_matched(self):
        self.target.add_rule([{"pattern": "(param1)", "method": "GET",
                               "func": self.dummyFunc0, "params": 0},
                              {"pattern": "(param2)", "method": "PUT",
                               "func": self.dummyFunc1, "params": 1}])
        request = Request("id1", "GET", "path/to/param2", "body")
        response = self.target.action(request)
        self.assertEqual(self.call_func0, 0)
        self.assertEqual(self.call_func1, 0)
        self.assertEqual(self.func1_body, None)
        self.assertEqual(response.status_code, 405)

    def test_action_with_pattern_not_matched(self):
        self.target.add_rule([{"pattern": "(param1)", "method": "GET",
                               "func": self.dummyFunc0, "params": 0},
                              {"pattern": "(param2)", "method": "PUT",
                               "func": self.dummyFunc1, "params": 1}])
        request = Request("id1", "GET", "path/to/param3", "body")
        response = self.target.action(request)
        self.assertEqual(self.call_func0, 0)
        self.assertEqual(self.call_func1, 0)
        self.assertEqual(self.func1_body, None)
        self.assertEqual(response.status_code, 404)