Return Selection Objects
In Queens, we are going to be returning a lot more information from the Scheduler to the Conductor. If we return it as a series of nested dictionaries and lists, it will be fragile and confusing. It would be far better to create an object to hold this data and make it accessible in a simpler and documented way. Blueprint: return-selection-objects Change-Id: I7e94525ba9ee22885ea18a752a416024c36b4a40
This commit is contained in:
232
specs/queens/approved/return-selection-objects.rst
Normal file
232
specs/queens/approved/return-selection-objects.rst
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
..
|
||||||
|
This work is licensed under a Creative Commons Attribution 3.0 Unported
|
||||||
|
License.
|
||||||
|
|
||||||
|
http://creativecommons.org/licenses/by/3.0/legalcode
|
||||||
|
|
||||||
|
========================
|
||||||
|
Return Selection Objects
|
||||||
|
========================
|
||||||
|
|
||||||
|
https://blueprints.launchpad.net/nova/+spec/return-selection-objects
|
||||||
|
|
||||||
|
In Queens, we will be changing what we return from select_destinations() in
|
||||||
|
order to both provide additional 'alternate' hosts for each requested instance
|
||||||
|
and also the allocation_request for building on each host. Returning this as an
|
||||||
|
unstructured chunk of data will be fragile and potentially confusing. It would
|
||||||
|
be far better to create an object to hold this data and make it accessible in a
|
||||||
|
simpler and documented way.
|
||||||
|
|
||||||
|
Problem description
|
||||||
|
===================
|
||||||
|
|
||||||
|
Before Queens, the scheduler's select_destinations() method returned a list,
|
||||||
|
containing a dictionary representing the selected host for each requested
|
||||||
|
instance. In Queens, we need to return much more information to the caller of
|
||||||
|
select_destinations(). We could attempt to return a list of HostDicts, which
|
||||||
|
represents the selected host as in the past, along with zero or more
|
||||||
|
'alternate' hosts that are in the same cell and also meet the requested
|
||||||
|
resources. Additionally, each of these will also be accompanied by a dictionary
|
||||||
|
for the allocation_request required to claim that host. The end result will be
|
||||||
|
a list, with one item per requested instance. Each item in that list will be a
|
||||||
|
list of 2-tuples of (HostState, allocation_request). The HostState is a simple
|
||||||
|
dict, but the allocation_request is itself a complex nested dict.
|
||||||
|
|
||||||
|
The result of these changes would mean that the data returned would be a
|
||||||
|
complex nested combination of dictionaries, lists, and tuples. This data
|
||||||
|
structure would be both difficult to understand how to use correctly, and
|
||||||
|
confusing to developers looking at the code for the first time (or even after a
|
||||||
|
period of being away from it). It is also unversioned, meaning it is impossible
|
||||||
|
to track and respond to future changes in a reliable manner.
|
||||||
|
|
||||||
|
Use Cases
|
||||||
|
---------
|
||||||
|
|
||||||
|
As an experienced Nova developer, I would like to be able to write code that
|
||||||
|
uses the information returned from select_destinations() without having to
|
||||||
|
decipher a complex data structure.
|
||||||
|
|
||||||
|
As a newcomer to the Nova codebase, I would like to be able to read code that
|
||||||
|
is clear so that I can work with it quicker and with more confidence that my
|
||||||
|
changes won't break something.
|
||||||
|
|
||||||
|
Proposed change
|
||||||
|
===============
|
||||||
|
|
||||||
|
We propose to create a new Selection object that would contain the data that
|
||||||
|
represents a single destination: both the host information as well as the
|
||||||
|
corresponding allocation_request needed for claiming. The host information,
|
||||||
|
which is currently in a dictionary containing hostname, nodename, and limits
|
||||||
|
keys, will now be stored as simple object fields along with the
|
||||||
|
allocation_request. Additionally, the compute_node_uuid field will be added, as
|
||||||
|
it would be useful to have this available in some of our allocation cleanup
|
||||||
|
tasks.
|
||||||
|
|
||||||
|
There is no need for a corresponding SelectionList object, as there is no need
|
||||||
|
for DB creation or retrieval. The select_destinations() method will return
|
||||||
|
simple Python lists of Selection objects. The Scheduler will return one list
|
||||||
|
of Selection objects for each requested instance, representing the selected
|
||||||
|
host as well as any alternates.
|
||||||
|
|
||||||
|
Alternatives
|
||||||
|
------------
|
||||||
|
|
||||||
|
We could cache the allocation_request data in placement, and simply return a
|
||||||
|
key along with the resource providers. When a claim needs to be made, the key
|
||||||
|
would be POSTed instead of the full allocation_request data, and Placement
|
||||||
|
would use the cached data to carry out the claim. This has the advantage that
|
||||||
|
nothing on the Nova side of things ever uses the data in the
|
||||||
|
allocation_request; to Nova, it's an opaque blob. The downside, of course, is
|
||||||
|
that Placement would have to handle the cache.
|
||||||
|
|
||||||
|
We could return the full allocation_request data to the scheduler, and then
|
||||||
|
handle the caching and key management on the Nova side. When a claim/unclaim is
|
||||||
|
needed, the allocation_request would be retrieved from this cache and POSTed to
|
||||||
|
placement. This alternative doesn't require any changes to placement, but
|
||||||
|
requires that both the API-level cell and all local cells have access to some
|
||||||
|
form of 'global ram' cache that is accessible across cells.
|
||||||
|
|
||||||
|
We could just return an unstructured bunch of Python data, and add a ton of
|
||||||
|
comments everywhere it is used in the hope that anyone looking at the code
|
||||||
|
would understand what each bit represents, and that every future change to the
|
||||||
|
data required would be able to be handled without versioning.
|
||||||
|
|
||||||
|
Data model impact
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
There will be no changes to any database schemas, but this will introduce a new
|
||||||
|
versioned object. This object will contain the following fields, along with
|
||||||
|
their types::
|
||||||
|
|
||||||
|
* compute_node_uuid: fields.UUIDField
|
||||||
|
* service_host: fields.StringField
|
||||||
|
* nodename: fields.StringField
|
||||||
|
* cell_uuid: fields.UUIDField
|
||||||
|
* numa_limits: fields.ObjectField("NUMATopologyLimits")
|
||||||
|
* allocation_request: fields.StringField
|
||||||
|
|
||||||
|
There isn't a good field type for the allocation_request value, as it is a
|
||||||
|
complex nested structure, so instead we'll store it as its JSON respresentation
|
||||||
|
in a StringField. The structure of an allocation_request, as described in this
|
||||||
|
spec[2], looks like::
|
||||||
|
|
||||||
|
"allocations": [
|
||||||
|
{
|
||||||
|
"resource_provider": {
|
||||||
|
"uuid": $COMPUTE_NODE1_UUID
|
||||||
|
},
|
||||||
|
"resources": {
|
||||||
|
"VCPU": $AMOUNT_REQUESTED_VCPU,
|
||||||
|
"MEMORY_MB": $AMOUNT_REQUESTED_MEMORY_MB
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resource_provider": {
|
||||||
|
"uuid": $SHARED_STORAGE_UUID
|
||||||
|
},
|
||||||
|
"resources": {
|
||||||
|
"DISK_GB": $AMOUNT_REQUESTED_DISK_GB
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
REST API impact
|
||||||
|
---------------
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
Security impact
|
||||||
|
---------------
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
Notifications impact
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
Other end user impact
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
Performance Impact
|
||||||
|
------------------
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
Other deployer impact
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
Developer impact
|
||||||
|
----------------
|
||||||
|
|
||||||
|
It will make life a little easier for anyone working with the Nova codebase by
|
||||||
|
not making them decipher complex data structures, but other than that, none.
|
||||||
|
|
||||||
|
|
||||||
|
Implementation
|
||||||
|
==============
|
||||||
|
|
||||||
|
Assignee(s)
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Primary assignee:
|
||||||
|
ed-leafe
|
||||||
|
|
||||||
|
Other contributors:
|
||||||
|
None
|
||||||
|
|
||||||
|
Work Items
|
||||||
|
----------
|
||||||
|
|
||||||
|
* Create the Selection object.
|
||||||
|
|
||||||
|
* Modify the scheduler's select_destinations() method to populate these objects
|
||||||
|
with the selected host info and return them.
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
============
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
|
||||||
|
Testing
|
||||||
|
=======
|
||||||
|
|
||||||
|
This is one part of the overall sweeping changes being made in Queens, and all
|
||||||
|
of it will have to be tested. The Selection object will need some basic tests,
|
||||||
|
but the bulk of the testing will be in the conductor to verify that it is
|
||||||
|
working with Selection objects for host selection, resource claiming, and
|
||||||
|
retries on build failures.
|
||||||
|
|
||||||
|
|
||||||
|
Documentation Impact
|
||||||
|
====================
|
||||||
|
|
||||||
|
The developer reference docs will need to be updated to document this new
|
||||||
|
object. The docs for the scheduler workflow will also need to be updated to
|
||||||
|
reflect these changes.
|
||||||
|
|
||||||
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
|
The initial problem was documented in a blog post[0], and was then discussed at
|
||||||
|
the Nova Scheduler subteam meeting[1], where this approach was agreed upon.
|
||||||
|
|
||||||
|
[0] https://blog.leafe.com/handling-unstructured-data/
|
||||||
|
[1] http://eavesdrop.openstack.org/meetings/nova_scheduler/2017/nova_scheduler.2017-08-28-14.00.log.html#l-140
|
||||||
|
[2] https://specs.openstack.org/openstack/nova-specs/specs/pike/approved/placement-allocation-requests.html
|
||||||
|
|
||||||
|
History
|
||||||
|
=======
|
||||||
|
|
||||||
|
.. list-table:: Revisions
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - Release Name
|
||||||
|
- Description
|
||||||
|
* - Queens
|
||||||
|
- Introduced
|
||||||
Reference in New Issue
Block a user