diff options
author | Dmitry Tantsur <dtantsur@protonmail.com> | 2019-09-19 14:21:58 +0200 |
---|---|---|
committer | Dmitry Tantsur <dtantsur@protonmail.com> | 2019-09-20 15:24:28 +0200 |
commit | b2834e66619c5f968389fa6ab1cf3e5f99cbafa3 (patch) | |
tree | fda99a4e472c26cb87dbb12d65b886f0d2f5eac2 /ironic/db | |
parent | 9fa39045dab1c3b401efac740d14a7e88c6c41f5 (diff) | |
download | ironic-b2834e66619c5f968389fa6ab1cf3e5f99cbafa3.tar.gz |
Allow retrying PXE boot if it takes too long
PXE is inherently unreliable and sometimes times out without an
obvious reason. It happens particularly often in resource constrained
environments, such as the CI. This change allows an operator to
set a timeout, after which the boot is retried again.
The _add_node_filters call had to be refactored to avoid hitting
the complexity limit.
Change-Id: I34a11f52e8e98e5b64f2d21f7190468a9e4b030d
Story: #2005167
Task: #29901
Diffstat (limited to 'ironic/db')
-rw-r--r-- | ironic/db/sqlalchemy/api.py | 57 |
1 files changed, 29 insertions, 28 deletions
diff --git a/ironic/db/sqlalchemy/api.py b/ironic/db/sqlalchemy/api.py index eee192c43..8ea75ba04 100644 --- a/ironic/db/sqlalchemy/api.py +++ b/ironic/db/sqlalchemy/api.py @@ -279,20 +279,28 @@ def _zip_matching(a, b, key): class Connection(api.Connection): """SqlAlchemy connection.""" + _NODE_QUERY_FIELDS = {'console_enabled', 'maintenance', 'driver', + 'resource_class', 'provision_state', 'uuid', 'id', + 'fault', 'conductor_group', 'owner'} + _NODE_IN_QUERY_FIELDS = {'%s_in' % field: field + for field in ('uuid', 'provision_state')} + _NODE_NON_NULL_FILTERS = {'associated': 'instance_uuid', + 'reserved': 'reservation', + 'with_power_state': 'power_state'} + _NODE_FILTERS = ({'chassis_uuid', 'reserved_by_any_of', + 'provisioned_before', 'inspection_started_before', + 'description_contains'} + | _NODE_QUERY_FIELDS + | set(_NODE_IN_QUERY_FIELDS) + | set(_NODE_NON_NULL_FILTERS)) + def __init__(self): pass def _validate_nodes_filters(self, filters): if filters is None: filters = dict() - supported_filters = {'console_enabled', 'maintenance', 'driver', - 'resource_class', 'provision_state', 'uuid', 'id', - 'chassis_uuid', 'associated', 'reserved', - 'reserved_by_any_of', 'provisioned_before', - 'inspection_started_before', 'fault', - 'conductor_group', 'owner', 'uuid_in', - 'with_power_state', 'description_contains'} - unsupported_filters = set(filters).difference(supported_filters) + unsupported_filters = set(filters).difference(self._NODE_FILTERS) if unsupported_filters: msg = _("SqlAlchemy API does not support " "filtering by %s") % ', '.join(unsupported_filters) @@ -301,26 +309,26 @@ class Connection(api.Connection): def _add_nodes_filters(self, query, filters): filters = self._validate_nodes_filters(filters) - for field in ['console_enabled', 'maintenance', 'driver', - 'resource_class', 'provision_state', 'uuid', 'id', - 'fault', 'conductor_group', 'owner']: + for field in self._NODE_QUERY_FIELDS: if field in filters: query = query.filter_by(**{field: filters[field]}) + for key, field in self._NODE_IN_QUERY_FIELDS.items(): + if key in filters: + query = query.filter( + getattr(models.Node, field).in_(filters[key])) + for key, field in self._NODE_NON_NULL_FILTERS.items(): + if key in filters: + column = getattr(models.Node, field) + if filters[key]: + query = query.filter(column != sql.null()) + else: + query = query.filter(column == sql.null()) + if 'chassis_uuid' in filters: # get_chassis_by_uuid() to raise an exception if the chassis # is not found chassis_obj = self.get_chassis_by_uuid(filters['chassis_uuid']) query = query.filter_by(chassis_id=chassis_obj.id) - if 'associated' in filters: - if filters['associated']: - query = query.filter(models.Node.instance_uuid != sql.null()) - else: - query = query.filter(models.Node.instance_uuid == sql.null()) - if 'reserved' in filters: - if filters['reserved']: - query = query.filter(models.Node.reservation != sql.null()) - else: - query = query.filter(models.Node.reservation == sql.null()) if 'reserved_by_any_of' in filters: query = query.filter(models.Node.reservation.in_( filters['reserved_by_any_of'])) @@ -334,13 +342,6 @@ class Connection(api.Connection): - (datetime.timedelta( seconds=filters['inspection_started_before']))) query = query.filter(models.Node.inspection_started_at < limit) - if 'uuid_in' in filters: - query = query.filter(models.Node.uuid.in_(filters['uuid_in'])) - if 'with_power_state' in filters: - if filters['with_power_state']: - query = query.filter(models.Node.power_state != sql.null()) - else: - query = query.filter(models.Node.power_state == sql.null()) if 'description_contains' in filters: keyword = filters['description_contains'] if keyword is not None: |