分享

Openstack Cinder中建立volume过程的源码解析(5)----以及taskflow相关解析

shihailong123 发表于 2014-11-22 13:29:14 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 0 15371
阅读导读:
1.如何实现Flow类的初始化的?
2.用于卷的建立的flow中都添加了哪些task?
3.ExtractVolumeRequestTask类的作用是什么?
4.如何完全或部分的重置flow的内部的状态?
5.如何从给定的卷中提取卷的id信息?
6.OnFailureChangeStatusTask类的作用?




感谢朋友支持本博客,欢迎共同探讨交流,由于能力和时间有限,错误之处在所难免,欢迎指正!


这里就不写什么开头语了,直接继续上一篇博客!
2.构建并返回用于建立卷的flow(继续)
我们先来关注,这里是如何实现Flow类的初始化的,来看语句:
  1. api_flow = linear_flow.Flow(flow_name)
复制代码
来看看任务流基类中都定义了哪些方法,这也有助于我们理解任务流的整体概念;
  1. class Flow(object):
  2.     """
  3.     The base abstract class of all flow implementations.
  4.     Flow抽象类;
  5.     """
  6.     def __init__(self, name, parents=None, uuid=None):
  7.         super(Flow, self).__init__(name, parents, uuid)
  8.         # 获取回滚方法累加器类的实例化对象;
  9.         self._accumulator = utils.RollbackAccumulator()
  10.         self.results = {}
  11.         self._leftoff_at = None
  12.         # 所有要运行的任务集合;
  13.         self._runners = []
  14.         self._connected = False
  15.         # 确定所要使用的恢复策略;
  16.         self.resumer = None
  17.    
  18. def name(self)flow可读的非唯一的名称;
  19.     def uuid(self)flow唯一的标识;
  20.     def state(self)为flow提供了一个只读的状态信息;
  21.     def _change_state(self, context, new_state)改变目前的flow状态为新的状态new_state,并执行通知操作;
  22.     def add(self, task)添加一个给定的task到工作流中;
  23.     def add_many(self, tasks)添加给定的若干的task到工作流中;
  24.     def interrupt(self)尝试中断当前的flow和当前没有在flow中执行的task;
  25.     def reset(self)完全重置flow的内部的状态,并允许flow再次运行;
  26.     def soft_reset(self)部分地重置flow的内部状态,并允许flow从中止的状态再次运行;
  27.     def run(self, context, *args, **kwargs)工作流(workflow)的执行操作;
  28.     def rollback(self, context, cause)执行workflow和其父workflow的回滚操作;
复制代码
再来看一下这里是如何实现task的添加的,比如语句:
  1. api_flow.add(base.InjectTask(create_what, addons=[ACTION]))
复制代码
所以来看看方法add的源码实现:
  1. @decorators.locked
  2.     def add(self, task):
  3.         """
  4.       Adds a given task to this flow.
  5.         添加一个给定的task到flow;
  6.         """
  7.         assert isinstance(task, collections.Callable)
  8.         r = utils.Runner(task)
  9.         r.runs_before = list(reversed(self._runners))
  10.         self._runners.append(r)
  11.         self._reset_internals()
  12.         return r.uuid
复制代码
所实现的功能就是添加一个给定的task到flow中,具体实现就是添加到self._runners中;其中每一个task都包装成了一个Runner类的对象;其中runs_before中存储了除了当前task的以前的task;这里的变量信息后面的flow运行实现过程中都要用到的;
我们继续来关注用于卷的建立的flow中都添加了哪些task?
2.1 api_flow.add(base.InjectTask(create_what, addons=[ACTION]))
这个类实现了注入字典信息create_what到flow中,create_what是建立卷所要遵守的规范信息(字典);
来看类InjectTask的具体代码:
  1. class InjectTask(CinderTask):
  2.     """
  3.     这个类实现了注入字典信息到flow中;
  4.     """
  5.     def __init__(self, inject_what, addons=None):
  6.         super(InjectTask, self).__init__(addons=addons)
  7.         self.provides.update(inject_what.keys())
  8.         self._inject = inject_what
  9.     def __call__(self, context):
  10.         return dict(self._inject)
