Files
nova-specs/specs/liberty/implemented/request-spec-object.rst
Michael Still 30d5bacb19 Mark liberty specs as implemented
This review syncs the state of launchpad with the spec repo for
things implemented up to liberty-3. There are no changes to the
specs, just things being moved around.

Change-Id: I930d33532b268b6e933c8be06a0569c20fd09586
2015-09-30 10:17:33 +10:00

249 lines
7.9 KiB
ReStructuredText

..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
=========================
Create RequestSpec Object
=========================
https://blueprints.launchpad.net/nova/+spec/request-spec-object
Add a structured, documented object that represents a specification for
launching multiple instances in a cloud.
Problem description
===================
The main interface into the scheduler, the `select_destinations()` method,
accepts a `request_spec` parameter that is a nested dict. This nested dict is
constructed in `nova.scheduler.utils.build_request_spec()`, however the
structure of the request spec is not documented anywhere and the filters in the
scheduler seem to take a laisse faire approach to querying the object during
scheduling as well as modifying the `request_spec` object during loops of the
`nova.scheduler.host_manager.HostStateManager.get_filtered_hosts()` method,
which calls the filter object's `host_passes` object, supplying a
`filter_properties` parameter, which itself has a key called `request_spec`
that contains the aforementioned nested dict.
This situation makes it very difficult to understand exactly what is going on
in the scheduler, and cleaning up this parameter in the scheduler interface is
a pre-requisite to making a properly-versioned and properly-documented
interface in preparation for a split-out of the scheduler code.
Use Cases
----------
This is a pure refactoring effort for cleaning up all the interfaces in between
Nova and the scheduler so the scheduler could be split out by the next cycle.
Project Priority
-----------------
This blueprint is part of a global effort around the 'scheduler' refactoring
for helping it to be split out. It was formerly identified as a priority in
Kilo.
Proposed change
===============
A new class called `RequestSpec` will be created that models a request to
launch multiple virtual machine instances. The first version of the
`RequestSpec` object will simply be an objectified version of the current
dictionary parameter. The scheduler will construct this `RequestSpec` object
from the `request_spec` dictionary itself.
The existing
`nova.scheduler.utils.build_request_spec` method will be removed in favor of a
factory method on `nova.objects.request_spec.RequestSpec` that will construct
a `RequestSpec` from the existing key/value pairs in the `request_spec`
parameter supplied to `select_destinations`.
Alternatives
------------
None.
Data model impact
-----------------
This spec is not focusing on persisting the RequestSpec object but another
blueprint (and a spec) will be proposed with this one as dependency for
providing a save() method to the RequestSpec object which would allow it to be
persisted in (probably) instance_extra DB table.
REST API impact
---------------
None.
Security impact
---------------
None.
Notifications impact
--------------------
None.
Other end user impact
---------------------
None.
Performance Impact
------------------
None.
Other deployer impact
---------------------
None.
Developer impact
----------------
None, besides making the scheduler call interfaces gradually easier to read
and understand.
Implementation
==============
The `request_spec` dictionary is currently constructed by the nova-conductor
when it calls the `nova.scheduler.utils.build_request_spec()` function, which
looks like this:
.. code:: python
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)
As the filter_properties dictionary is hydrated with the request_spec
dictionary, this proposal is merging both dictionaries into a single object.
A possible first version of a class interface for the `RequestSpec`
class would look like this, in order to be as close to a straight conversion
from the nested dict's keys to object attribute notation:
.. code:: python
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)
}
This blueprint targets to provide a new Scheduler API method which would only
accept RequestSpec objects in replacement of select_destinations() which would
be deprecated and removed in a later cycle.
That RPC API method could be having the following signature:
.. code:: python
def select_nodes(RequestSpec):
# ...
As said above in the data model impact section, this blueprint is not targeting
to persist this object at the moment.
Assignee(s)
-----------
Primary assignee:
bauzas
Other contributors:
None
Work Items
----------
- Add request spec class to `nova/objects/request_spec.py` w/ unit tests
- Add a factory classmethod on `nova.objects.RequestSpec` that constructs a
`RequestSpec` object from the *existing* set of instance type extra_specs,
scheduler_hints, flavor and image objects that are supplied to the
`nova.scheduler.utils.build_request_spec` function.
- Convert all filter classes to operate against the `RequestSpec` object
instead the nested `request_spec` dictionary.
- Add developer reference documentation for what the request spec models.
Dependencies
============
None.
Testing
=======
New unit tests for the request spec objects will be added. The existing unit
tests of the scheduler filters will be modified to access the `RequestSpec`
object in the `filter_properties` dictionary.
Documentation Impact
====================
Update any developer reference material that might be referencing the old
dictionary accesses.
References
==========
This blueprint is part of an overall effort to clean up, version, and stabilize
the interfaces between the nova-api, nova-scheduler, nova-conductor and
nova-compute daemons that involve scheduling and resource decisions.