Пример #1
0
 def _run_catch(self, func, path, path_is_dir=False):
     """
     执行func并捕获异常,将文件系统异常转换为对应的异常对象
     """
     ospath = self._base + path
     try:
         if os.path.exists(ospath):
             if path_is_dir:
                 if os.path.isdir(ospath):
                     return func()
             else:
                 if os.path.isfile(ospath):
                     # 判断文件是否过期,过期直接报错
                     mtime = os.stat(ospath).st_mtime
                     if mtime < time.time() - self._timeout:
                         self.delete_node(path, True)
                     else:
                         return func()
                 else:
                     return func()
         raise exception.EPNoNodeError()
     except exception.EPNoNodeError as e:
         log.r(e, "Node not exist:{}".format(path))
     except Exception as e:
         log.r(exception.EPIOError(), "Request I/O Error")
Пример #2
0
 def _run_catch(cls, func, path, path_is_dir=False):
     """
     执行func并捕获异常,将kazoo异常转换为对应的异常对象
     """
     try:
         if not os.path.exists(path) or (path_is_dir and not os.path.isdir(path)):
             raise exception.EPNoNodeError()
         return func()
     except exception.EPNoNodeError as e:
         log.r(e, "Node not exist:{}".format(path))
     except:
         log.r(exception.EPIOError(), "Request I/O Error")
Пример #3
0
 def _run_catch(cls, func):
     """
     执行func并捕获异常,将kazoo异常转换为对应的异常对象
     """
     import kazoo
     try:
         return func()
     except kazoo.interfaces.IHandler.timeout_exception:
         raise exception.EPConnectTimeout()
     except kazoo.exceptions.NoNodeError:
         raise exception.EPNoNodeError()
     except:
         log.r(exception.EPIOError(), "Request I/O Error")
Пример #4
0
    def del_listener(self, listener):
        """
        删除一个消息处理器

        :param Listener listener: 消息处理器
        :return: 无返回
        :rtype: None
        :raises ValueError: 消息处理器不存在
        """
        try:
            self._listener_list.remove(listener)
            del self._listener_table[listener]
        except ValueError as e:
            log.r(e, "del listener failed")
Пример #5
0
    def create_node(self, path, value="", ephemeral=False, sequence=False, makepath=False):
        """
        根据节点各属性创建节点

        :param str path: 节点路径
        :param str value: 待存数据
        :param bool ephemeral: 是否是临时节点
        :param bool sequence: 是否是顺序节点
        :param bool makepath: 是否创建父节点
        :return: None
        :raises: exception.EPNoNodeError 节点不存在
        :raises: exception.EPIOError IO异常
        """
        path = self._base + path
        try:
            if ephemeral:
                # 临时节点,直接用文件来表示
                dirname = os.path.dirname(path)
                if not os.path.exists(dirname):
                    if makepath:
                        os.makedirs(dirname, self._mode)
                    else:
                        raise exception.EPNoNodeError
                file_path = path
                if sequence:
                    file_path = FilePersistence._seq_file_name(path)
                with open(file_path, 'w') as f:
                    f.write(value)
                with self._lock:
                    self._touch_paths[file_path] = ""
            else:
                # 实体节点,用目录来表示,数据存放在目录下的.data文件中
                if not os.path.exists(path):
                    if not os.path.exists(os.path.dirname(path)) and not makepath:
                        raise exception.EPNoNodeError
                    os.makedirs(path, self._mode)

                file_path = "/".join((path, ".data"))

                with open(file_path, 'w') as f:
                    f.write(value)
        except exception.EPNoNodeError as e:
            log.r(e, "Node not exist:{}".format(os.path.dirname(path)))
        except:
            log.r(exception.EPIOError(), "Request I/O Error")
        log.d("create node success, path:{path}, value:{value}, ephemeral:"
              "{ephemeral}, sequence:{sequence}, makepath:{makepath}".format(
                                                        path=path, value=value,
                                                        ephemeral=ephemeral, sequence=sequence,
                                                        makepath=makepath))
Пример #6
0
 def _run_catch(cls, func):
     """
     执行func并捕获异常,将kazoo异常转换为对应的异常对象
     """
     import kazoo
     try:
         return func()
     except kazoo.exceptions.NoNodeError:
         raise exception.EPNoNodeError()
     except kazoo.exceptions.ZookeeperError:
         log.f("zk fail")
         raise exception.EPServerError()
     except Exception as e:
         log.r(exception.EPIOError(), "Requesst I/O Error")
Пример #7
0
 def _run_catch(cls, func, path="", path_is_dir=False):
     """
     执行func并捕获异常,将kazoo异常转换为对应的异常对象
     """
     import redis
     # noinspection PyBroadException
     try:
         return func()
     except redis.exceptions.ConnectionError:
         raise exception.EPConnectTimeout()
     except exception.EPNoNodeError as e:
         raise e
     except Exception as e:
         log.r(exception.EPIOError(), "Request I/O Error")