复制代码
这个类以task的形式添加到flow中,从这个类的__call__方法我们可以看出,这个类实际上就是实现了对create_what的字典化处理;
在这个task类中并没有具体实现revert方法,因为这个task中不需要回滚操作;
2.2 api_flow.add(ExtractVolumeRequestTask(image_service, az_check_functor))
这个task类所实现的功能就是对输入的请求信息中的相关参数进行验证,并将这些参数转换成有效的集合,并返回这些经过验证和转换的参数,这些参数会应用于后续的task的实现过程之中的;
来看类ExtractVolumeRequestTask的具体代码:
  1. class ExtractVolumeRequestTask(base.CinderTask):
  2.     """
  3.     实现提取并验证处理卷的请求信息任务类;
  4.     这个task的主要任务是提取和验证输入的值,这些输入的值将形成一个潜在的卷的请求信息;
  5.     并且实现根据一组条件对这些输入值进行验证,并将这些输入值转换成有效的集合;
  6.     并返回这些经过验证和转换的输入值,这些输入值将会应用于其他task中。
  7.     """
  8.     # image_service:获取默认的镜像服务类
  9.     # az_check_functor:验证availability_zone是否是可用的(即是否包含在可用zone的列表中);
  10.     def __init__(self, image_service, az_check_functor=None):
  11.         super(ExtractVolumeRequestTask, self).__init__(addons=[ACTION])
  12.         self.provides.update(['availability_zone', 'size', 'snapshot_id',
  13.                               'source_volid', 'volume_type', 'volume_type_id',
  14.                               'encryption_key_id'])
  15.         self.requires.update(['availability_zone', 'image_id', 'metadata',
  16.                               'size', 'snapshot', 'source_volume',
  17.                               'volume_type', 'key_manager',
  18.                               'backup_source_volume'])
  19.         self.image_service = image_service
  20.         self.az_check_functor = az_check_functor
  21.         if not self.az_check_functor:
  22.             self.az_check_functor = lambda az: True
  23.     def __call__(self, context, size, snapshot, image_id, source_volume,
  24.                  availability_zone, volume_type, metadata,
  25.                  key_manager, backup_source_volume):
  26.         """
  27.         这个task的主要任务是提取和验证输入的值,这些输入的值将形成一个潜在的卷的请求信息;
  28.         并且实现根据一组条件对这些输入值进行验证,并将这些输入值转换成有效的集合;
  29.         并返回这些经过验证和转换的输入值,这些输入值将会应用于其他task中。
  30.         """
  31.         # 实现对所提供的输入参数进行是否为空的验证操作;
  32.         utils.check_exclusive_options(snapshot=snapshot,
  33.                                       imageRef=image_id,
  34.                                       source_volume=source_volume)
  35.         # 验证在指定的上下文环境中ACTION是有效的;
  36.         # ACTION = 'volume:create';
  37.         policy.enforce_action(context, ACTION)
  38.         
  39.         # 从给定的快照中提取快照的id信息;
  40.         snapshot_id = self._extract_snapshot(snapshot)
  41.         # 从给定的卷中提取卷的id信息;
  42.         source_volid = self._extract_source_volume(source_volume)
  43.         # 提取并验证卷的大小;
  44.         size = self._extract_size(size, source_volume, snapshot)
  45.         # 检测镜像的存在性,并验证镜像的元数据中镜像大小的属性信息;
  46.         self._check_image_metadata(context, image_id, size)
  47.         # 提取并返回一个经过验证的可用的zone;
  48.         availability_zone = self._extract_availability_zone(availability_zone,
  49.                                                             snapshot,
  50.                                                             source_volume)
  51.         
  52.         # 如果没有定义volume_type,则获取默认的卷的类型;
  53.         if not volume_type and not source_volume and not snapshot:
  54.             # 获取默认的卷的类型;
  55.             volume_type = volume_types.get_default_volume_type()
  56.         # 获取卷类型信息的id值;
  57.         volume_type_id = self._get_volume_type_id(volume_type,
  58.                                                   source_volume, snapshot,
  59.                                                   backup_source_volume)
  60.         
  61.         # 获取加密密钥信息的id值;
  62.         encryption_key_id = self._get_encryption_key_id(key_manager,
  63.                                                         context,
  64.                                                         volume_type_id,
  65.                                                         snapshot,
  66.                                                         source_volume,
  67.                                                         backup_source_volume)
  68.         specs = {}
  69.         # 根据给定的卷类型获取所有QOS功能相关的信息;
  70.         if volume_type_id:
  71.             qos_specs = volume_types.get_volume_type_qos_specs(volume_type_id)
  72.             specs = qos_specs['qos_specs']
  73.         if not specs:
  74.             specs = None
  75.         # 检测卷的元数据属性是有效的;
  76.         self._check_metadata_properties(metadata)
  77.         # 返回经过验证的参数信息;
  78.         # 将会用于其他task的操作;
  79.         return {
  80.             'size': size,
  81.             'snapshot_id': snapshot_id,
  82.             'source_volid': source_volid,
  83.             'availability_zone': availability_zone,
  84.             'volume_type': volume_type,
  85.             'volume_type_id': volume_type_id,
  86.             'encryption_key_id': encryption_key_id,
  87.             'qos_specs': specs,
  88.         }
