Remove direct mapping from API -> DB
In order to complete the eventlet migration, we need to be able to use the indirection_api surface to be able to disjoint the API surface from the message bus, so we're not fighting between processes for database locks. Previously, the calls were directly routed directly to the database layer to streamline performance. This attachment allows the calls to run through the indirection layer to the object, and return the data to the caller. As a result, API RPC versions are incremented. Change-Id: I7358ac2a70198c78a0a9ba48511fc1289c64294f Signed-off-by: Julia Kreger <juliaashleykreger@gmail.com>
This commit is contained in:
@@ -446,7 +446,8 @@ class AllocationsController(pecan.rest.RestController):
|
||||
# if any. The result is processes authenticating with system
|
||||
# scope will not be impacted, where as project scoped requests
|
||||
# will need additional authorization.
|
||||
converted = api.request.dbapi.check_node_list(
|
||||
converted = objects.Allocation.check_node_list(
|
||||
context,
|
||||
allocation['candidate_nodes'],
|
||||
project=owner)
|
||||
except exception.NodeNotFound as exc:
|
||||
|
||||
@@ -26,7 +26,7 @@ from ironic.common import exception
|
||||
from ironic.common.i18n import _
|
||||
from ironic.common import metrics_utils
|
||||
from ironic.drivers import base as driver_base
|
||||
|
||||
from ironic import objects
|
||||
|
||||
METRICS = metrics_utils.get_metrics_logger(__name__)
|
||||
|
||||
@@ -130,8 +130,10 @@ def convert_with_links(name, hosts, detail=False, interface_info=None,
|
||||
if detail:
|
||||
if interface_info is None:
|
||||
# TODO(jroll) objectify this
|
||||
interface_info = (api.request.dbapi
|
||||
.list_hardware_type_interfaces([name]))
|
||||
interface_info = (objects.Conductor
|
||||
.list_hardware_type_interfaces_dict(
|
||||
api.request.context,
|
||||
[name]))
|
||||
for iface_type in driver_base.ALL_INTERFACES:
|
||||
default = None
|
||||
enabled = set()
|
||||
@@ -191,7 +193,8 @@ def list_convert_with_links(hardware_types, detail=False, fields=None):
|
||||
# This is checked in Driver.convert_with_links(), however also
|
||||
# checking here can save us a DB query.
|
||||
if api_utils.allow_dynamic_drivers() and detail:
|
||||
iface_info = api.request.dbapi.list_hardware_type_interfaces(
|
||||
iface_info = objects.Conductor.list_hardware_type_interfaces_dict(
|
||||
api.request.context,
|
||||
list(hardware_types))
|
||||
else:
|
||||
iface_info = []
|
||||
@@ -348,7 +351,8 @@ class DriversController(rest.RestController):
|
||||
'if specified.'))
|
||||
|
||||
if type is None or type == 'dynamic':
|
||||
hw_type_dict = api.request.dbapi.get_active_hardware_type_dict()
|
||||
hw_type_dict = objects.Conductor.get_active_hardware_type_dict(
|
||||
api.request.context)
|
||||
else:
|
||||
# NOTE(dtantsur): we don't support classic drivers starting with
|
||||
# the Rocky release.
|
||||
@@ -369,7 +373,8 @@ class DriversController(rest.RestController):
|
||||
|
||||
_check_allow_driver_fields(fields)
|
||||
|
||||
hw_type_dict = api.request.dbapi.get_active_hardware_type_dict()
|
||||
hw_type_dict = objects.Conductor.get_active_hardware_type_dict(
|
||||
api.request.context)
|
||||
for name, hosts in hw_type_dict.items():
|
||||
if name == driver_name:
|
||||
return convert_with_links(name, list(hosts),
|
||||
|
||||
@@ -21,6 +21,7 @@ from ironic.api.schemas.v1 import shard as schema
|
||||
from ironic.api import validation
|
||||
from ironic.common.i18n import _
|
||||
from ironic.common import metrics_utils
|
||||
from ironic import objects
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
@@ -47,7 +48,7 @@ class ShardController(pecan.rest.RestController):
|
||||
api_utils.check_policy('baremetal:shards:get')
|
||||
|
||||
return {
|
||||
'shards': api.request.dbapi.get_shard_list(),
|
||||
'shards': objects.Conductor.get_shard_list(api.request.context),
|
||||
}
|
||||
|
||||
@METRICS.timer('ShardController.get_one')
|
||||
|
||||
@@ -899,12 +899,12 @@ RELEASE_MAPPING = {
|
||||
'api': '1.100',
|
||||
'rpc': '1.61',
|
||||
'objects': {
|
||||
'Allocation': ['1.1'],
|
||||
'Allocation': ['1.2', '1.1'],
|
||||
'BIOSSetting': ['1.1'],
|
||||
'Node': ['1.41'],
|
||||
'NodeHistory': ['1.0'],
|
||||
'NodeInventory': ['1.0'],
|
||||
'Conductor': ['1.4'],
|
||||
'Conductor': ['1.5', '1.4'],
|
||||
'Chassis': ['1.3'],
|
||||
'Deployment': ['1.0'],
|
||||
'DeployTemplate': ['1.1'],
|
||||
|
||||
@@ -27,7 +27,8 @@ from ironic.objects import notification
|
||||
class Allocation(base.IronicObject, object_base.VersionedObjectDictCompat):
|
||||
# Version 1.0: Initial version
|
||||
# Version 1.1: Add owner field
|
||||
VERSION = '1.1'
|
||||
# Version 1.2: Add remotable method check_node_list
|
||||
VERSION = '1.2'
|
||||
|
||||
dbapi = dbapi.get_instance()
|
||||
|
||||
@@ -272,6 +273,17 @@ class Allocation(base.IronicObject, object_base.VersionedObjectDictCompat):
|
||||
self.obj_refresh(current)
|
||||
self.obj_reset_changes()
|
||||
|
||||
@base.remotable_classmethod
|
||||
def check_node_list(cls, context, candidate_nodes, project):
|
||||
"""Provides a pass-through to the database for allocation node lists.
|
||||
|
||||
Calls the database directly as opposed to allowing the API to directly
|
||||
call the database when an indirection API is set.
|
||||
"""
|
||||
return cls.dbapi.check_node_list(
|
||||
candidate_nodes,
|
||||
project=project)
|
||||
|
||||
|
||||
@base.IronicObjectRegistry.register
|
||||
class AllocationCRUDNotification(notification.NotificationBase):
|
||||
|
||||
@@ -26,6 +26,8 @@ from ironic.objects import fields as object_fields
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
remotable_classmethod = object_base.remotable_classmethod
|
||||
|
||||
|
||||
def max_version(versions):
|
||||
"""Return the maximum version in the list.
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import datetime
|
||||
|
||||
from oslo_versionedobjects import base as object_base
|
||||
|
||||
from ironic.common.i18n import _
|
||||
@@ -32,7 +34,10 @@ class Conductor(base.IronicObject, object_base.VersionedObjectDictCompat):
|
||||
# unregister_all_hardware_interfaces()
|
||||
# Version 1.3: Add conductor_group field.
|
||||
# Version 1.4: Add online field.
|
||||
VERSION = '1.4'
|
||||
# Version 1.5: Add new remotable methods
|
||||
# get_shard_list, list_hardware_type_interfaces,
|
||||
# and get_active_hardware_type_dict
|
||||
VERSION = '1.5'
|
||||
|
||||
dbapi = db_api.get_instance()
|
||||
|
||||
@@ -172,3 +177,54 @@ class Conductor(base.IronicObject, object_base.VersionedObjectDictCompat):
|
||||
def unregister_all_hardware_interfaces(self):
|
||||
"""Unregister all hardware interfaces for this conductor."""
|
||||
self.dbapi.unregister_conductor_hardware_interfaces(self.id)
|
||||
|
||||
@base.remotable_classmethod
|
||||
def get_active_hardware_type_dict(cls, context, use_groups=False):
|
||||
"""Provides a hardware type list as it relates to the conductors.
|
||||
|
||||
This method provides a pass-through call mechanism on an attached
|
||||
object for insight into the state of hardware managers by conductors
|
||||
and does so as a direct call for compatibility with lightweight
|
||||
API method.
|
||||
"""
|
||||
return cls.dbapi.get_active_hardware_type_dict(use_groups=use_groups)
|
||||
|
||||
@base.remotable_classmethod
|
||||
def list_hardware_type_interfaces_dict(cls, context, names):
|
||||
"""Provides a list of hardware type interface names from conductors.
|
||||
|
||||
This method provides a pass-through call mechanism on an object as
|
||||
opposed to direct API call functionality.
|
||||
"""
|
||||
# NOTE(TheJulia): SQLAlchemy hands us a hybrid object which also
|
||||
# works like a dictionary, and the consumer of this call treats
|
||||
# it as such but we can't hand it across the message bus as a
|
||||
# DB object.
|
||||
db_resp = cls.dbapi.list_hardware_type_interfaces(names)
|
||||
resp = []
|
||||
for row in db_resp:
|
||||
entry = {}
|
||||
for col_key in row.keys():
|
||||
if isinstance(row[col_key], datetime.datetime):
|
||||
# SQLAclchemy hands response objects with nested
|
||||
# datetime objects, so they need to be converted
|
||||
# before trying to serialize as opposed before
|
||||
# sending the API response out.
|
||||
entry[col_key] = row[col_key].isoformat()
|
||||
else:
|
||||
entry[col_key] = row[col_key]
|
||||
resp.append(entry)
|
||||
return resp
|
||||
|
||||
@base.remotable_classmethod
|
||||
def get_shard_list(cls, context):
|
||||
"""Provides a shard list as it relates to conductors.
|
||||
|
||||
This method provides a pass-through all mechanism on an attached
|
||||
object for insight into the list of represented shards in a deployment
|
||||
which is sourced in the database combined with runtime configurations.
|
||||
The primary prupose of this being be lightweight and enable
|
||||
indirection_api call usage instead of trying to directly invoke the
|
||||
database.
|
||||
"""
|
||||
return cls.dbapi.get_shard_list()
|
||||
|
||||
@@ -680,7 +680,7 @@ expected_object_fingerprints = {
|
||||
'Chassis': '1.3-d656e039fd8ae9f34efc232ab3980905',
|
||||
'Port': '1.13-f79db5cc15189d3e8b257db582b2329e',
|
||||
'Portgroup': '1.5-df4dc15967f67114d51176a98a901a83',
|
||||
'Conductor': '1.4-a9703208fdab5fab8f1cec420be1b4a7',
|
||||
'Conductor': '1.5-c241d0c83c05c263b12c9b0289995462',
|
||||
'EventType': '1.1-aa2ba1afd38553e3880c267404e8d370',
|
||||
'NotificationPublisher': '1.0-51a09397d6c0687771fb5be9a999605d',
|
||||
'NodePayload': '1.17-4022bb737b058d426a7ff878b1875e5c',
|
||||
@@ -712,7 +712,7 @@ expected_object_fingerprints = {
|
||||
'TraitList': '1.0-33a2e1bb91ad4082f9f63429b77c1244',
|
||||
'BIOSSetting': '1.1-1137db88675a4e2d7f7bcc3a0d52345a',
|
||||
'BIOSSettingList': '1.0-33a2e1bb91ad4082f9f63429b77c1244',
|
||||
'Allocation': '1.1-38937f2854722f1057ec667b12878708',
|
||||
'Allocation': '1.2-9aae5cc874a292af10ba08918ba21b13',
|
||||
'AllocationCRUDNotification': '1.0-59acc533c11d306f149846f922739c15',
|
||||
'AllocationCRUDPayload': '1.1-3c8849932b80380bb96587ff62e8f087',
|
||||
'DeployTemplate': '1.1-4e30c8e9098595e359bb907f095bf1a9',
|
||||
|
||||
Reference in New Issue
Block a user