创建 RequestSpec 对象

https://blueprints.launchpad.net/nova/+spec/request-spec-object

添加一个结构化、文档化的对象,用于表示在云中启动多个实例的规范。

问题描述

调度器的主要接口,select_destinations() 方法,接受一个 request_spec 参数,该参数是一个嵌套字典。该嵌套字典是在 nova.scheduler.utils.build_request_spec() 中构建的,但是请求规范的结构在任何地方都没有文档说明,并且调度器中的过滤器似乎对在调度期间查询该对象以及在 nova.scheduler.host_manager.HostStateManager.get_filtered_hosts() 方法的循环中修改 request_spec 对象采取了一种放任自流的态度,该方法调用过滤器的 host_passes 对象,并提供一个 filter_properties 参数,该参数本身包含一个名为 request_spec 的键,其中包含上述嵌套字典。

这种情况使得很难理解调度器中到底发生了什么,并且清理调度器接口中的此参数是为调度器代码的拆分做准备,以便创建一个正确版本化和正确文档化的接口的先决条件。

用例

这是一项纯粹的重构工作,旨在清理 Nova 和调度器之间的所有接口,以便在下一个周期中可以拆分调度器。

项目优先级

这份蓝图是围绕“调度器”重构进行的一项全球性努力的一部分,旨在帮助将其拆分出去。它之前在 Kilo 中被确定为优先级。

提议的变更

将创建一个名为 RequestSpec 的新类,用于模拟请求启动多个虚拟机实例。 RequestSpec 对象的第一个版本将只是当前字典参数的对象化版本。 调度器将从 request_spec 字典本身构建此 RequestSpec 对象。

现有的 nova.scheduler.utils.build_request_spec 方法将被移除,以支持 nova.objects.request_spec.RequestSpec 上的一个工厂方法,该方法将从提供给 select_destinationsrequest_spec 参数中的现有键/值对构建一个 RequestSpec

备选方案

无。

数据模型影响

此规范不侧重于持久化 RequestSpec 对象,但将提出另一个蓝图(和一个规范),并将此规范作为依赖项,为 RequestSpec 对象提供一个 save() 方法,该方法将允许将其持久化在(可能)instance_extra DB 表中。

REST API 影响

无。

安全影响

无。

通知影响

无。

其他最终用户影响

无。

性能影响

无。

其他部署者影响

无。

开发人员影响

除了使调度器调用接口逐渐更容易阅读和理解之外,没有其他影响。

实现

当前由 nova-conductor 在调用 nova.scheduler.utils.build_request_spec() 函数时构建 request_spec 字典,其结构如下

def build_request_spec(ctxt, image, instances, instance_type=None):
   """Build a request_spec for the scheduler.

   The request_spec assumes that all instances to be scheduled are the same
   type.
   """
   instance = instances[0]
   if isinstance(instance, obj_base.NovaObject):
       instance = obj_base.obj_to_primitive(instance)

   if instance_type is None:
       instance_type = flavors.extract_flavor(instance)
   # NOTE(comstud): This is a bit ugly, but will get cleaned up when
   # we're passing an InstanceType internal object.
   extra_specs = db.flavor_extra_specs_get(ctxt, instance_type['flavorid'])
   instance_type['extra_specs'] = extra_specs
   request_spec = {
           'image': image or {},
           'instance_properties': instance,
           'instance_type': instance_type,
           'num_instances': len(instances),
           # NOTE(alaski): This should be removed as logic moves from the
           # scheduler to conductor.  Provides backwards compatibility now.
           'instance_uuids': [inst['uuid'] for inst in instances]}
   return jsonutils.to_primitive(request_spec)

由于 `filter_properties` 字典会使用 `request_spec` 字典进行填充,因此该提案将这两个字典合并到一个对象中。

为了尽可能接近从嵌套字典的键到对象属性表示法的直接转换,RequestSpec 类的一个可能的第一个版本类接口如下所示

class RequestSpec(base.NovaObject):

   """Models the request to launch one or more instances in the cloud."""

   VERSION = '1.0'

   fields = {
       'image': fields.ObjectField('ImageMeta', nullable=False),
       'root_gb': fields.IntegerField(nullable=False),
       'ephemeral_gb': fields.IntegerField(nullable=False),
       'memory_mb: fields.IntegerField(nullable=False),
       'vcpus': fields.IntegerField(nullable=False),
       'numa_topology': fields.ObjectField('InstanceNUMATopology',
                                           nullable=True),
       'project_id': fields.StringField(nullable=True),
       'os_type': fields.StringField(nullable=True),
       'availability_zone': fields.StringField(nullable=True),
       'instance_type': fields.ObjectField('Flavor', nullable=False),
       'num_instances': fields.IntegerField(default=1),
       'force_hosts': fields.StringField(nullable=True),
       'force_nodes': fields.StringField(nullable=True),
       'pci_requests': fields.ListOfObjectsField('PCIRequest', nullable=True),
       'retry': fields.ObjectField('Retry', nullable=True),
       'limits': fields.ObjectField('Limits', nullable=True),
       'group': fields.ObjectField('GroupInfo', nullable=True),
       'scheduler_hints': fields.DictOfStringsField(nullable=True)
   }

这份蓝图的目标是提供一个新的调度器 API 方法,该方法仅接受 `RequestSpec` 对象,以替代 `select_destinations()`,后者将在后续周期中被弃用并移除。

该 RPC API 方法的签名可能如下所示

def select_nodes(RequestSpec):
   # ...

如上文“数据模型影响”部分所述,这份蓝图目前不打算持久化此对象。

负责人

主要负责人

bauzas

其他贡献者

工作项

  • nova/objects/request_spec.py 中添加请求规范类,并附带单元测试

  • nova.objects.RequestSpec 上添加一个工厂类方法,该方法从提供给 nova.scheduler.utils.build_request_spec 函数的 *现有* 实例类型 extra_specs、scheduler_hints、flavor 和 image 对象中构建一个 RequestSpec 对象。

  • 将所有过滤器类更改为对 RequestSpec 对象而不是嵌套的 request_spec 字典进行操作。

  • 添加开发人员参考文档,说明请求规范建模的内容。

依赖项

无。

测试

将添加新的请求规范对象单元测试。调度器过滤器的现有单元测试将被修改,以访问 filter_properties 字典中的 RequestSpec 对象。

文档影响

更新任何可能引用旧字典访问的开发人员参考资料。

参考资料

此蓝图是整体工作的一部分,旨在清理、版本化和稳定 nova-api、nova-scheduler、nova-conductor 和 nova-compute 守护程序之间涉及调度和资源决策的接口。