复制代码
具体功能的实现过程可以看我在代码中的注释信息,这里不再赘述,这个task类中也是不需要回滚操作的;
2.3 api_flow.add(QuotaReserveTask())
在这个task类中主要实现了几个步骤的内容,也就是说:
  • 根据给定的建立新卷的大小和类型,对资源配额信息进行检测,检测建立卷的可行性;
  • 根据给定的建立新卷的大小和类型,实现对数据库中资源配额信息的更新;
  • 保留建立新卷之前的相关资源配额信息,用于一旦卷建立的执行出现异常时,调用逆转回滚方法实现资源配额信息的恢复;
来看类QuotaReserveTask的具体代码:
  1. class QuotaReserveTask(base.CinderTask):
  2.     """
  3.     根据给定的大小值和给定的卷类型信息实现保存单一的卷;
  4.     """
  5.     def __init__(self):
  6.         super(QuotaReserveTask, self).__init__(addons=[ACTION])
  7.         self.requires.update(['size', 'volume_type_id'])
  8.         self.provides.update(['reservations'])
  9.     def __call__(self, context, size, volume_type_id):
  10.         """
  11.         根据给定的大小值和给定的卷类型信息实现保存单一的卷;
  12.         根据给定的建立新卷的大小和类型,对资源配额信息进行检测,检测建立卷的可行性;
  13.         根据给定的建立新卷的大小和类型,实现对数据库中资源配额信息的更新;
  14.         保留建立新卷之前的相关资源配额信息,用于一旦卷建立的执行出现异常时,调用逆转回滚方法实现资源配额信息的恢复;
  15.         """
  16.         try:
  17.             reserve_opts = {'volumes': 1, 'gigabytes': size}
  18.             # 添加卷的类型信息到reserve_opts,reserve_opts表示保留选项信息;
  19.             QUOTAS.add_volume_type_opts(context, reserve_opts, volume_type_id)
  20.             # 检测配额信息和并建立相应的资源配额预留资源;
  21.             reservations = QUOTAS.reserve(context, **reserve_opts)
  22.             return {
  23.                 'reservations': reservations,
  24.             }
  25.         except exception.OverQuota as e:
  26.             overs = e.kwargs['overs']
  27.             quotas = e.kwargs['quotas']
  28.             usages = e.kwargs['usages']
  29.             def _consumed(name):
  30.                 return (usages[name]['reserved'] + usages[name]['in_use'])
  31.             def _is_over(name):
  32.                 for over in overs:
  33.                     if name in over:
  34.                         return True
  35.                 return False
  36.             if _is_over('gigabytes'):
  37.                 msg = _("Quota exceeded for %(s_pid)s, tried to create "
  38.                         "%(s_size)sG volume (%(d_consu:med)dG "
  39.                         "of %(d_quota)dG already consumed)")
  40.                 LOG.warn(msg % {'s_pid': context.project_id,
  41.                                 's_size': size,
  42.                                 'd_consumed': _consumed('gigabytes'),
  43.                                 'd_quota': quotas['gigabytes']})
  44.                 raise exception.VolumeSizeExceedsAvailableQuota()
  45.             elif _is_over('volumes'):
  46.                 msg = _("Quota exceeded for %(s_pid)s, tried to create "
  47.                         "volume (%(d_consumed)d volumes "
  48.                         "already consumed)")
  49.                 LOG.warn(msg % {'s_pid': context.project_id,
  50.                                 'd_consumed': _consumed('volumes')})
  51.                 allowed = quotas['volumes']
  52.                 raise exception.VolumeLimitExceeded(allowed=quotas['volumes'])
  53.             else:
  54.                 # If nothing was reraised, ensure we reraise the initial error
  55.                 raise
  56.     def revert(self, context, result, cause):
  57.         """
  58.         根据result中的reservations保留的信息,恢复数据库中卷的配额信息到建立新卷之前的状态;
  59.         """
  60.         if not result:
  61.             return
  62.         if context.quota_committed:
  63.             return
  64.         reservations = result['reservations']
  65.         
  66.         # 根据reservations保留的信息,恢复数据库中卷的配额信息到建立新卷之前的状态;
  67.         try:
  68.             QUOTAS.rollback(context, reservations)
  69.         except exception.CinderException:
  70.             LOG.exception(_("Failed rolling back quota for"
  71.                             " %s reservations"), reservations)
