Skip to content

Commit f521f4d

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Provider Config File: Enable loading and merging of provider configs"
2 parents 197dac3 + 260713d commit f521f4d

File tree

8 files changed

+545
-3
lines changed

8 files changed

+545
-3
lines changed

doc/source/admin/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ instance for these kind of workloads.
113113
ports-with-resource-requests
114114
virtual-persistent-memory
115115
emulated-tpm
116+
managing-resource-providers
116117

117118

118119
Additional guides
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
==============================================
2+
Managing Resource Providers Using Config Files
3+
==============================================
4+
5+
In order to facilitate management of resource provider information in the
6+
Placement API, Nova provides `a method`__ for admins to add custom inventory
7+
and traits to resource providers using YAML files.
8+
9+
__ https://specs.openstack.org/openstack/nova-specs/specs/ussuri/approved/provider-config-file.html
10+
11+
.. note::
12+
13+
Only ``CUSTOM_*`` resource classes and traits may be managed this way.
14+
15+
Placing Files
16+
-------------
17+
18+
Nova-compute will search for ``*.yaml`` files in the path specified in
19+
:oslo.config:option:`compute.provider_config_location`. These files will be
20+
loaded and validated for errors on nova-compute startup. If there are any
21+
errors in the files, nova-compute will fail to start up.
22+
23+
Administrators should ensure that provider config files have appropriate
24+
permissions and ownership. See the `specification`__ and `admin guide`__
25+
for more details.
26+
27+
__ https://specs.openstack.org/openstack/nova-specs/specs/ussuri/approved/provider-config-file.html
28+
__ https://docs.openstack.org/nova/latest/admin/managing-resource-providers.html
29+
30+
.. note::
31+
32+
The files are loaded once at nova-compute startup and any changes or new
33+
files will not be recognized until the next nova-compute startup.
34+
35+
Examples
36+
--------
37+
38+
Resource providers to target can be identified by either UUID or name. In
39+
addition, the value ``$COMPUTE_NODE`` can be used in the UUID field to
40+
identify all nodes managed by the service.
41+
42+
If an entry does not include any additional inventory or traits, it will be
43+
logged at load time but otherwise ignored. In the case of a resource provider
44+
being identified by both ``$COMPUTE_NODE`` and individual UUID/name, the
45+
values in the ``$COMPUTE_NODE`` entry will be ignored for *that provider* only
46+
if the explicit entry includes inventory or traits.
47+
48+
.. note::
49+
50+
In the case that a resource provider is identified more than once by
51+
explicit UUID/name, the nova-compute service will fail to start. This
52+
is a global requirement across all supplied ``provider.yaml`` files.
53+
54+
.. code-block:: yaml
55+
56+
meta:
57+
schema_version: '1.0'
58+
providers:
59+
- identification:
60+
name: 'EXAMPLE_RESOURCE_PROVIDER'
61+
# Additional valid identification examples:
62+
# uuid: '$COMPUTE_NODE'
63+
# uuid: '5213b75d-9260-42a6-b236-f39b0fd10561'
64+
inventories:
65+
additional:
66+
- CUSTOM_EXAMPLE_RESOURCE_CLASS:
67+
total: 100
68+
reserved: 0
69+
min_unit: 1
70+
max_unit: 10
71+
step_size: 1
72+
allocation_ratio: 1.0
73+
traits:
74+
additional:
75+
- 'CUSTOM_EXAMPLE_TRAIT'
76+
77+
Schema Example
78+
--------------
79+
.. code-block:: yaml
80+
81+
type: object
82+
properties:
83+
# This property is used to track where the provider.yaml file originated.
84+
# It is reserved for internal use and should never be set in a provider.yaml
85+
# file supplied by an end user.
86+
__source_file:
87+
not: {}
88+
meta:
89+
type: object
90+
properties:
91+
# Version ($Major, $minor) of the schema must successfully parse
92+
# documents conforming to ($Major, 0..N). Any breaking schema change
93+
# (e.g. removing fields, adding new required fields, imposing a stricter
94+
# pattern on a value, etc.) must bump $Major.
95+
schema_version:
96+
type: string
97+
pattern: '^1\.([0-9]|[1-9][0-9]+)$'
98+
required:
99+
- schema_version
100+
additionalProperties: true
101+
providers:
102+
type: array
103+
items:
104+
type: object
105+
properties:
106+
identification:
107+
$ref: '#/provider_definitions/provider_identification'
108+
inventories:
109+
$ref: '#/provider_definitions/provider_inventories'
110+
traits:
111+
$ref: '#/provider_definitions/provider_traits'
112+
required:
113+
- identification
114+
additionalProperties: true
115+
required:
116+
- meta
117+
additionalProperties: true
118+
119+
provider_definitions:
120+
provider_identification:
121+
# Identify a single provider to configure. Exactly one identification
122+
# method should be used. Currently `uuid` or `name` are supported, but
123+
# future versions may support others.
124+
# The uuid can be set to the sentinel value `$COMPUTE_NODE` which will
125+
# cause the consuming compute service to apply the configuration to
126+
# to all compute node root providers it manages that are not otherwise
127+
# specified using a uuid or name.
128+
type: object
129+
properties:
130+
uuid:
131+
oneOf:
132+
# TODO(sean-k-mooney): replace this with type uuid when we can depend
133+
# on a version of the jsonschema lib that implements draft 8 or later
134+
# of the jsonschema spec.
135+
- type: string
136+
pattern: '^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$'
137+
- type: string
138+
const: '$COMPUTE_NODE'
139+
name:
140+
type: string
141+
minLength: 1
142+
# This introduces the possibility of an unsupported key name being used to
143+
# get by schema validation, but is necessary to support forward
144+
# compatibility with new identification methods. This should be checked
145+
# after schema validation.
146+
minProperties: 1
147+
maxProperties: 1
148+
additionalProperties: false
149+
provider_inventories:
150+
# Allows the admin to specify various adjectives to create and manage
151+
# providers' inventories. This list of adjectives can be extended in the
152+
# future as the schema evolves to meet new use cases. As of v1.0, only one
153+
# adjective, `additional`, is supported.
154+
type: object
155+
properties:
156+
additional:
157+
type: array
158+
items:
159+
patternProperties:
160+
# Allows any key name matching the resource class pattern,
161+
# check to prevent conflicts with virt driver owned resouces classes
162+
# will be done after schema validation.
163+
^[A-Z0-9_]{1,255}$:
164+
type: object
165+
properties:
166+
# Any optional properties not populated will be given a default value by
167+
# placement. If overriding a pre-existing provider values will not be
168+
# preserved from the existing inventory.
169+
total:
170+
type: integer
171+
reserved:
172+
type: integer
173+
min_unit:
174+
type: integer
175+
max_unit:
176+
type: integer
177+
step_size:
178+
type: integer
179+
allocation_ratio:
180+
type: number
181+
required:
182+
- total
183+
# The defined properties reflect the current placement data
184+
# model. While defining those in the schema and not allowing
185+
# additional properties means we will need to bump the schema
186+
# version if they change, that is likely to be part of a large
187+
# change that may have other impacts anyway. The benefit of
188+
# stricter validation of property names outweighs the (small)
189+
# chance of having to bump the schema version as described above.
190+
additionalProperties: false
191+
# This ensures only keys matching the pattern above are allowed
192+
additionalProperties: false
193+
additionalProperties: true
194+
provider_traits:
195+
# Allows the admin to specify various adjectives to create and manage
196+
# providers' traits. This list of adjectives can be extended in the
197+
# future as the schema evolves to meet new use cases. As of v1.0, only one
198+
# adjective, `additional`, is supported.
199+
type: object
200+
properties:
201+
additional:
202+
type: array
203+
items:
204+
# Allows any value matching the trait pattern here, additional
205+
# validation will be done after schema validation.
206+
type: string
207+
pattern: '^[A-Z0-9_]{1,255}$'
208+
additionalProperties: true
209+
210+
.. note::
211+
212+
When creating a ``provider.yaml`` config file it is recommended to use the
213+
schema provided by nova to validate the config using a simple jsonschema
214+
validator rather than starting the nova compute agent to enable faster
215+
iteration.
216+