Пример #8
0
    def active(self):
        """
        感知器生效函数。该函数创建新线程,定期进行外部事件拉取操作

        :return: 无返回
        :rtype: None
        :raises ThreadError: 创建线程失败
        """
        try:
            self._pull_thread = threading.Thread(
                target=self.event_dealer)
            self._pull_thread.daemon = True
            self._pull_thread.start()
        except threading.ThreadError as e:
            log.r(e, "create new thread err")
Пример #9
0
    def active(self):
        """
        重载感知器生效函数,加入自动刷新线程的生效操作。

        :return: 无返回
        :rtype: None
        :raises ThreadError: 创建线程失败
        """
        super(CronSensor, self).active()
        try:
            self._reload_thread = threading.Thread(target=self._reload)
            self._reload_thread.daemon = True
            self._reload_thread.start()
        except threading.ThreadError as e:
            log.r(e, "create new thread err")
Пример #10
0
    def start(self):
        """
        启动状态机

        :return: None
        :raises EStatusMismatch: 状态不匹配
        :raises Exception: 通用异常
        """
        self.prepare()
        if self._status == self.Status.INITED \
                or self._status == self.Status.PAUSED:
            self._status = self.Status.RUNNING
        else:
            raise exception.EStatusMismatch(
                "Only in inited or paused status can call "
                "this method.current status:{}".format(self._status))
        while self._status == self.Status.RUNNING:
            try:
                self.run_next()
            except Exception as e:
                self._status = self.Status.FAILED
                log.r(e, "start fail in run_next")
Пример #11
0
    def save_context(self):
        """
        运行数据持久化,当当前Guardian为主(lock属性为True)时,可持久化数据,否则失败

        :return: 无返回
        :rtype: None
        :raises EInvalidOperation: 非法操作
        """
        if not self.lock:
            log.e("current guardian instance no privilege to save context")
            raise exception.EInvalidOperation(
                "current guardian instance no privilege to save context")
        context_path = config.GuardianConfig.get_persistent_path("context")
        context_to_persist = self
        operations_tmp = self.operations
        context_to_persist.operations = {}
        try:
            persistence.PersistenceDriver().save_data(context_path, pickle.dumps(context_to_persist))
        except Exception as e:
            self.operations = operations_tmp
            log.r(e, "save context fail")

        self.operations = operations_tmp
        log.d("save context success")
Пример #12
0
    def start(self):
        """
        带有持久化功能的状态机启动执行。状态机启动后,会根据每个节点执行的返回值,执行下一个节点,直到返回
        结束或执行异常。在每个节点执行完成后,会向结果队列中发送消息,由主进程进行处理



        :return: 无返回
        :rtype: None
        """
        session = self.session
        while True:
            control_id, control_message = self._helper.get_control_message(session)
            if control_id is not None:
                # 状态机第一次处理控制消息或控制消息为最新还没被处理
                if session.last_control_id is None \
                        or session.last_control_id != control_id:
                    control_message_cp = copy.deepcopy(control_message)
                    session.last_control_id = copy.deepcopy(control_id)
                else:
                    control_message_cp = None
            else:
                control_message_cp = None

            # session中的控制消息应在处理完成之后被清理
            session.control_message = control_message_cp
            if session.control_message is not None:
                # 感知到控制消息后要强制持久化session,避免控制消息丢失
                self._helper.persist(
                    reason=PersistedStateMachineHelper.Reason.CONTROL,
                    session=session,
                    finished_name=None,
                    next_name=None
                )

            # 第一次运行的状态机,记录第一个节点信息
            if self.status == self.Status.INITED:
                todo_params = self.dump()
                todo_node_name = todo_params["current_node"]
                self._helper.persist(
                    reason=PersistedStateMachineHelper.Reason.STARTED,
                    session=session,
                    finished_name=None,
                    next_name=todo_node_name
                )
                self.status = self.Status.RUNNING

            if self.status == self.Status.RUNNING:
                try:
                    finished_node_name = self.dump()["current_node"]
                    self.run_next()
                    session.nodes_process[finished_node_name] = True

                    finished_state = self.dump()
                    todo_node_name = finished_state["current_node"]
                    session.status = finished_state["status"]

                    if self.status == self.Status.FINISHED:
                        session.current_node = None
                    else:
                        session.current_node = self. \
                            get_node(todo_node_name)

                    session.nodes_process = copy.copy(
                        finished_state["nodes_process"])

                    # 节点变更或需要强制刷新
                    if finished_node_name != todo_node_name or session.reset_flush():
                        self._helper.persist(
                            reason=PersistedStateMachineHelper.Reason.NODE_CHANGED,
                            session=session,
                            finished_name=finished_node_name,
                            next_name=todo_node_name
                        )

                except Exception as e:
                    self.status = self.Status.FAILED
                    log.r(e, "start fail in running")
            else:
                break