复制代码
具体功能的实现过程可以看我在代码中的注释信息,这里不再赘述;在这个类中实现了revert方法,用于当建立卷的过程中出现异常时,实现根据result中的reservations保留的信息,恢复数据库中卷的配额信息到建立新卷之前的状态;在方法revert中,具体调用了方法QUOTAS.rollback,我们简单来看一下代码的实现过程:
  1. def rollback(self, context, reservations, project_id=None):
  2.         """
  3.         回调配额预留资源;
  4.         根据reservations保留的信息,恢复数据库中卷的配额信息到建立新卷之前的状态;
  5.         """
  6.         # 回调配额预留资源;
  7.         # 根据reservations保留的信息,恢复数据库中卷的配额信息到建立新卷之前的状态;
  8.         try:
  9.             self._driver.rollback(context, reservations, project_id=project_id)
  10.         except Exception:
  11.             LOG.exception(_("Failed to roll back reservations "
  12.                             "%s") % reservations)
  13.     def rollback(self, context, reservations, project_id=None):
  14.         """
  15.         回调配额预留资源;
  16.         根据reservations保留的信息,恢复数据库中卷的配额信息到建立新卷之前的状态;
  17.         """
  18.         if project_id is None:
  19.             project_id = context.project_id
  20.         db.reservation_rollback(context, reservations, project_id=project_id)
  21.     def reservation_rollback(context, reservations, project_id=None):
  22.         """
  23.         回调配额预留资源;
  24.         根据reservations保留的信息,恢复数据库中卷的配额信息到建立新卷之前的状态;
  25.         """
  26.         return IMPL.reservation_rollback(context, reservations,
  27.                                          project_id=project_id)
  28.     @require_context
  29.     def reservation_rollback(context, reservations, project_id=None):
  30.         """
  31.         回调配额预留资源;
  32.         根据reservations保留的信息,恢复数据库中卷的配额信息到建立新卷之前的状态;
  33.         """
  34.         session = get_session()
  35.         with session.begin():
  36.             usages = _get_quota_usages(context, session, project_id)
  37.             for reservation in _quota_reservations(session, context, reservations):
  38.                 usage = usages[reservation.resource]
  39.                 if reservation.delta >= 0:
  40.                     usage.reserved -= reservation.delta
  41.                 reservation.delete(session=session)
  42.             for usage in usages.values():
  43.                 usage.save(session=session)
  44.     def _quota_reservations(session, context, reservations):
  45.         """Return the relevant reservations."""
  46.         # Get the listed reservations
  47.         return model_query(context, models.Reservation,
  48.                            read_deleted="no",
  49.                            session=session).\
  50.             filter(models.Reservation.uuid.in_(reservations)).\
  51.             with_lockmode('update').\
  52.             all()