nova/compute/resource_tracker.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
from nova.compute import claims
3232
from nova.compute import monitors
33+
from nova.compute import provider_config
3334
from nova.compute import stats as compute_stats
3435
from nova.compute import task_states
3536
from nova.compute import utils as compute_utils
@@ -112,6 +113,11 @@ def __init__(self, host, driver, reportclient=None):
112113
# and value of this sub-dict is a set of Resource obj
113114
self.assigned_resources = collections.defaultdict(
114115
lambda: collections.defaultdict(set))
116+
# Retrieves dict of provider config data. This can fail with
117+
# nova.exception.ProviderConfigException if invalid or conflicting
118+
# data exists in the provider config files.
119+
self.provider_configs = provider_config.get_provider_configs(
120+
CONF.compute.provider_config_location)
115121
# Set of ids for providers identified in provider config files that
116122
# are not found on the provider tree. These are tracked to facilitate
117123
# smarter logging.
@@ -1155,6 +1161,9 @@ def _update_to_placement(self, context, compute_node, startup):
11551161

11561162
self.provider_tree = prov_tree
11571163

1164+
# This merges in changes from the provider config files loaded in init
1165+
self._merge_provider_configs(self.provider_configs, prov_tree)
1166+
11581167
# Flush any changes. If we processed ReshapeNeeded above, allocs is not
11591168
# None, and this will hit placement's POST /reshaper route.
11601169
self.reportclient.update_from_provider_tree(context, prov_tree,
@@ -1714,6 +1723,7 @@ def _merge_provider_configs(self, provider_configs, provider_tree):
17141723
:param provider_tree: The provider tree to be updated in place
17151724
"""
17161725
processed_providers = {}
1726+
provider_custom_traits = {}
17171727
for uuid_or_name, provider_data in provider_configs.items():
17181728
additional_traits = provider_data.get(
17191729
"traits", {}).get("additional", [])
@@ -1758,10 +1768,23 @@ def _merge_provider_configs(self, provider_configs, provider_tree):
17581768
'current_uuid': current_uuid
17591769
}
17601770
)
1761-
processed_providers[current_uuid] = source_file_name
1771+
1772+
# NOTE(sean-k-mooney): since each provider should be processed
1773+
# at most once if a provider has custom traits they were
1774+
# set either in previous iteration, the virt driver or via the
1775+
# the placement api. As a result we must ignore them when
1776+
# checking for duplicate traits so we construct a set of the
1777+
# existing custom traits.
1778+
if current_uuid not in provider_custom_traits:
1779+
provider_custom_traits[current_uuid] = {
1780+
trait for trait in provider.traits
1781+
if trait.startswith('CUSTOM')
1782+
}
1783+
existing_custom_traits = provider_custom_traits[current_uuid]
17621784

17631785
if additional_traits:
17641786
intersect = set(provider.traits) & set(additional_traits)
1787+
intersect -= existing_custom_traits
17651788
if intersect:
17661789
invalid = ','.join(intersect)
17671790
raise ValueError(_(
@@ -1797,6 +1820,8 @@ def _merge_provider_configs(self, provider_configs, provider_tree):
17971820
provider_tree.update_inventory(
17981821
provider.uuid, merged_inventory)
17991822

1823+
processed_providers[current_uuid] = source_file_name
1824+
18001825
def _get_providers_to_update(self, uuid_or_name, provider_tree,
18011826
source_file):
18021827
"""Identifies the providers to be updated.

nova/conf/compute.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,19 @@
967967
968968
* -1 means unlimited
969969
* Any integer >= 0 represents the maximum allowed
970+
"""),
971+
cfg.StrOpt('provider_config_location',
972+
default='/etc/nova/provider_config/',
973+
help="""
974+
Location of YAML files containing resource provider configuration data.
975+
976+
These files allow the operator to specify additional custom inventory and
977+
traits to assign to one or more resource providers.
978+
979+
Additional documentation is available here:
980+
981+
https://docs.openstack.org/nova/latest/admin/managing-resource-providers.html
982+
970983
"""),
971984
]
972985

0 commit comments

Comments
 (0)