Exemple #1
0
    def execute(self):
        """
        首先判断是否在storage表中
            如果当前为 Storage 状态,那么标记为 Recycling 状态
            如果当前为 Abnormal, Recycling 或 Deleted 状态,那么就 warning
            其余状态等待下次扫描
        然后判断是否在journal表中
            如果为 CreateInJournal,那么标记为 已消费
            其余状态等待下次扫描
        都没有
            warning
        """
        with lm.get_journal_locker(self.trace_msg), lm.get_storage_locker(
                self.trace_msg), s.transaction():
            consume = True
            for ident in self.idents:
                try:
                    if self._deal_in_storage(ident):
                        continue
                    elif self._deal_in_journal(ident):
                        continue
                    else:
                        _logger.warning(f'<{ident}> in [{self}] NOT exist')
                except DestroyJournal.DelayDealException:
                    consume = False  # DelayDealException 异常表示本次不处理,下次再处理

            if consume:
                self._params.consume()
Exemple #2
0
    def execute(self):
        """执行作业

        1. 更新数据库记录,新建立的存储对象指向父节点
            * 新建状态为 Creating 状态
            * 日志对象有子节点记录,就意味着子节点先于本节点创建
              如本节点不是根节点,那么该步骤不修改子节点的指向,在第3步骤再修改
              如本节点为根节点,那么在该步骤修改子节点依赖;因为如果本节点创建失败,逻辑上后续子节点应该无效
            * 父快照必须在 storage 表中
        2. 调用底层模块创建存储文件
            * 如果创建突然中断,那么数据库记录会保持为 Creating 状态,下次启动时进行状态修正
            * 如果创建失败,那么标记为 Abnormal 状态,后台回收线程异步进行状态修正
        3. 更新数据库记录,将建立的存储对象标记为 Writing 状态
            * 如果本节点不是根节点,且具有子节点,需要移动子节点的指向

        :remark:
        1. 调用底层模块创建存储文件并未纳入锁空间
            可知:上层逻辑如果确切需要使用某个存储文件中的数据(同时写入与读取),那么应该自行保证调用时序
        """

        handle: pool.Handle = pool.generate_handle(self._handle, True,
                                                   self.raw_flag)
        new_snapshot: storage.Storage = None
        try:
            with deal_handle_when_excption(handle):
                with lm.get_journal_locker(
                        self.trace_msg), lm.get_storage_locker(
                            self.trace_msg), s.transaction():
                    parent_storage, rw_chain, tree_ident = self._query_parent_storage_and_chain(
                    )
                    new_snapshot = self._create_new_storage(
                        parent_storage, tree_ident)
                    if self.is_root_node:
                        self._deal_children_in_journal(new_snapshot)
                    handle.storage_chain = rw_chain.insert_tail(
                        new_snapshot.storage_obj).acquire()
                    tree.check(new_snapshot.tree_ident)

                with handle.locker:
                    handle.raw_handle, handle.ice_endpoint = (
                        action.DiskSnapshotAction.create_qcow_snapshot(
                            handle.storage_chain, handle.raw_flag))

                with lm.get_storage_locker(self.trace_msg), s.transaction():
                    if not self.is_root_node:
                        self._deal_children_in_journal(new_snapshot)
                    new_snapshot.update_status(
                        m.SnapshotStorage.STATUS_WRITING)
                    tree.check(new_snapshot.tree_ident)

                return handle
        except Exception as e:
            self._set_storage_abnormal_when_except(new_snapshot)
            raise e
Exemple #3
0
    def execute(self) -> pool.Handle:
        """
        1. 更新数据库记录,新建立的存储对象指向父节点
            * 父快照为qcow类型文件时,支持父快照还在日志表中 CreateInJournal;
              也就是,创建文件的时序与日志的时序不一致
              需要在日志表中记录当前节点,支持创建父快照时,调整当前节点的父
            * 其余情况,其父快照必须已经在存储对象表中
        2. 调用底层模块创建存储文件
            * 如果创建突然中断,那么数据库记录会保持为 Creating 状态,下次启动时进行状态修正
            * 如果创建失败,那么标记为 Abnormal 状态,后台回收线程异步进行状态修正
        3. 更新数据库记录,将建立的存储对象标记为 Writing 状态

        :remark:
        1. 仅仅支持单次的创建时序与依赖关系顺序不一致
            也就是不支持依赖链上有超过一个 CreateInJournal 类型的节点,且这些节点在未来某个时刻会真实创建;
            上层逻辑应杜绝出现此类状况
            参考 CreateQcowStorage
        """
        handle: pool.Handle = pool.generate_handle(self._handle, True,
                                                   self.raw_flag)
        new_snapshot: storage.Storage = None
        try:
            with deal_handle_when_excption(handle):
                with lm.get_journal_locker(
                        self.trace_msg), lm.get_storage_locker(
                            self.trace_msg), s.transaction():
                    parent_storage = self._query_parent_storage()
                    new_snapshot = self._create_new_storage(parent_storage)
                    handle.storage_chain = (chain.StorageChainForWrite(
                        srm.get_srm(), self.caller_name).insert_tail(
                            new_snapshot.storage_obj).acquire())

                with handle.locker:
                    handle.raw_handle, handle.ice_endpoint = (
                        action.DiskSnapshotAction.create_cdp_snapshot(
                            handle.storage_chain.last_storage_item,
                            handle.raw_flag))

                with lm.get_storage_locker(self.trace_msg), s.transaction():
                    new_snapshot.update_status(
                        m.SnapshotStorage.STATUS_WRITING)

                return handle
        except Exception as e:
            self._set_storage_abnormal_when_except(new_snapshot)
            raise e
Exemple #4
0
def consume(token: str, trace_msg: str, return_class: typing.Type[J]) -> J:
    """消费日志

    :param token:
    :param trace_msg:
    :param return_class:
    :return: return_class类型的实例
    """

    with lm.get_journal_locker(trace_msg), s.transaction():
        journal_obj = s.get_scoped_session().query(
            m.Journal).filter(m.Journal.token == token).first()
        assert journal_obj, ('磁盘快照日志令牌不存在',
                             f'journal token [{token}] not exist', 0)
        assert not journal_obj.consumed_timestamp, (
            '磁盘快照日志已被消费', f'journal has consumed {token}', 0)
        da_journal.consume(journal_obj)
        return return_class(journal_obj)
Exemple #5
0
    def execute(self):
        """
        1. 获取快照存储链
        2. 调用底层接口打开快照存储链
        """
        handle: pool.Handle = pool.generate_handle(self._handle, False,
                                                   self.raw_flag)
        try:
            with lm.get_journal_locker(self.trace_msg), lm.get_storage_locker(
                    self.trace_msg), s.readonly():
                depend_nodes = self._query_depend_nodes()
                handle.storage_chain = self._generate_chain(
                    depend_nodes).acquire()

            if self.open_raw_handle:
                with handle.locker:
                    handle.raw_handle, handle.ice_endpoint = action.DiskSnapshotAction.open_disk_snapshot(
                        handle.storage_chain, handle.raw_flag)

            return handle
        except Exception:
            handle.destroy()
            raise