复制代码
我们可以看到,到最后方法根据reservations在数据表Reservation中查询到对应的保留的资源配额信息,来实现恢复数据库中卷的资源配额信息到建立新卷之前的状态。
2.4 v_uuid = api_flow.add(EntryCreateTask(db))
这个task类所实现的功能是在数据库中为给定的要建立的卷来建立相关条目;
来看类EntryCreateTask的具体代码:
  1. class EntryCreateTask(base.CinderTask):
  2.     """
  3.     在数据库中为给定的卷建立条目;
  4.     逆转操作:从数据库中删除volume_id建立的条目;
  5.     """
  6.     def __init__(self, db):
  7.         super(EntryCreateTask, self).__init__(addons=[ACTION])
  8.         self.db = db
  9.         self.requires.update(['availability_zone', 'description', 'metadata',
  10.                               'name', 'reservations', 'size', 'snapshot_id',
  11.                               'source_volid', 'volume_type_id',
  12.                               'encryption_key_id'])
  13.         self.provides.update(['volume_properties', 'volume_id'])
  14.     def __call__(self, context, **kwargs):
  15.         """
  16.         为给定的输入在数据库中建立数据条目,并返回详细信息;
  17.         从kwargs中获取卷的相关属性值,并根据卷的相关属性值在数据库中实现新卷的建立;
  18.         """
  19.         volume_properties = {
  20.             'size': kwargs.pop('size'),
  21.             'user_id': context.user_id,
  22.             'project_id': context.project_id,
  23.             'status': 'creating',
  24.             'attach_status': 'detached',
  25.             'encryption_key_id': kwargs.pop('encryption_key_id'),
  26.             # Rename these to the internal name.
  27.             'display_description': kwargs.pop('description'),
  28.             'display_name': kwargs.pop('name'),
  29.         }
  30.         volume_properties.update(kwargs)
  31.         # 根据卷的相关属性volume_properties的值来建立新卷;
  32.         volume = self.db.volume_create(context, volume_properties)
  33.         return {
  34.             'volume_id': volume['id'],
  35.             'volume_properties': volume_properties,
  36.             'volume': volume,
  37.         }
  38.     def revert(self, context, result, cause):
  39.         """
  40.         删除指定的卷在数据库中的数据条目信息,实现逆转回滚操作;
  41.         """
  42.         
  43.         # 如果result为none,说明从来没有产生任何结果,因此不能删除任何数据信息;
  44.         if not result:
  45.             return
  46.         
  47.         # quota_committed说明不能执行回滚操作,说明此时卷已经建立;
  48.         if context.quota_committed:
  49.             return
  50.         vol_id = result['volume_id']
  51.         
  52.         # 删除指定的卷在数据库中的数据条目信息;
  53.         try:
  54.             self.db.volume_destroy(context.elevated(), vol_id)
  55.         except exception.CinderException:
  56.             LOG.exception(_("Failed destroying volume entry %s"), vol_id)
