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 __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 __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 __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 setUp(self): self.call_func0 = 0 self.call_func1 = 0 self.func1_body = None self.target = RequestParser()
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)
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)
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 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)
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)
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 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)
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)