复制代码
这个task类实现的功能很简单,就是在数据库中为新建立的卷添加相关的条目信息,如果建立卷的操作出现异常,可以调用方法revert来实现删除卷在数据库中新建立的数据条目信息,从而实现逆转回滚操作;
2.5 api_flow.add(QuotaCommitTask())
这个task类所实现的功能就是,暂时假设卷的建立是成功的,此时需要改变资源配额信息,这里就是提交新的资源配额信息到数据库中;
如果卷的建立出现异常,这个task中也实现了revert方法,这个方法就是根据新建立的卷的大小等信息,从改变后的资源配额预留信息中减去新建立卷的大小等信息,就可以实现恢复卷的资源配额预留信息到新卷的建立之前的状态;
来看类QuotaCommitTask的具体代码:
  1. class QuotaCommitTask(base.CinderTask):
  2.     """
  3.     提交新的资源配额的预留信息到数据库中;
  4.     """
  5.     def __init__(self):
  6.         super(QuotaCommitTask, self).__init__(addons=[ACTION])
  7.         self.requires.update(['reservations', 'volume_properties'])
  8.     def __call__(self, context, reservations, volume_properties):
  9.         # 提交新的资源配额的预留信息到数据库中;
  10.         QUOTAS.commit(context, reservations)
  11.         context.quota_committed = True
  12.         return {'volume_properties': volume_properties}
  13.     def revert(self, context, result, cause):
  14.         """
  15.         如果建立卷出现异常,则执行回滚操作,实现恢复数据库中原有的资源配额预留信息;
  16.         """
  17.         if not result:
  18.             return
  19.         volume = result['volume_properties']
  20.         try:
  21.             reserve_opts = {'volumes': -1, 'gigabytes': -volume['size']}
  22.             # 添加卷的类型选项到reserve_opts;
  23.             QUOTAS.add_volume_type_opts(context,
  24.                                         reserve_opts,
  25.                                         volume['volume_type_id'])
  26.             # 检测配额信息和并建立相应的资源配额预留资源;
  27.             reservations = QUOTAS.reserve(context,
  28.                                           project_id=context.project_id,
  29.                                           **reserve_opts)
  30.             # 提交资源配额的预留信息到数据库中;
  31.             if reservations:
  32.                 QUOTAS.commit(context, reservations,
  33.                               project_id=context.project_id)
  34.         except Exception:
  35.             LOG.exception(_("Failed to update quota for deleting volume: %s"),
  36.                           volume['id'])
复制代码
上述功能的实现是很好理解的,也就是数据库相关的操作;
2.6 api_flow.add(OnFailureChangeStatusTask(db))
这个task类所实现的功能是当出现错误异常时,设置指定id的卷的状态为ERROR;
来看类OnFailureChangeStatusTask的具体代码:
  1. class OnFailureChangeStatusTask(base.CinderTask):
  2.     """
  3.     这个task实现了当出现错误时,设置指定id的卷的状态为ERROR;
  4.     """
  5.     def __init__(self, db):
  6.         super(OnFailureChangeStatusTask, self).__init__(addons=[ACTION])
  7.         self.db = db
  8.         self.requires.update(['volume_id'])
  9.         self.optional.update(['volume_spec'])
  10.     def __call__(self, context, volume_id, volume_spec=None):
  11.         return {
  12.             'volume_id': volume_id,
  13.             'volume_spec': volume_spec,
  14.         }
  15.     def revert(self, context, result, cause):
  16.         volume_spec = result.get('volume_spec')
  17.         if not volume_spec:
  18.             volume_spec = _find_result_spec(cause.flow)
  19.         volume_id = result['volume_id']
  20.         _restore_source_status(context, self.db, volume_spec)
  21.         _error_out_volume(context, self.db, volume_id, reason=cause.exc)
  22.         LOG.error(_("Volume %s: create failed"), volume_id)
  23.         exc_info = False
  24.         if all(cause.exc_info):
  25.             exc_info = cause.exc_info
  26.         LOG.error(_('Unexpected build error:'), exc_info=exc_info)
复制代码
2.7 api_flow.add(VolumeCastTask(scheduler_rpcapi, volume_rpcapi, db))
这个task类所实现的功能就是根据具体需求调用相关的方法实现卷的建立。这里我先不做具体的分析,后面我会专门写一篇新的博客来对这里的实现进行详细的解析。当然,这个task类中就没有revert方法啦。

OK!上面我对添加到flow中的相关task进行了简单的解析,我们发现这些task类都继承自父类CinderTask,以及祖父类(哈哈哈)Task,我们来看看它们的相关实现:
  1. class CinderTask(task.Task):
  2.     """
  3.     所有cinder任务的基类;
  4.     """
  5.     def __init__(self, addons=None):
  6.         # _make_task_name:获取任务类的名称;
  7.         super(CinderTask, self).__init__(_make_task_name(self.__class__, addons))
复制代码
这里我们看一个输出实例,是添加第一个task之后进行测试输出的:
  1. _make_task_name(self.__class__, addons) = cinder.volume.flows.base.InjectTask;volume:create
复制代码
可见,实现的功能就是获取了当前任务类的类名和任务;
  1. class Task(object):
  2.     """
  3.     这里定义了task的抽象的概念,可以用于恢复进程到没有执行操作的状态;
  4.     """
  5.     __metaclass__ = abc.ABCMeta
  6.     def __init__(self, name):
  7.         self.name = name
  8.         self.requires = set()
  9.         self.optional = set()
  10.         self.provides = set()
  11.         self.version = (1, 0)
  12.     def __str__(self):
  13.         return "%s==%s" % (self.name, utils.join(self.version, with_what="."))
  14.     @abc.abstractmethod
  15.     def __call__(self, context, *args, **kwargs):
  16.         raise NotImplementedError()
  17.     def revert(self, context, result, cause):
  18.         pass
复制代码
好了,具体如何实现用于建立新卷的flow的构建的过程已经简单的进行了解析,在下一篇博客中,我会进行如何执行构建好的flow的解析工作,也就是上一篇博客中的第3步骤!


相关文章:
Openstack Cinder中建立volume过程的源码解析(1)
http://www.aboutyun.com/thread-10217-1-1.html
1.cinder中卷的建立的过程中,客户端传递过来的request的执行过程是怎样的?
2.__call__方法都通过什么方法封装?
3.如何调用指定中间件的__call__方法?


Openstack Cinder中建立volume过程的源码解析(2)
http://www.aboutyun.com/thread-10216-1-1.html
1.如何获取要执行的action方法及其相关的扩展方法?
2.Resource类中的__call__(self,request)方法如何实现?
3.meth的作用?
4.如何从request.environ中获取要执行的action方法?
5.如何对body进行反序列化操作?


Openstack Cinder中建立volume过程的源码解析(3)
http://www.aboutyun.com/thread-10215-1-1.html
1.get_serializer的作用?
2.isgeneratorfunction是用来做什么的?
3.什么是特殊的generator方法?
4.进行响应信息的序列化操作的步骤?
5.简述在cinder模块中实现客户端发送过来的请求信息操作的主要的步骤?

Openstack Cinder中建立volume过程的源码解析(4)----以及taskflow相关解析
http://www.aboutyun.com/thread-10214-1-1.html
1.简述cinder是如何实现卷的建立的?
2.简述taskflow库来实现卷的简历过程?
3.如何根据给定id来检索获取单个的卷的类型?
4.如何构建并返回用于建立卷的flow?
5.如何声明flow是否是真的?
6.简述建立卷的flow的步骤?




Openstack Cinder中建立volume过程的源码解析(6)----以及taskflow相关解析
http://www.aboutyun.com/thread-10212-1-1.html
1.如何来运行已经构建好的flow?
2.run的源码如何实现及实现过程是什么?
3.resume_it的实现过程是什么?
4.类Runner的初始化方法是什么?
5.run_it的源码如何实现?

Openstack Cinder中建立volume过程的源码解析(7)----以及taskflow相关解析
http://www.aboutyun.com/thread-10211-1-1.html
1.关于flow中task执行的重要语句的实现基本解析完成,如何实现?
2.如果卷的建立出现异常,则如何执行相关的逆转回滚操作?

Openstack Cinder中建立volume过程的源码解析(8)
http://www.aboutyun.com/thread-10219-1-1.html
1.VolumeCastTask的源码如何实现?
2.远程调用建立新卷的操作,有哪几个步骤?
3.task类VolumeCastTask具体是如何来实现根据请求信息进行卷的建立的?


Openstack Cinder中建立volume过程的源码解析(9)
http://www.aboutyun.com/thread-10210-1-1.html
1.如何实现create_volume的源码?
2.Cast如何实现远程调create_volume?
3.如何实现调用方法self.volume_rpcapi.create_volume来实现在目标主机上新卷的建立?




好晚了啊,明天继续吧,加油!如果转载,请保留作者信息。
博客地址:http://blog.csdn.net/gaoxingnengjisuan
邮箱地址:dong.liu@siat.ac.cn




没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条