From 67da8d8c31e301171e3c478a5b3e2d1e15407e25 Mon Sep 17 00:00:00 2001 From: Julia Kreger Date: Mon, 4 Aug 2025 10:22:34 -0700 Subject: [PATCH] Optional indirection API use Adds the capability to utilize the indirection API model. The vast majority of this change is the removal of legacy comments and the swap of decorators on object methods to allow the Versioned Objects Indirection API to route the calls upon objects through the RPC layer to the conductor. In order to make these calls occur, we need to also send along a context, which is required to call the RPC layer, which is fine. Original tests still work in that API surface calls still ultimately trigger DB API calls in the backend, thus test changes are actually minimal, similar to very slight changes in trait retrieval as well. In that we really can't nest objects across the indirection layer. Change-Id: Ia161fef67b8a116fdf7cad9b2e559ba75263e196 Signed-off-by: Julia Kreger --- ironic/api/controllers/v1/node.py | 8 +- ironic/api/hooks.py | 12 ++- ironic/api/wsgi.py | 6 ++ ironic/command/api.py | 8 ++ ironic/command/novncproxy.py | 8 ++ ironic/command/pxe_filter.py | 8 ++ ironic/command/singleprocess.py | 8 ++ ironic/common/hash_ring.py | 11 ++- ironic/common/release_mappings.py | 36 ++++----- ironic/conductor/manager.py | 5 ++ ironic/conf/default.py | 8 ++ ironic/objects/allocation.py | 53 +++---------- ironic/objects/base.py | 1 + ironic/objects/bios.py | 58 +++----------- ironic/objects/chassis.py | 47 +++-------- ironic/objects/conductor.py | 37 +++------ ironic/objects/deploy_template.py | 57 +++---------- ironic/objects/deployment.py | 36 ++------- ironic/objects/firmware.py | 12 ++- ironic/objects/indirection.py | 3 + ironic/objects/inspection_rule.py | 26 ++---- ironic/objects/node.py | 79 +++++-------------- ironic/objects/node_history.py | 41 ++-------- ironic/objects/node_inventory.py | 7 +- ironic/objects/port.py | 71 ++++------------- ironic/objects/portgroup.py | 65 +++------------ ironic/objects/runbook.py | 17 ++-- ironic/objects/trait.py | 50 +++--------- ironic/objects/volume_connector.py | 53 +++---------- ironic/objects/volume_target.py | 59 +++----------- .../tests/unit/conductor/test_base_manager.py | 5 +- ironic/tests/unit/db/test_bios_settings.py | 4 +- .../tests/unit/db/test_firmware_component.py | 2 +- ironic/tests/unit/db/test_nodes.py | 2 +- ironic/tests/unit/objects/test_bios.py | 4 +- ironic/tests/unit/objects/test_objects.py | 40 +++++----- ironic/tests/unit/objects/test_trait.py | 4 +- .../notes/remotable-api-92d7b9bc7e843cd4.yaml | 23 ++++++ 38 files changed, 338 insertions(+), 636 deletions(-) create mode 100644 releasenotes/notes/remotable-api-92d7b9bc7e843cd4.yaml diff --git a/ironic/api/controllers/v1/node.py b/ironic/api/controllers/v1/node.py index 53f95a883fd..b90d119b52a 100644 --- a/ironic/api/controllers/v1/node.py +++ b/ironic/api/controllers/v1/node.py @@ -1008,7 +1008,9 @@ class NodeStatesController(rest.RestController): policy_name='baremetal:runbook:use', runbook_ident=runbook) - node_traits = rpc_node.traits.get_trait_names() or [] + traits = objects.TraitList.get_by_node_id(api.request.context, + rpc_node.id) + node_traits = traits.get_trait_names() or [] if rpc_runbook.name not in node_traits: msg = (_('This runbook has not been approved for ' 'use on this node %s. Please ask an administrator ' @@ -1649,7 +1651,9 @@ def node_convert_with_links(rpc_node, fields=None, sanitize=True): fields=_get_fields_for_node_query(fields)) if node.get('traits') is not None: - node['traits'] = rpc_node.traits.get_trait_names() + traits = objects.TraitList.get_by_node_id(api.request.context, + rpc_node.id) + node['traits'] = traits.get_trait_names() if (api_utils.allow_expose_conductors() and (fields is None or 'conductor' in fields)): diff --git a/ironic/api/hooks.py b/ironic/api/hooks.py index 547958fe8ca..62acf1da7a4 100644 --- a/ironic/api/hooks.py +++ b/ironic/api/hooks.py @@ -38,6 +38,8 @@ ID_FORMAT = (r'^req-[a-f0-9]{8}-[a-f0-9]{4}-' # a ton of extra overhead. DBAPI = dbapi.get_instance() +CONF = cfg.CONF + def policy_deprecation_check(): global CHECKED_DEPRECATED_POLICY_ARGS @@ -80,8 +82,16 @@ class ConfigHook(hooks.PecanHook): class DBHook(hooks.PecanHook): """Attach the dbapi object to the request so controllers can get to it.""" + # NOTE(TheJulia): This hook is deprecated, and should be expected to be + # removed after the 2026.2 Ironic release. def before(self, state): - state.request.dbapi = DBAPI + if CONF.rpc_transport == 'none' or CONF.use_rpc_for_database: + # If the transport is disabled, the request is not to use + # the database, and as such it doesn't need to be attached + # to the request. + state.request.dbapi = None + else: + state.request.dbapi = DBAPI def after(self, state): # Explicitly set to None since we don't need the DB connection diff --git a/ironic/api/wsgi.py b/ironic/api/wsgi.py index bf98de90fb1..039ef3ccd67 100644 --- a/ironic/api/wsgi.py +++ b/ironic/api/wsgi.py @@ -19,6 +19,8 @@ from oslo_log import log from ironic.api import app from ironic.common import i18n from ironic.common import service +from ironic.objects import base as objects_base +from ironic.objects import indirection CONF = cfg.CONF @@ -32,6 +34,10 @@ def initialize_wsgi_app(argv=sys.argv): service.prepare_command(argv) service.ensure_rpc_transport() + if CONF.rpc_transport in ['local', 'none'] or CONF.use_rpc_for_database: + objects_base.IronicObject.indirection_api = \ + indirection.IronicObjectIndirectionAPI() + LOG.debug("Configuration:") CONF.log_opt_values(LOG, log.DEBUG) diff --git a/ironic/command/api.py b/ironic/command/api.py index b017ee9e1e3..c4eb7f265d9 100644 --- a/ironic/command/api.py +++ b/ironic/command/api.py @@ -24,6 +24,8 @@ from oslo_log import log from ironic.common import service as ironic_service from ironic.common import wsgi_service +from ironic.objects import base as objects_base +from ironic.objects import indirection CONF = cfg.CONF @@ -46,6 +48,12 @@ def main(): ironic_service.prepare_service('ironic_api', sys.argv) ironic_service.ensure_rpc_transport() + # Sets the indirection API to direct API calls for objects across the + # RPC layer. + if CONF.rpc_transport in ['local', 'none'] or CONF.use_rpc_for_database: + objects_base.IronicObject.indirection_api = \ + indirection.IronicObjectIndirectionAPI() + # Build and start the WSGI app launcher = ironic_service.process_launcher() server = wsgi_service.WSGIService('ironic_api', CONF.api.enable_ssl_api) diff --git a/ironic/command/novncproxy.py b/ironic/command/novncproxy.py index 41c6cd0cd3f..05a2e4a1095 100644 --- a/ironic/command/novncproxy.py +++ b/ironic/command/novncproxy.py @@ -26,6 +26,8 @@ import oslo_middleware.cors as cors_middleware from ironic.common import exception from ironic.common import service as ironic_service from ironic.console import novncproxy_service +from ironic.objects import base as objects_base +from ironic.objects import indirection CONF = cfg.CONF @@ -45,6 +47,12 @@ def main(): raise exception.ConfigInvalid("To allow this service to start, set " "[vnc]enabled = True") + # Sets the indirection API to direct API calls for objects across the + # RPC layer. + if CONF.rpc_transport in ['local', 'none'] or CONF.use_rpc_for_database: + objects_base.IronicObject.indirection_api = \ + indirection.IronicObjectIndirectionAPI() + # Build and start the websocket proxy launcher = ironic_service.process_launcher(no_fork=True) server = novncproxy_service.NoVNCProxyService() diff --git a/ironic/command/pxe_filter.py b/ironic/command/pxe_filter.py index ad48a9c0fbb..f29c4a01d4b 100644 --- a/ironic/command/pxe_filter.py +++ b/ironic/command/pxe_filter.py @@ -18,6 +18,8 @@ from oslo_service import service from ironic.common import rpc_service from ironic.common import service as ironic_service +from ironic.objects import base as objects_base +from ironic.objects import indirection CONF = cfg.CONF LOG = log.getLogger(__name__) @@ -56,6 +58,12 @@ def main(): "rpc_transport = json-rpc. Please use another " "RPC transport.") + # Sets the indirection API to direct API calls for objects across the + # RPC layer. + if CONF.rpc_transport in ['local', 'none'] or CONF.use_rpc_for_database: + objects_base.IronicObject.indirection_api = \ + indirection.IronicObjectIndirectionAPI() + mgr = RPCService( CONF.host, 'ironic.pxe_filter.service', 'PXEFilterManager') diff --git a/ironic/command/singleprocess.py b/ironic/command/singleprocess.py index 4f13c1a1293..f2d37a5b252 100644 --- a/ironic/command/singleprocess.py +++ b/ironic/command/singleprocess.py @@ -23,6 +23,8 @@ from ironic.common import wsgi_service from ironic.conductor import local_rpc from ironic.conductor import rpc_service from ironic.console import novncproxy_service +from ironic.objects import base as objects_base +from ironic.objects import indirection CONF = cfg.CONF @@ -55,6 +57,12 @@ def main(): conductor_cmd.issue_startup_warnings(CONF) launcher.launch_service(mgr) + # Sets the indirection API to direct API calls for objects across the + # RPC layer. + if CONF.rpc_transport in ['local', 'none'] or CONF.use_rpc_for_database: + objects_base.IronicObject.indirection_api = \ + indirection.IronicObjectIndirectionAPI() + wsgi = wsgi_service.WSGIService('ironic_api', CONF.api.enable_ssl_api) launcher.launch_service(wsgi) diff --git a/ironic/common/hash_ring.py b/ironic/common/hash_ring.py index fab102b0e7a..4ba6150c2c2 100644 --- a/ironic/common/hash_ring.py +++ b/ironic/common/hash_ring.py @@ -19,12 +19,12 @@ import time from oslo_log import log from tooz import hashring +from ironic.common import context from ironic.common import exception from ironic.common.i18n import _ from ironic.common import utils from ironic.conf import CONF -from ironic.db import api as dbapi - +from ironic import objects LOG = log.getLogger(__name__) @@ -34,7 +34,6 @@ class HashRingManager(object): _lock = threading.Lock() def __init__(self, use_groups=True, cache=True): - self.dbapi = dbapi.get_instance() self.use_groups = use_groups self.cache = cache @@ -68,7 +67,11 @@ class HashRingManager(object): def _load_hash_rings(self): rings = {} - d2c = self.dbapi.get_active_hardware_type_dict( + # NOTE(TheJulia): Do not use the dbapi interface directly + # as hash_ring code is common code with the API, and want + # the overall flow respected. + d2c = objects.Conductor.get_active_hardware_type_dict( + context.get_admin_context(), use_groups=self.use_groups) for driver_name, hosts in d2c.items(): diff --git a/ironic/common/release_mappings.py b/ironic/common/release_mappings.py index 8c424dee41e..36a0bdb6210 100644 --- a/ironic/common/release_mappings.py +++ b/ironic/common/release_mappings.py @@ -899,24 +899,24 @@ RELEASE_MAPPING = { 'api': '1.100', 'rpc': '1.61', 'objects': { - 'Allocation': ['1.2', '1.1'], - 'BIOSSetting': ['1.1'], - 'Node': ['1.41'], - 'NodeHistory': ['1.0'], - 'NodeInventory': ['1.0'], - 'Conductor': ['1.5', '1.4'], - 'Chassis': ['1.3'], - 'Deployment': ['1.0'], - 'DeployTemplate': ['1.1'], - 'Port': ['1.13'], - 'Portgroup': ['1.5'], - 'Trait': ['1.0'], - 'TraitList': ['1.0'], - 'VolumeConnector': ['1.0'], - 'VolumeTarget': ['1.0'], - 'FirmwareComponent': ['1.0'], - 'Runbook': ['1.0'], - 'InspectionRule': ['1.0'], + 'Allocation': ['1.3', '1.2', '1.1'], + 'BIOSSetting': ['1.2', '1.1'], + 'Node': ['1.42', '1.41'], + 'NodeHistory': ['1.1', '1.0'], + 'NodeInventory': ['1.1', '1.0'], + 'Conductor': ['1.6', '1.5', '1.4'], + 'Chassis': ['1.4', '1.3'], + 'Deployment': ['1.1', '1.0'], + 'DeployTemplate': ['1.2', '1.1'], + 'Port': ['1.14', '1.13', '1.12'], + 'Portgroup': ['1.6', '1.5'], + 'Trait': ['1.1', '1.0'], + 'TraitList': ['1.1', '1.0'], + 'VolumeConnector': ['1.1', '1.0'], + 'VolumeTarget': ['1.1', '1.0'], + 'FirmwareComponent': ['1.1', '1.0'], + 'Runbook': ['1.1', '1.0'], + 'InspectionRule': ['1.1', '1.0'], } }, } diff --git a/ironic/conductor/manager.py b/ironic/conductor/manager.py index 9d59391cbe3..b4ca59f1da5 100644 --- a/ironic/conductor/manager.py +++ b/ironic/conductor/manager.py @@ -3473,6 +3473,11 @@ class ConductorManager(base_manager.BaseConductorManager): try: # NOTE(danms): Keep the getattr inside the try block since # a missing method is really a client problem + # NOTE(TheJulia): Explicitly set the indirection_api to None + # because we don't want to recurse into calling ourselves as + # a side-effect in single process mode -- i.e. if we have a + # request on this end, we've already routed through the layers. + target.indirection_api = None return getattr(target, method)(context, *args, **kwargs) except Exception: # NOTE(danms): This is oslo.messaging fu. ExpectedException() diff --git a/ironic/conf/default.py b/ironic/conf/default.py index 639273fa442..2b8a54104eb 100644 --- a/ironic/conf/default.py +++ b/ironic/conf/default.py @@ -99,6 +99,14 @@ api_opts = [ default="", help=_('The conductor_group to use for new nodes when no ' 'conductor_group was defined in the creation request.')), + cfg.BoolOpt('use_rpc_for_database', + default=False, + mutable=False, + help=_('If the Ironic API should utilize the RPC layer for ' + 'database interactions as opposed to directly ' + 'connecting to the database API endpoint. Defaults ' + 'to False, however is implied when the ' + '[default]rpc_transport option is set to \'none\'.')), ] driver_opts = [ diff --git a/ironic/objects/allocation.py b/ironic/objects/allocation.py index 3ae7f9985d3..3c41bfdcf46 100644 --- a/ironic/objects/allocation.py +++ b/ironic/objects/allocation.py @@ -28,7 +28,8 @@ class Allocation(base.IronicObject, object_base.VersionedObjectDictCompat): # Version 1.0: Initial version # Version 1.1: Add owner field # Version 1.2: Add remotable method check_node_list - VERSION = '1.2' + # Version 1.3: Relevant methods changed to be remotable methods. + VERSION = '1.3' dbapi = dbapi.get_instance() @@ -80,11 +81,7 @@ class Allocation(base.IronicObject, object_base.VersionedObjectDictCompat): # DB: set unavailable fields to their default. self.owner = None - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get(cls, context, allocation_ident): """Find an allocation by its ID, UUID or name. @@ -103,11 +100,7 @@ class Allocation(base.IronicObject, object_base.VersionedObjectDictCompat): else: raise exception.InvalidIdentity(identity=allocation_ident) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_id(cls, context, allocation_id): """Find an allocation by its integer ID. @@ -122,11 +115,7 @@ class Allocation(base.IronicObject, object_base.VersionedObjectDictCompat): allocation = cls._from_db_object(context, cls(), db_allocation) return allocation - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_uuid(cls, context, uuid): """Find an allocation by its UUID. @@ -141,11 +130,7 @@ class Allocation(base.IronicObject, object_base.VersionedObjectDictCompat): allocation = cls._from_db_object(context, cls(), db_allocation) return allocation - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_name(cls, context, name): """Find an allocation based by its name. @@ -160,11 +145,7 @@ class Allocation(base.IronicObject, object_base.VersionedObjectDictCompat): allocation = cls._from_db_object(context, cls(), db_allocation) return allocation - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def list(cls, context, filters=None, limit=None, marker=None, sort_key=None, sort_dir=None): """Return a list of Allocation objects. @@ -187,10 +168,7 @@ class Allocation(base.IronicObject, object_base.VersionedObjectDictCompat): sort_dir=sort_dir) return cls._from_db_object_list(context, db_allocations) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def create(self, context=None): """Create a Allocation record in the DB. @@ -207,10 +185,7 @@ class Allocation(base.IronicObject, object_base.VersionedObjectDictCompat): db_allocation = self.dbapi.create_allocation(values) self._from_db_object(self._context, self, db_allocation) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def destroy(self, context=None): """Delete the Allocation from the DB. @@ -226,10 +201,7 @@ class Allocation(base.IronicObject, object_base.VersionedObjectDictCompat): self.dbapi.destroy_allocation(self.uuid) self.obj_reset_changes() - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def save(self, context=None): """Save updates to this Allocation. @@ -249,10 +221,7 @@ class Allocation(base.IronicObject, object_base.VersionedObjectDictCompat): updated_allocation = self.dbapi.update_allocation(self.uuid, updates) self._from_db_object(self._context, self, updated_allocation) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def refresh(self, context=None): """Loads updates for this Allocation. diff --git a/ironic/objects/base.py b/ironic/objects/base.py index 3eeb29b7368..e93b406651c 100644 --- a/ironic/objects/base.py +++ b/ironic/objects/base.py @@ -27,6 +27,7 @@ from ironic.objects import fields as object_fields LOG = log.getLogger(__name__) remotable_classmethod = object_base.remotable_classmethod +remotable = object_base.remotable def max_version(versions): diff --git a/ironic/objects/bios.py b/ironic/objects/bios.py index d99e06b1f51..1a1f3d16b7b 100644 --- a/ironic/objects/bios.py +++ b/ironic/objects/bios.py @@ -25,7 +25,8 @@ from ironic.objects import fields as object_fields class BIOSSetting(base.IronicObject): # Version 1.0: Initial version # Version 1.1: Added registry - VERSION = '1.1' + # Version 1.2: Relevant methods changed to be remotable methods. + VERSION = '1.2' dbapi = dbapi.get_instance() @@ -49,10 +50,7 @@ class BIOSSetting(base.IronicObject): 'upper_bound': object_fields.IntegerField(nullable=True) } - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def create(self, context=None): """Create a BIOS Setting record in DB. @@ -74,10 +72,7 @@ class BIOSSetting(base.IronicObject): values['node_id'], [settings], values['version']) self._from_db_object(self._context, self, db_bios_setting[0]) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def save(self, context=None): """Save BIOS Setting update in DB. @@ -100,11 +95,7 @@ class BIOSSetting(base.IronicObject): values['node_id'], [settings], values['version']) self._from_db_object(self._context, self, updated_bios_setting[0]) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get(cls, context, node_id, name): """Get a BIOS Setting based on its node_id and name. @@ -118,11 +109,7 @@ class BIOSSetting(base.IronicObject): db_bios_setting = cls.dbapi.get_bios_setting(node_id, name) return cls._from_db_object(context, cls(), db_bios_setting) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def delete(cls, context, node_id, name): """Delete a BIOS Setting based on its node_id and name. @@ -172,7 +159,8 @@ class BIOSSetting(base.IronicObject): @base.IronicObjectRegistry.register class BIOSSettingList(base.IronicObjectListBase, base.IronicObject): # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.1: Relevant methods changed to be remotable methods. + VERSION = '1.1' dbapi = dbapi.get_instance() @@ -180,11 +168,7 @@ class BIOSSettingList(base.IronicObjectListBase, base.IronicObject): 'objects': object_fields.ListOfObjectsField('BIOSSetting'), } - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def create(cls, context, node_id, settings): """Create a list of BIOS Setting records in DB. @@ -207,11 +191,7 @@ class BIOSSettingList(base.IronicObjectListBase, base.IronicObject): return object_base.obj_make_list( context, cls(), BIOSSetting, db_setting_list) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def save(cls, context, node_id, settings): """Save a list of BIOS Setting updates in DB. @@ -234,11 +214,7 @@ class BIOSSettingList(base.IronicObjectListBase, base.IronicObject): return object_base.obj_make_list( context, cls(), BIOSSetting, updated_setting_list) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def delete(cls, context, node_id, names): """Delete BIOS Settings based on node_id and names. @@ -250,11 +226,7 @@ class BIOSSettingList(base.IronicObjectListBase, base.IronicObject): """ cls.dbapi.delete_bios_setting_list(node_id, names) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_node_id(cls, context, node_id): """Get BIOS Setting based on node_id. @@ -267,11 +239,7 @@ class BIOSSettingList(base.IronicObjectListBase, base.IronicObject): return object_base.obj_make_list( context, cls(), BIOSSetting, node_bios_setting) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def sync_node_setting(cls, context, node_id, settings): """Returns lists of create/update/delete/unchanged settings. diff --git a/ironic/objects/chassis.py b/ironic/objects/chassis.py index 714fb83729f..dc3e52dcd41 100644 --- a/ironic/objects/chassis.py +++ b/ironic/objects/chassis.py @@ -31,7 +31,8 @@ class Chassis(base.IronicObject, object_base.VersionedObjectDictCompat): # only work with a uuid # Version 1.2: Add create() and destroy() # Version 1.3: Add list() - VERSION = '1.3' + # Version 1.4: Relevant methods changed to be remotable methods. + VERSION = '1.4' dbapi = dbapi.get_instance() @@ -42,11 +43,7 @@ class Chassis(base.IronicObject, object_base.VersionedObjectDictCompat): 'description': object_fields.StringField(nullable=True), } - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get(cls, context, chassis_id): """Find a chassis based on its id or uuid and return a Chassis object. @@ -61,11 +58,7 @@ class Chassis(base.IronicObject, object_base.VersionedObjectDictCompat): else: raise exception.InvalidIdentity(identity=chassis_id) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_id(cls, context, chassis_id): """Find a chassis based on its integer ID and return a Chassis object. @@ -78,11 +71,7 @@ class Chassis(base.IronicObject, object_base.VersionedObjectDictCompat): chassis = cls._from_db_object(context, cls(), db_chassis) return chassis - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_uuid(cls, context, uuid): """Find a chassis based on UUID and return a :class:`Chassis` object. @@ -95,11 +84,7 @@ class Chassis(base.IronicObject, object_base.VersionedObjectDictCompat): chassis = cls._from_db_object(context, cls(), db_chassis) return chassis - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def list(cls, context, limit=None, marker=None, sort_key=None, sort_dir=None): """Return a list of Chassis objects. @@ -119,10 +104,7 @@ class Chassis(base.IronicObject, object_base.VersionedObjectDictCompat): sort_dir=sort_dir) return cls._from_db_object_list(context, db_chassis) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def create(self, context=None): """Create a Chassis record in the DB. @@ -143,10 +125,7 @@ class Chassis(base.IronicObject, object_base.VersionedObjectDictCompat): db_chassis = self.dbapi.create_chassis(values) self._from_db_object(self._context, self, db_chassis) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def destroy(self, context=None): """Delete the Chassis from the DB. @@ -160,10 +139,7 @@ class Chassis(base.IronicObject, object_base.VersionedObjectDictCompat): self.dbapi.destroy_chassis(self.uuid) self.obj_reset_changes() - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def save(self, context=None): """Save updates to this Chassis. @@ -181,10 +157,7 @@ class Chassis(base.IronicObject, object_base.VersionedObjectDictCompat): updated_chassis = self.dbapi.update_chassis(self.uuid, updates) self._from_db_object(self._context, self, updated_chassis) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def refresh(self, context=None): """Loads and applies updates for this Chassis. diff --git a/ironic/objects/conductor.py b/ironic/objects/conductor.py index 75d8db1d9d3..3312bbc13b5 100644 --- a/ironic/objects/conductor.py +++ b/ironic/objects/conductor.py @@ -37,7 +37,9 @@ class Conductor(base.IronicObject, object_base.VersionedObjectDictCompat): # Version 1.5: Add new remotable methods # get_shard_list, list_hardware_type_interfaces, # and get_active_hardware_type_dict - VERSION = '1.5' + # Version 1.6: Updates methods numerous conductor methods to + # to be remotable calls. + VERSION = '1.6' dbapi = db_api.get_instance() @@ -49,7 +51,7 @@ class Conductor(base.IronicObject, object_base.VersionedObjectDictCompat): 'online': object_fields.BooleanField(), } - @classmethod + @object_base.remotable_classmethod def list(cls, context, limit=None, marker=None, sort_key=None, sort_dir=None): """Return a list of Conductor objects. @@ -68,11 +70,7 @@ class Conductor(base.IronicObject, object_base.VersionedObjectDictCompat): sort_dir=sort_dir) return cls._from_db_object_list(context, db_conductors) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_hostname(cls, context, hostname, online=True): """Get a Conductor record by its hostname. @@ -88,15 +86,13 @@ class Conductor(base.IronicObject, object_base.VersionedObjectDictCompat): conductor = cls._from_db_object(context, cls(), db_obj) return conductor + @object_base.remotable def save(self, context): """Save is not supported by Conductor objects.""" raise NotImplementedError( _('Cannot update a conductor record directly.')) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def refresh(self, context=None): """Loads and applies updates for this Conductor. @@ -114,18 +110,10 @@ class Conductor(base.IronicObject, object_base.VersionedObjectDictCompat): current = self.get_by_hostname(self._context, hostname=self.hostname) self.obj_refresh(current) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable def touch(self, context=None, online=True): """Touch this conductor's DB record, marking it as up-to-date.""" self.dbapi.touch_conductor(self.hostname, online=online) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable @classmethod def register(cls, context, hostname, drivers, conductor_group, update_existing=False): @@ -154,10 +142,6 @@ class Conductor(base.IronicObject, object_base.VersionedObjectDictCompat): update_existing=update_existing) return cls._from_db_object(context, cls(), db_cond) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable def unregister(self, context=None): """Remove this conductor from the service registry.""" self.unregister_all_hardware_interfaces() @@ -187,7 +171,10 @@ class Conductor(base.IronicObject, object_base.VersionedObjectDictCompat): 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) + # NOTE(TheJulia): Return a dict object instead of a collection object + # because the indirection layer cannot handle a collection class. + return dict( + cls.dbapi.get_active_hardware_type_dict(use_groups=use_groups)) @base.remotable_classmethod def list_hardware_type_interfaces_dict(cls, context, names): @@ -227,4 +214,6 @@ class Conductor(base.IronicObject, object_base.VersionedObjectDictCompat): indirection_api call usage instead of trying to directly invoke the database. """ + # FIXME(TheJulia): Ideally this should be a formal object, but the + # calling method expects json, so it works. return cls.dbapi.get_shard_list() diff --git a/ironic/objects/deploy_template.py b/ironic/objects/deploy_template.py index a9c8a60fe02..f87bd46dfe6 100644 --- a/ironic/objects/deploy_template.py +++ b/ironic/objects/deploy_template.py @@ -22,7 +22,8 @@ from ironic.objects import notification class DeployTemplate(base.IronicObject, object_base.VersionedObjectDictCompat): # Version 1.0: Initial version # Version 1.1: Added 'extra' field - VERSION = '1.1' + # Version 1.2: Relevant methods changed to be remotable methods. + VERSION = '1.2' dbapi = db_api.get_instance() @@ -34,11 +35,7 @@ class DeployTemplate(base.IronicObject, object_base.VersionedObjectDictCompat): 'extra': object_fields.FlexibleDictField(nullable=True), } - # NOTE(mgoddard): We don't want to enable RPC on this call just yet. - # Remotable methods can be used in the future to replace current explicit - # RPC calls. Implications of calling new remote procedures should be - # thought through. - # @object_base.remotable + @object_base.remotable def create(self, context=None): """Create a DeployTemplate record in the DB. @@ -57,11 +54,7 @@ class DeployTemplate(base.IronicObject, object_base.VersionedObjectDictCompat): db_template = self.dbapi.create_deploy_template(values) self._from_db_object(self._context, self, db_template) - # NOTE(mgoddard): We don't want to enable RPC on this call just yet. - # Remotable methods can be used in the future to replace current explicit - # RPC calls. Implications of calling new remote procedures should be - # thought through. - # @object_base.remotable + @object_base.remotable def save(self, context=None): """Save updates to this DeployTemplate. @@ -82,11 +75,7 @@ class DeployTemplate(base.IronicObject, object_base.VersionedObjectDictCompat): db_template = self.dbapi.update_deploy_template(self.uuid, updates) self._from_db_object(self._context, self, db_template) - # NOTE(mgoddard): We don't want to enable RPC on this call just yet. - # Remotable methods can be used in the future to replace current explicit - # RPC calls. Implications of calling new remote procedures should be - # thought through. - # @object_base.remotable_classmethod + @object_base.remotable def destroy(self): """Delete the DeployTemplate from the DB. @@ -102,12 +91,7 @@ class DeployTemplate(base.IronicObject, object_base.VersionedObjectDictCompat): self.dbapi.destroy_deploy_template(self.id) self.obj_reset_changes() - # NOTE(mgoddard): We don't want to enable RPC on this call just yet. - # Remotable methods can be used in the future to replace current explicit - # RPC calls. Implications of calling new remote procedures should be - # thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_id(cls, context, template_id): """Find a deploy template based on its integer ID. @@ -126,12 +110,7 @@ class DeployTemplate(base.IronicObject, object_base.VersionedObjectDictCompat): template = cls._from_db_object(context, cls(), db_template) return template - # NOTE(mgoddard): We don't want to enable RPC on this call just yet. - # Remotable methods can be used in the future to replace current explicit - # RPC calls. Implications of calling new remote procedures should be - # thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_uuid(cls, context, uuid): """Find a deploy template based on its UUID. @@ -150,12 +129,7 @@ class DeployTemplate(base.IronicObject, object_base.VersionedObjectDictCompat): template = cls._from_db_object(context, cls(), db_template) return template - # NOTE(mgoddard): We don't want to enable RPC on this call just yet. - # Remotable methods can be used in the future to replace current explicit - # RPC calls. Implications of calling new remote procedures should be - # thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_name(cls, context, name): """Find a deploy template based on its name. @@ -174,12 +148,7 @@ class DeployTemplate(base.IronicObject, object_base.VersionedObjectDictCompat): template = cls._from_db_object(context, cls(), db_template) return template - # NOTE(mgoddard): We don't want to enable RPC on this call just yet. - # Remotable methods can be used in the future to replace current explicit - # RPC calls. Implications of calling new remote procedures should be - # thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def list(cls, context, limit=None, marker=None, sort_key=None, sort_dir=None): """Return a list of DeployTemplate objects. @@ -200,12 +169,7 @@ class DeployTemplate(base.IronicObject, object_base.VersionedObjectDictCompat): limit=limit, marker=marker, sort_key=sort_key, sort_dir=sort_dir) return cls._from_db_object_list(context, db_templates) - # NOTE(mgoddard): We don't want to enable RPC on this call just yet. - # Remotable methods can be used in the future to replace current explicit - # RPC calls. Implications of calling new remote procedures should be - # thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def list_by_names(cls, context, names): """Return a list of DeployTemplate objects matching a set of names. @@ -221,6 +185,7 @@ class DeployTemplate(base.IronicObject, object_base.VersionedObjectDictCompat): db_templates = cls.dbapi.get_deploy_template_list_by_names(names) return cls._from_db_object_list(context, db_templates) + @object_base.remotable def refresh(self, context=None): """Loads updates for this deploy template. diff --git a/ironic/objects/deployment.py b/ironic/objects/deployment.py index 7fe7f754448..e9fa9b20a2c 100644 --- a/ironic/objects/deployment.py +++ b/ironic/objects/deployment.py @@ -23,7 +23,8 @@ from ironic.objects import node as node_obj @base.IronicObjectRegistry.register class Deployment(base.IronicObject, object_base.VersionedObjectDictCompat): # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.1: Relevant methods changed to be remotable methods. + VERSION = '1.1' dbapi = dbapi.get_instance() @@ -118,11 +119,7 @@ class Deployment(base.IronicObject, object_base.VersionedObjectDictCompat): node.instance_info = instance_info return node - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_uuid(cls, context, uuid): """Find a deployment by its UUID. @@ -136,11 +133,7 @@ class Deployment(base.IronicObject, object_base.VersionedObjectDictCompat): node = node_obj.Node.get_by_instance_uuid(context, uuid) return cls._from_node_object(context, node) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_node_uuid(cls, context, node_uuid): """Find a deployment based by its node's UUID. @@ -154,11 +147,7 @@ class Deployment(base.IronicObject, object_base.VersionedObjectDictCompat): node = node_obj.Node.get_by_uuid(context, node_uuid) return cls._from_node_object(context, node) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def list(cls, context, filters=None, limit=None, marker=None, sort_key=None, sort_dir=None): """Return a list of Deployment objects. @@ -179,10 +168,7 @@ class Deployment(base.IronicObject, object_base.VersionedObjectDictCompat): sort_dir=sort_dir) return [cls._from_node_object(context, node) for node in nodes] - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def create(self, context=None, node=None): """Create a Deployment. @@ -213,10 +199,7 @@ class Deployment(base.IronicObject, object_base.VersionedObjectDictCompat): self._update_from_node_object(node) self.obj_reset_changes() - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def destroy(self, context=None, node=None): """Delete the Deployment. @@ -240,10 +223,7 @@ class Deployment(base.IronicObject, object_base.VersionedObjectDictCompat): self._update_from_node_object(node) self.obj_reset_changes() - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def refresh(self, context=None): """Refresh the object by re-fetching from the DB. diff --git a/ironic/objects/firmware.py b/ironic/objects/firmware.py index d30bc16911f..2a1eaa37010 100644 --- a/ironic/objects/firmware.py +++ b/ironic/objects/firmware.py @@ -23,7 +23,8 @@ from ironic.objects import fields as object_fields @base.IronicObjectRegistry.register class FirmwareComponent(base.IronicObject): # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.1: Relevant methods changed to be remotable methods. + VERSION = '1.1' dbapi = dbapi.get_instance() @@ -36,6 +37,7 @@ class FirmwareComponent(base.IronicObject): 'last_version_flashed': object_fields.StringField(nullable=True), } + @object_base.remotable def create(self, context=None): """Create a Firmware record in the DB. @@ -50,6 +52,7 @@ class FirmwareComponent(base.IronicObject): db_fwcmp = self.dbapi.create_firmware_component(values) self._from_db_object(self._context, self, db_fwcmp) + @object_base.remotable def save(self, context=None): """Save updates to this Firmware Component. @@ -74,7 +77,7 @@ class FirmwareComponent(base.IronicObject): self.node_id, self.component, updates) self._from_db_object(self._context, self, up_fwcmp) - @classmethod + @object_base.remotable_classmethod def get(cls, context, node_id, name): """Get a FirmwareComponent based on its node_id and name. @@ -94,7 +97,8 @@ class FirmwareComponent(base.IronicObject): @base.IronicObjectRegistry.register class FirmwareComponentList(base.IronicObjectListBase, base.IronicObject): # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.1: Relevant methods changed to be remotable methods. + VERSION = '1.1' dbapi = dbapi.get_instance() @@ -102,7 +106,7 @@ class FirmwareComponentList(base.IronicObjectListBase, base.IronicObject): 'objects': object_fields.ListOfObjectsField('FirmwareComponent'), } - @classmethod + @object_base.remotable_classmethod def get_by_node_id(cls, context, node_id): """Get FirmwareComponent based on node_id. diff --git a/ironic/objects/indirection.py b/ironic/objects/indirection.py index cf92cb40a90..bc0ac1deb31 100644 --- a/ironic/objects/indirection.py +++ b/ironic/objects/indirection.py @@ -15,6 +15,9 @@ from oslo_versionedobjects import base as object_base from ironic.conductor import rpcapi as conductor_api +# NOTE(TheJulia): The whole purpose of the indirection API is to disjoint +# the interactions to the conductor through a class based upon the +# VersionedObjectIndirectionAPI class provided by oslo.versionedobjects. class IronicObjectIndirectionAPI(object_base.VersionedObjectIndirectionAPI): def __init__(self): super(IronicObjectIndirectionAPI, self).__init__() diff --git a/ironic/objects/inspection_rule.py b/ironic/objects/inspection_rule.py index 1773f0d5f2c..1e533a92f64 100644 --- a/ironic/objects/inspection_rule.py +++ b/ironic/objects/inspection_rule.py @@ -20,7 +20,8 @@ from ironic.objects import notification @base.IronicObjectRegistry.register class InspectionRule(base.IronicObject, object_base.VersionedObjectDictCompat): # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.1: Relevant methods changed to be remotable methods. + VERSION = '1.1' dbapi = db_api.get_instance() @@ -36,11 +37,7 @@ class InspectionRule(base.IronicObject, object_base.VersionedObjectDictCompat): 'conditions': object_fields.ListOfFlexibleDictsField(nullable=True), } - # NOTE(mgoddard): We don't want to enable RPC on this call just yet. - # Remotable methods can be used in the future to replace current explicit - # RPC calls. Implications of calling new remote procedures should be - # thought through. - # @object_base.remotable + @object_base.remotable def create(self, context=None): """Create a InspectionRule record in the DB. @@ -59,6 +56,7 @@ class InspectionRule(base.IronicObject, object_base.VersionedObjectDictCompat): db_rule = self.dbapi.create_inspection_rule(values) self._from_db_object(self._context, self, db_rule) + @object_base.remotable def save(self, context=None): """Save updates to this InspectionRule. @@ -77,6 +75,7 @@ class InspectionRule(base.IronicObject, object_base.VersionedObjectDictCompat): db_rule = self.dbapi.update_inspection_rule(self.uuid, updates) self._from_db_object(self._context, self, db_rule) + @object_base.remotable def destroy(self): """Delete the InspectionRule from the DB. @@ -92,12 +91,7 @@ class InspectionRule(base.IronicObject, object_base.VersionedObjectDictCompat): self.dbapi.destroy_inspection_rule(self.id) self.obj_reset_changes() - # NOTE(mgoddard): We don't want to enable RPC on this call just yet. - # Remotable methods can be used in the future to replace current explicit - # RPC calls. Implications of calling new remote procedures should be - # thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_uuid(cls, context, uuid): """Find a inspection rule based on its UUID. @@ -116,12 +110,7 @@ class InspectionRule(base.IronicObject, object_base.VersionedObjectDictCompat): rule = cls._from_db_object(context, cls(), db_rule) return rule - # NOTE(mgoddard): We don't want to enable RPC on this call just yet. - # Remotable methods can be used in the future to replace current explicit - # RPC calls. Implications of calling new remote procedures should be - # thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def list(cls, context, limit=None, marker=None, sort_key=None, sort_dir=None, filters=None): """Return a list of InspectionRule objects. @@ -143,6 +132,7 @@ class InspectionRule(base.IronicObject, object_base.VersionedObjectDictCompat): filters=filters) return cls._from_db_object_list(context, db_rules) + @object_base.remotable def refresh(self, context=None): """Loads updates for this inspection rule. diff --git a/ironic/objects/node.py b/ironic/objects/node.py index 19f0105484a..7ef1443a7d8 100644 --- a/ironic/objects/node.py +++ b/ironic/objects/node.py @@ -83,7 +83,8 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat): # Version 1.39: Add firmware_interface field # Version 1.40: Add service_step field # Version 1.41: Add disable_power_off field - VERSION = '1.41' + # Version 1.42: Moves multiple methods to be remotable methods. + VERSION = '1.42' dbapi = db_api.get_instance() @@ -240,11 +241,7 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat): fields=['trait', 'version']) self.traits.obj_reset_changes() - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get(cls, context, node_id): """Find a node based on its id or uuid and return a Node object. @@ -259,11 +256,7 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat): else: raise exception.InvalidIdentity(identity=node_id) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_id(cls, context, node_id): """Find a node based on its integer ID and return a Node object. @@ -276,11 +269,7 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat): node = cls._from_db_object(context, cls(), db_node) return node - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_uuid(cls, context, uuid): """Find a node based on UUID and return a Node object. @@ -293,11 +282,7 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat): node = cls._from_db_object(context, cls(), db_node) return node - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_name(cls, context, name): """Find a node based on name and return a Node object. @@ -310,11 +295,7 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat): node = cls._from_db_object(context, cls(), db_node) return node - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_instance_uuid(cls, context, instance_uuid): """Find a node based on the instance UUID and return a Node object. @@ -327,11 +308,7 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat): node = cls._from_db_object(context, cls(), db_node) return node - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def list(cls, context, limit=None, marker=None, sort_key=None, sort_dir=None, filters=None, fields=None): """Return a list of Node objects. @@ -367,10 +344,9 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat): fields=target_fields) return cls._from_db_object_list(context, db_nodes, target_fields) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod + # NOTE(TheJulia): The choice to not make this a remotable method is + # explicit in that locks are intended only for a conductor. If we choose + # to change this, we need reconsider the locking model. @classmethod def reserve(cls, context, tag, node_id): """Get and reserve a node. @@ -390,10 +366,9 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat): node = cls._from_db_object(context, cls(), db_node) return node - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod + # NOTE(TheJulia): The choice to not make this a remotable method is + # explicit in that locks are intended only for a conductor. If we choose + # to change this, we need reconsider the locking model. @classmethod def release(cls, context, tag, node_id): """Release the reservation on a node. @@ -406,10 +381,7 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat): """ cls.dbapi.release_node(tag, node_id) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def create(self, context=None): """Create a Node record in the DB. @@ -433,10 +405,7 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat): db_node = self.dbapi.create_node(values) self._from_db_object(self._context, self, db_node) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def destroy(self, context=None): """Delete the Node from the DB. @@ -450,10 +419,7 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat): self.dbapi.destroy_node(self.uuid) self.obj_reset_changes() - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def save(self, context=None): """Save updates to this Node. @@ -519,10 +485,7 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat): utils.validate_conductor_group(fields['conductor_group']) fields['conductor_group'] = fields['conductor_group'].lower() - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def refresh(self, context=None): """Refresh the object by re-fetching from the DB. @@ -537,15 +500,11 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat): self.obj_refresh(current) self.obj_reset_changes() - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable def touch_provisioning(self, context=None): """Touch the database record to mark the provisioning as alive.""" self.dbapi.touch_node_provisioning(self.id) - @classmethod + @object_base.remotable_classmethod def get_by_port_addresses(cls, context, addresses): """Get a node by associated port addresses. diff --git a/ironic/objects/node_history.py b/ironic/objects/node_history.py index abccd518431..cc93e40229b 100644 --- a/ironic/objects/node_history.py +++ b/ironic/objects/node_history.py @@ -23,7 +23,8 @@ from ironic.objects import fields as object_fields @base.IronicObjectRegistry.register class NodeHistory(base.IronicObject, object_base.VersionedObjectDictCompat): # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.1: Relevant methods changed to be remotable methods. + VERSION = '1.1' dbapi = dbapi.get_instance() @@ -38,11 +39,7 @@ class NodeHistory(base.IronicObject, object_base.VersionedObjectDictCompat): 'severity': object_fields.StringField(nullable=True), } - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get(cls, context, history_ident): """Get a history based on its id or uuid. @@ -59,11 +56,7 @@ class NodeHistory(base.IronicObject, object_base.VersionedObjectDictCompat): else: raise exception.InvalidIdentity(identity=history_ident) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_id(cls, context, history_id): """Get a NodeHistory object by its integer ID. @@ -78,11 +71,7 @@ class NodeHistory(base.IronicObject, object_base.VersionedObjectDictCompat): history = cls._from_db_object(context, cls(), db_history) return history - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_uuid(cls, context, uuid): """Get a NodeHistory object by its UUID. @@ -97,11 +86,7 @@ class NodeHistory(base.IronicObject, object_base.VersionedObjectDictCompat): history = cls._from_db_object(context, cls(), db_history) return history - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def list(cls, context, limit=None, marker=None, sort_key=None, sort_dir=None): """Return a list of NodeHistory objects. @@ -122,11 +107,7 @@ class NodeHistory(base.IronicObject, object_base.VersionedObjectDictCompat): sort_dir=sort_dir) return cls._from_db_object_list(context, db_histories) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def list_by_node_id(cls, context, node_id, limit=None, marker=None, sort_key=None, sort_dir=None): """Return a list of NodeHistory objects belongs to a given node ID. @@ -147,10 +128,6 @@ class NodeHistory(base.IronicObject, object_base.VersionedObjectDictCompat): sort_dir=sort_dir) return cls._from_db_object_list(context, db_histories) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable def create(self, context=None): """Create a NodeHistory record in the DB. @@ -165,10 +142,6 @@ class NodeHistory(base.IronicObject, object_base.VersionedObjectDictCompat): db_history = self.dbapi.create_node_history(values) self._from_db_object(self._context, self, db_history) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable def destroy(self, context=None): """Delete the NodeHistory from the DB. diff --git a/ironic/objects/node_inventory.py b/ironic/objects/node_inventory.py index eccc842dd8d..8061cbb800b 100644 --- a/ironic/objects/node_inventory.py +++ b/ironic/objects/node_inventory.py @@ -20,7 +20,8 @@ from ironic.objects import fields as object_fields @base.IronicObjectRegistry.register class NodeInventory(base.IronicObject, object_base.VersionedObjectDictCompat): # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.1: Relevant methods changed to be remotable methods. + VERSION = '1.1' dbapi = dbapi.get_instance() @@ -45,7 +46,7 @@ class NodeInventory(base.IronicObject, object_base.VersionedObjectDictCompat): for src, dest in self.instance_info_mapping.items(): setattr(self, dest, node.instance_info.get(src)) - @classmethod + @object_base.remotable_classmethod def get_by_node_id(cls, context, node_id): """Get a NodeInventory object by its node ID. @@ -60,6 +61,7 @@ class NodeInventory(base.IronicObject, object_base.VersionedObjectDictCompat): inventory = cls._from_db_object(context, cls(), db_inventory) return inventory + @object_base.remotable def create(self, context=None): """Create a NodeInventory record in the DB. @@ -74,6 +76,7 @@ class NodeInventory(base.IronicObject, object_base.VersionedObjectDictCompat): db_inventory = self.dbapi.create_node_inventory(values) self._from_db_object(self._context, self, db_inventory) + @object_base.remotable def destroy(self, context=None): """Delete the NodeInventory from the DB. diff --git a/ironic/objects/port.py b/ironic/objects/port.py index ecda6c5b0b9..db5462af96b 100644 --- a/ironic/objects/port.py +++ b/ironic/objects/port.py @@ -47,7 +47,8 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat): # Version 1.11: Add node_uuid field # Version 1.12: Add description field # Version 1.13: Add vendor field - VERSION = '1.13' + # Version 1.14: Mark multiple methods as remotable methods. + VERSION = '1.14' dbapi = dbapi.get_instance() @@ -163,11 +164,7 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat): self._convert_field_by_version('vendor', (1, 13), target_version, remove_unavailable_fields) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get(cls, context, port_id): """Find a port. @@ -191,11 +188,7 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat): else: raise exception.InvalidIdentity(identity=port_id) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_id(cls, context, port_id): """Find a port based on its integer ID and return a Port object. @@ -210,11 +203,7 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat): port = cls._from_db_object(context, cls(), db_port) return port - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_uuid(cls, context, uuid): """Find a port based on UUID and return a :class:`Port` object. @@ -229,11 +218,7 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat): port = cls._from_db_object(context, cls(), db_port) return port - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_address(cls, context, address, owner=None, project=None): """Find a port based on address and return a :class:`Port` object. @@ -252,11 +237,7 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat): port = cls._from_db_object(context, cls(), db_port) return port - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_name(cls, context, name): """Find a port based on name and return a :class:`Port` object. @@ -271,11 +252,7 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat): port = cls._from_db_object(context, cls(), db_port) return port - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def list(cls, context, limit=None, marker=None, sort_key=None, sort_dir=None, owner=None, project=None, conductor_groups=None, filters=None): @@ -330,11 +307,7 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat): filters=filters) return cls._from_db_object_list(context, db_ports) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def list_by_node_id(cls, context, node_id, limit=None, marker=None, sort_key=None, sort_dir=None, owner=None, project=None, filters=None): @@ -362,11 +335,7 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat): filters=filters) return cls._from_db_object_list(context, db_ports) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def list_by_portgroup_id(cls, context, portgroup_id, limit=None, marker=None, sort_key=None, sort_dir=None, owner=None, project=None, filters=None): @@ -395,10 +364,7 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat): filters=filters) return cls._from_db_object_list(context, db_ports) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def create(self, context=None): """Create a Port record in the DB. @@ -420,10 +386,7 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat): db_port = self.dbapi.get_port_by_id(db_port['id']) self._from_db_object(self._context, self, db_port) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def destroy(self, context=None): """Delete the Port from the DB. @@ -439,10 +402,7 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat): self.dbapi.destroy_port(self.uuid) self.obj_reset_changes() - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def save(self, context=None): """Save updates to this Port. @@ -463,10 +423,7 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat): updated_port = self.dbapi.update_port(self.uuid, updates) self._from_db_object(self._context, self, updated_port) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def refresh(self, context=None): """Loads updates for this Port. diff --git a/ironic/objects/portgroup.py b/ironic/objects/portgroup.py index 0fac096a393..662e074d602 100644 --- a/ironic/objects/portgroup.py +++ b/ironic/objects/portgroup.py @@ -37,7 +37,8 @@ class Portgroup(base.IronicObject, object_base.VersionedObjectDictCompat): # internal_info['tenant_vif_port_id'] (not an explicit db # change) # Version 1.5: Add node_uuid field - VERSION = '1.5' + # Version 1.6: Relevant methods changed to be remotable methods. + VERSION = '1.6' dbapi = dbapi.get_instance() @@ -86,11 +87,7 @@ class Portgroup(base.IronicObject, object_base.VersionedObjectDictCompat): internal_info['tenant_vif_port_id'] = vif self.internal_info = internal_info - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get(cls, context, portgroup_ident): """Find a portgroup based on its id, uuid, name or address. @@ -111,11 +108,7 @@ class Portgroup(base.IronicObject, object_base.VersionedObjectDictCompat): else: raise exception.InvalidIdentity(identity=portgroup_ident) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_id(cls, context, portgroup_id): """Find a portgroup by its integer ID and return a Portgroup object. @@ -130,11 +123,7 @@ class Portgroup(base.IronicObject, object_base.VersionedObjectDictCompat): portgroup = cls._from_db_object(context, cls(), db_portgroup) return portgroup - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_uuid(cls, context, uuid): """Find a portgroup by UUID and return a :class:`Portgroup` object. @@ -149,11 +138,7 @@ class Portgroup(base.IronicObject, object_base.VersionedObjectDictCompat): portgroup = cls._from_db_object(context, cls(), db_portgroup) return portgroup - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_address(cls, context, address, project=None): """Find portgroup by address and return a :class:`Portgroup` object. @@ -170,11 +155,7 @@ class Portgroup(base.IronicObject, object_base.VersionedObjectDictCompat): portgroup = cls._from_db_object(context, cls(), db_portgroup) return portgroup - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_name(cls, context, name): """Find portgroup based on name and return a :class:`Portgroup` object. @@ -189,11 +170,7 @@ class Portgroup(base.IronicObject, object_base.VersionedObjectDictCompat): portgroup = cls._from_db_object(context, cls(), db_portgroup) return portgroup - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def list(cls, context, limit=None, marker=None, sort_key=None, sort_dir=None, project=None, conductor_groups=None, filters=None): @@ -223,11 +200,7 @@ class Portgroup(base.IronicObject, object_base.VersionedObjectDictCompat): conductor_groups=conductor_groups) return cls._from_db_object_list(context, db_portgroups) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def list_by_node_id(cls, context, node_id, limit=None, marker=None, sort_key=None, sort_dir=None, project=None): """Return a list of Portgroup objects associated with a given node ID. @@ -252,10 +225,7 @@ class Portgroup(base.IronicObject, object_base.VersionedObjectDictCompat): project=project) return cls._from_db_object_list(context, db_portgroups) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def create(self, context=None): """Create a Portgroup record in the DB. @@ -276,10 +246,7 @@ class Portgroup(base.IronicObject, object_base.VersionedObjectDictCompat): db_portgroup = self.dbapi.get_portgroup_by_id(db_portgroup['id']) self._from_db_object(self._context, self, db_portgroup) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def destroy(self, context=None): """Delete the Portgroup from the DB. @@ -295,10 +262,7 @@ class Portgroup(base.IronicObject, object_base.VersionedObjectDictCompat): self.dbapi.destroy_portgroup(self.id) self.obj_reset_changes() - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def save(self, context=None): """Save updates to this Portgroup. @@ -318,10 +282,7 @@ class Portgroup(base.IronicObject, object_base.VersionedObjectDictCompat): updated_portgroup = self.dbapi.update_portgroup(self.uuid, updates) self._from_db_object(self._context, self, updated_portgroup) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def refresh(self, context=None): """Loads updates for this Portgroup. diff --git a/ironic/objects/runbook.py b/ironic/objects/runbook.py index 66a0656d9a7..3168c32946f 100644 --- a/ironic/objects/runbook.py +++ b/ironic/objects/runbook.py @@ -21,7 +21,8 @@ from ironic.objects import notification @base.IronicObjectRegistry.register class Runbook(base.IronicObject, object_base.VersionedObjectDictCompat): # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.1: Relevant methods changed to be remotable methods. + VERSION = '1.1' dbapi = db_api.get_instance() @@ -36,6 +37,7 @@ class Runbook(base.IronicObject, object_base.VersionedObjectDictCompat): 'owner': object_fields.StringField(nullable=True), } + @object_base.remotable def create(self, context=None): """Create a Runbook record in the DB. @@ -54,6 +56,7 @@ class Runbook(base.IronicObject, object_base.VersionedObjectDictCompat): db_template = self.dbapi.create_runbook(values) self._from_db_object(self._context, self, db_template) + @object_base.remotable def save(self, context=None): """Save updates to this Runbook. @@ -74,6 +77,7 @@ class Runbook(base.IronicObject, object_base.VersionedObjectDictCompat): db_template = self.dbapi.update_runbook(self.uuid, updates) self._from_db_object(self._context, self, db_template) + @object_base.remotable def destroy(self): """Delete the Runbook from the DB. @@ -89,7 +93,7 @@ class Runbook(base.IronicObject, object_base.VersionedObjectDictCompat): self.dbapi.destroy_runbook(self.id) self.obj_reset_changes() - @classmethod + @object_base.remotable_classmethod def get_by_id(cls, context, runbook_id): """Find a runbook based on its integer ID. @@ -108,7 +112,7 @@ class Runbook(base.IronicObject, object_base.VersionedObjectDictCompat): template = cls._from_db_object(context, cls(), db_template) return template - @classmethod + @object_base.remotable_classmethod def get_by_uuid(cls, context, uuid): """Find a runbook based on its UUID. @@ -127,7 +131,7 @@ class Runbook(base.IronicObject, object_base.VersionedObjectDictCompat): template = cls._from_db_object(context, cls(), db_template) return template - @classmethod + @object_base.remotable_classmethod def get_by_name(cls, context, name): """Find a runbook based on its name. @@ -146,7 +150,7 @@ class Runbook(base.IronicObject, object_base.VersionedObjectDictCompat): template = cls._from_db_object(context, cls(), db_template) return template - @classmethod + @object_base.remotable_classmethod def list(cls, context, limit=None, marker=None, sort_key=None, sort_dir=None, filters=None): """Return a list of Runbook objects. @@ -170,7 +174,7 @@ class Runbook(base.IronicObject, object_base.VersionedObjectDictCompat): filters=filters) return cls._from_db_object_list(context, db_templates) - @classmethod + @object_base.remotable_classmethod def list_by_names(cls, context, names): """Return a list of Runbook objects matching a set of names. @@ -186,6 +190,7 @@ class Runbook(base.IronicObject, object_base.VersionedObjectDictCompat): db_templates = cls.dbapi.get_runbook_list_by_names(names) return cls._from_db_object_list(context, db_templates) + @object_base.remotable def refresh(self, context=None): """Loads updates for this runbook. diff --git a/ironic/objects/trait.py b/ironic/objects/trait.py index d7e6c4b3762..0575628f730 100644 --- a/ironic/objects/trait.py +++ b/ironic/objects/trait.py @@ -20,7 +20,8 @@ from ironic.objects import fields as object_fields @base.IronicObjectRegistry.register class Trait(base.IronicObject): # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.1: Relevant methods changed to be remotable methods. + VERSION = '1.1' dbapi = db_api.get_instance() @@ -29,11 +30,7 @@ class Trait(base.IronicObject): 'trait': object_fields.StringField(), } - # NOTE(mgoddard): We don't want to enable RPC on this call just yet. - # Remotable methods can be used in the future to replace current explicit - # RPC calls. Implications of calling new remote procedures should be - # thought through. - # @object_base.remotable + @object_base.remotable def create(self, context=None): """Create a Trait record in the DB. @@ -52,12 +49,7 @@ class Trait(base.IronicObject): values['node_id'], values['trait'], values['version']) self._from_db_object(self._context, self, db_trait) - # NOTE(mgoddard): We don't want to enable RPC on this call just yet. - # Remotable methods can be used in the future to replace current explicit - # RPC calls. Implications of calling new remote procedures should be - # thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def destroy(cls, context, node_id, trait): """Delete the Trait from the DB. @@ -74,12 +66,7 @@ class Trait(base.IronicObject): """ cls.dbapi.delete_node_trait(node_id, trait) - # NOTE(mgoddard): We don't want to enable RPC on this call just yet. - # Remotable methods can be used in the future to replace current explicit - # RPC calls. Implications of calling new remote procedures should be - # thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def exists(cls, context, node_id, trait): """Check whether a Trait exists in the DB. @@ -100,7 +87,8 @@ class Trait(base.IronicObject): @base.IronicObjectRegistry.register class TraitList(base.IronicObjectListBase, base.IronicObject): # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.1: Relevant methods changed to be remotable methods. + VERSION = '1.1' dbapi = db_api.get_instance() @@ -108,12 +96,7 @@ class TraitList(base.IronicObjectListBase, base.IronicObject): 'objects': object_fields.ListOfObjectsField('Trait'), } - # NOTE(mgoddard): We don't want to enable RPC on this call just yet. - # Remotable methods can be used in the future to replace current explicit - # RPC calls. Implications of calling new remote procedures should be - # thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_node_id(cls, context, node_id): """Return all traits for the specified node. @@ -129,12 +112,7 @@ class TraitList(base.IronicObjectListBase, base.IronicObject): db_traits = cls.dbapi.get_node_traits_by_node_id(node_id) return object_base.obj_make_list(context, cls(), Trait, db_traits) - # NOTE(mgoddard): We don't want to enable RPC on this call just yet. - # Remotable methods can be used in the future to replace current explicit - # RPC calls. Implications of calling new remote procedures should be - # thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def create(cls, context, node_id, traits): """Replace all existing traits with the specified list. @@ -154,12 +132,7 @@ class TraitList(base.IronicObjectListBase, base.IronicObject): db_traits = cls.dbapi.set_node_traits(node_id, traits, version) return object_base.obj_make_list(context, cls(), Trait, db_traits) - # NOTE(mgoddard): We don't want to enable RPC on this call just yet. - # Remotable methods can be used in the future to replace current explicit - # RPC calls. Implications of calling new remote procedures should be - # thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def destroy(cls, context, node_id): """Delete all traits for the specified node. @@ -174,6 +147,7 @@ class TraitList(base.IronicObjectListBase, base.IronicObject): """ cls.dbapi.unset_node_traits(node_id) - def get_trait_names(self): + @object_base.remotable + def get_trait_names(self, context=None): """Return a list of names of the traits in this list.""" return [t.trait for t in self.objects] diff --git a/ironic/objects/volume_connector.py b/ironic/objects/volume_connector.py index 57070ab0696..37dbff38563 100644 --- a/ironic/objects/volume_connector.py +++ b/ironic/objects/volume_connector.py @@ -27,7 +27,8 @@ from ironic.objects import notification class VolumeConnector(base.IronicObject, object_base.VersionedObjectDictCompat): # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.1: Relevant methods changed to be remotable methods. + VERSION = '1.1' dbapi = db_api.get_instance() @@ -40,11 +41,7 @@ class VolumeConnector(base.IronicObject, 'extra': object_fields.FlexibleDictField(nullable=True), } - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get(cls, context, ident): """Find a volume connector based on its ID or UUID. @@ -63,11 +60,7 @@ class VolumeConnector(base.IronicObject, else: raise exception.InvalidIdentity(identity=ident) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_id(cls, context, db_id): """Find a volume connector based on its integer ID. @@ -83,11 +76,7 @@ class VolumeConnector(base.IronicObject, connector = cls._from_db_object(context, cls(), db_connector) return connector - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_uuid(cls, context, uuid): """Find a volume connector based on its UUID. @@ -102,11 +91,7 @@ class VolumeConnector(base.IronicObject, connector = cls._from_db_object(context, cls(), db_connector) return connector - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def list(cls, context, limit=None, marker=None, sort_key=None, sort_dir=None, project=None): """Return a list of VolumeConnector objects. @@ -127,11 +112,7 @@ class VolumeConnector(base.IronicObject, project=project) return cls._from_db_object_list(context, db_connectors) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def list_by_node_id(cls, context, node_id, limit=None, marker=None, sort_key=None, sort_dir=None, project=None): """Return a list of VolumeConnector objects related to a given node ID. @@ -156,10 +137,7 @@ class VolumeConnector(base.IronicObject, project=project) return cls._from_db_object_list(context, db_connectors) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def create(self, context=None): """Create a VolumeConnector record in the DB. @@ -178,10 +156,7 @@ class VolumeConnector(base.IronicObject, db_connector = self.dbapi.create_volume_connector(values) self._from_db_object(self._context, self, db_connector) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def destroy(self, context=None): """Delete the VolumeConnector from the DB. @@ -197,10 +172,7 @@ class VolumeConnector(base.IronicObject, self.dbapi.destroy_volume_connector(self.uuid) self.obj_reset_changes() - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def save(self, context=None): """Save updates to this VolumeConnector. @@ -225,10 +197,7 @@ class VolumeConnector(base.IronicObject, updates) self._from_db_object(self._context, self, updated_connector) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def refresh(self, context=None): """Load updates for this VolumeConnector. diff --git a/ironic/objects/volume_target.py b/ironic/objects/volume_target.py index 051d9ed9e73..f833c7844a2 100644 --- a/ironic/objects/volume_target.py +++ b/ironic/objects/volume_target.py @@ -27,7 +27,8 @@ from ironic.objects import notification class VolumeTarget(base.IronicObject, object_base.VersionedObjectDictCompat): # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.1: Relevant methods changed to be remotable methods. + VERSION = '1.1' dbapi = db_api.get_instance() @@ -42,11 +43,7 @@ class VolumeTarget(base.IronicObject, 'extra': object_fields.FlexibleDictField(nullable=True), } - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get(cls, context, ident): """Find a volume target based on its ID or UUID. @@ -65,11 +62,7 @@ class VolumeTarget(base.IronicObject, else: raise exception.InvalidIdentity(identity=ident) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_id(cls, context, db_id): """Find a volume target based on its database ID. @@ -83,11 +76,7 @@ class VolumeTarget(base.IronicObject, target = cls._from_db_object(context, cls(), db_target) return target - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def get_by_uuid(cls, context, uuid): """Find a volume target based on its UUID. @@ -101,11 +90,7 @@ class VolumeTarget(base.IronicObject, target = cls._from_db_object(context, cls(), db_target) return target - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def list(cls, context, limit=None, marker=None, sort_key=None, sort_dir=None, project=None): """Return a list of VolumeTarget objects. @@ -127,11 +112,7 @@ class VolumeTarget(base.IronicObject, project=project) return cls._from_db_object_list(context, db_targets) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def list_by_node_id(cls, context, node_id, limit=None, marker=None, sort_key=None, sort_dir=None, project=None): """Return a list of VolumeTarget objects related to a given node ID. @@ -156,11 +137,7 @@ class VolumeTarget(base.IronicObject, project=project) return cls._from_db_object_list(context, db_targets) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable_classmethod - @classmethod + @object_base.remotable_classmethod def list_by_volume_id(cls, context, volume_id, limit=None, marker=None, sort_key=None, sort_dir=None, project=None): """Return a list of VolumeTarget objects related to a given volume ID. @@ -184,10 +161,7 @@ class VolumeTarget(base.IronicObject, project=project) return cls._from_db_object_list(context, db_targets) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def create(self, context=None): """Create a VolumeTarget record in the DB. @@ -206,10 +180,7 @@ class VolumeTarget(base.IronicObject, db_target = self.dbapi.create_volume_target(values) self._from_db_object(self._context, self, db_target) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def destroy(self, context=None): """Delete the VolumeTarget from the DB. @@ -224,10 +195,7 @@ class VolumeTarget(base.IronicObject, self.dbapi.destroy_volume_target(self.uuid) self.obj_reset_changes() - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def save(self, context=None): """Save updates to this VolumeTarget. @@ -249,10 +217,7 @@ class VolumeTarget(base.IronicObject, updated_target = self.dbapi.update_volume_target(self.uuid, updates) self._from_db_object(self._context, self, updated_target) - # NOTE(xek): We don't want to enable RPC on this call just yet. Remotable - # methods can be used in the future to replace current explicit RPC calls. - # Implications of calling new remote procedures should be thought through. - # @object_base.remotable + @object_base.remotable def refresh(self, context=None): """Loads updates for this VolumeTarget. diff --git a/ironic/tests/unit/conductor/test_base_manager.py b/ironic/tests/unit/conductor/test_base_manager.py index 05fee8ef71e..a01edcf912c 100644 --- a/ironic/tests/unit/conductor/test_base_manager.py +++ b/ironic/tests/unit/conductor/test_base_manager.py @@ -309,7 +309,10 @@ class StartStopTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase): @mock.patch.object(dbapi, 'get_instance', autospec=True) def test_start_dbapi_single_call(self, mock_dbapi): self._start_service() - self.assertEqual(1, mock_dbapi.call_count) + # NOTE(TheJulia): This counts the dbapi instance count + # from starting the hash_ring, but since the hashring is + # common code, it shouldn't invoke a db call directly. + self.assertEqual(0, mock_dbapi.call_count) def test_start_with_json_rpc(self): CONF.set_override('rpc_transport', 'json-rpc') diff --git a/ironic/tests/unit/db/test_bios_settings.py b/ironic/tests/unit/db/test_bios_settings.py index 9cb077e07cc..9c80d0f70c9 100644 --- a/ironic/tests/unit/db/test_bios_settings.py +++ b/ironic/tests/unit/db/test_bios_settings.py @@ -29,7 +29,7 @@ class DbBIOSSettingTestCase(base.DbTestCase): self.assertEqual(result['node_id'], self.node.id) self.assertEqual(result['name'], 'virtualization') self.assertEqual(result['value'], 'on') - self.assertEqual(result['version'], '1.1') + self.assertEqual(result['version'], '1.2') def test_get_bios_setting_node_not_exist(self): self.assertRaises(exception.NodeNotFound, @@ -50,7 +50,7 @@ class DbBIOSSettingTestCase(base.DbTestCase): self.assertEqual(result[0]['node_id'], self.node.id) self.assertEqual(result[0]['name'], 'virtualization') self.assertEqual(result[0]['value'], 'on') - self.assertEqual(result[0]['version'], '1.1') + self.assertEqual(result[0]['version'], '1.2') self.assertEqual(len(result), 1) def test_get_bios_setting_list_node_not_exist(self): diff --git a/ironic/tests/unit/db/test_firmware_component.py b/ironic/tests/unit/db/test_firmware_component.py index 70431ca002d..54e78a7362a 100644 --- a/ironic/tests/unit/db/test_firmware_component.py +++ b/ironic/tests/unit/db/test_firmware_component.py @@ -63,7 +63,7 @@ class DbFirmwareComponentTestCase(base.DbTestCase): self.assertEqual(result[0]['node_id'], self.node.id) self.assertEqual(result[0]['component'], 'bmc') self.assertEqual(result[0]['initial_version'], 'v1.0.0') - self.assertEqual(result[0]['version'], '1.0') + self.assertEqual(result[0]['version'], '1.1') self.assertEqual(len(result), 1) def test_get_firmware_component_list_node_not_exist(self): diff --git a/ironic/tests/unit/db/test_nodes.py b/ironic/tests/unit/db/test_nodes.py index 82d6e451671..1b341d5fa35 100644 --- a/ironic/tests/unit/db/test_nodes.py +++ b/ironic/tests/unit/db/test_nodes.py @@ -798,7 +798,7 @@ class DbNodeTestCase(base.DbTestCase): created_at=second_timestamp, plugin_data={"pdata": {"plugin": "data"}}, - version='1.0') + version='1.1') self.assertJsonEqual(expected_inventory, node_inventory) def test_inventory_get_destroyed_after_destroying_a_node_by_uuid(self): diff --git a/ironic/tests/unit/objects/test_bios.py b/ironic/tests/unit/objects/test_bios.py index 9f7f4e7465b..e76897044ae 100644 --- a/ironic/tests/unit/objects/test_bios.py +++ b/ironic/tests/unit/objects/test_bios.py @@ -151,7 +151,7 @@ class TestBIOSSettingObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn): self.context, self.node_id, settings) mock_create_list.assert_called_once_with(mock.ANY, self.node_id, - settings, '1.1') + settings, '1.2') self.assertEqual(self.context, bios_obj_list._context) self.assertEqual(2, len(bios_obj_list)) self.assertEqual(self.bios_setting['node_id'], @@ -171,7 +171,7 @@ class TestBIOSSettingObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn): self.context, self.node_id, settings) mock_update_list.assert_called_once_with(mock.ANY, self.node_id, - settings, '1.1') + settings, '1.2') self.assertEqual(self.context, bios_obj_list._context) self.assertEqual(2, len(bios_obj_list)) self.assertEqual(self.bios_setting['node_id'], diff --git a/ironic/tests/unit/objects/test_objects.py b/ironic/tests/unit/objects/test_objects.py index 54ca8caf9ce..3deb6ec3291 100644 --- a/ironic/tests/unit/objects/test_objects.py +++ b/ironic/tests/unit/objects/test_objects.py @@ -675,12 +675,12 @@ class TestObject(_LocalTest, _TestObject): # version bump. It is an MD5 hash of the object fields and remotable methods. # The fingerprint values should only be changed if there is a version bump. expected_object_fingerprints = { - 'Node': '1.41-baff7b2b06243d97448b720030b2e612', + 'Node': '1.42-a1d3e6011e3cdb27aafa9353b7c0b6d4', 'MyObj': '1.5-9459d30d6954bffc7a9afd347a807ca6', - 'Chassis': '1.3-d656e039fd8ae9f34efc232ab3980905', - 'Port': '1.13-f79db5cc15189d3e8b257db582b2329e', - 'Portgroup': '1.5-df4dc15967f67114d51176a98a901a83', - 'Conductor': '1.5-c241d0c83c05c263b12c9b0289995462', + 'Chassis': '1.4-fe427272d8bad232a8d46e996a5ca42a', + 'Port': '1.14-684faad7173c1d9e8a2d630381c51903', + 'Portgroup': '1.6-ada5300518c2262766121a4333d92df3', + 'Conductor': '1.6-ed00540fae97aa1c9982f9017c6e8b68', 'EventType': '1.1-aa2ba1afd38553e3880c267404e8d370', 'NotificationPublisher': '1.0-51a09397d6c0687771fb5be9a999605d', 'NodePayload': '1.17-4022bb737b058d426a7ff878b1875e5c', @@ -692,8 +692,8 @@ expected_object_fingerprints = { 'NodeSetProvisionStateNotification': '1.0-59acc533c11d306f149846f922739c15', 'NodeSetProvisionStatePayload': '1.18-ac98c88d6dc8c6c924a415868f0a36e7', - 'VolumeConnector': '1.0-3e0252c0ab6e6b9d158d09238a577d97', - 'VolumeTarget': '1.0-0b10d663d8dae675900b2c7548f76f5e', + 'VolumeConnector': '1.1-658527dd56485af9a7375d517b57d5c7', + 'VolumeTarget': '1.1-ea229476f06db156e87ed547f1c539f4', 'ChassisCRUDNotification': '1.0-59acc533c11d306f149846f922739c15', 'ChassisCRUDPayload': '1.0-dce63895d8186279a7dd577cffccb202', 'NodeCRUDNotification': '1.0-59acc533c11d306f149846f922739c15', @@ -708,25 +708,25 @@ expected_object_fingerprints = { 'VolumeConnectorCRUDPayload': '1.0-5e8dbb41e05b6149d8f7bfd4daff9339', 'VolumeTargetCRUDNotification': '1.0-59acc533c11d306f149846f922739c15', 'VolumeTargetCRUDPayload': '1.0-30dcc4735512c104a3a36a2ae1e2aeb2', - 'Trait': '1.0-3f26cb70c8a10a3807d64c219453e347', - 'TraitList': '1.0-33a2e1bb91ad4082f9f63429b77c1244', - 'BIOSSetting': '1.1-1137db88675a4e2d7f7bcc3a0d52345a', - 'BIOSSettingList': '1.0-33a2e1bb91ad4082f9f63429b77c1244', - 'Allocation': '1.2-9aae5cc874a292af10ba08918ba21b13', + 'Trait': '1.1-ae534208fc5ade27700db7202b5b6b82', + 'TraitList': '1.1-1e938b9a94cba59f5ac35a5db0a6dc0f', + 'BIOSSetting': '1.2-a0c2924d8ffef7ed872e48435a569a83', + 'BIOSSettingList': '1.1-6e606655643a9a5fa116ce771cbebe59', + 'Allocation': '1.3-91102bce67725a4ee924c6b2f213bcde', 'AllocationCRUDNotification': '1.0-59acc533c11d306f149846f922739c15', 'AllocationCRUDPayload': '1.1-3c8849932b80380bb96587ff62e8f087', - 'DeployTemplate': '1.1-4e30c8e9098595e359bb907f095bf1a9', + 'DeployTemplate': '1.2-8b218ab0b3d30208adc601322abc2c50', 'DeployTemplateCRUDNotification': '1.0-59acc533c11d306f149846f922739c15', 'DeployTemplateCRUDPayload': '1.0-200857e7e715f58a5b6d6b700ab73a3b', - 'Deployment': '1.0-ff10ae028c5968f1596131d85d7f5f9d', - 'NodeHistory': '1.0-9b576c6481071e7f7eac97317fa29418', - 'NodeInventory': '1.0-97692fec24e20ab02022b9db54e8f539', - 'FirmwareComponent': '1.0-0e0720dab959e20247bbcfd5f28958c5', - 'FirmwareComponentList': '1.0-33a2e1bb91ad4082f9f63429b77c1244', - 'Runbook': '1.0-7a9c65b49b5f7b45686b6a674e703629', + 'Deployment': '1.1-1f326911955bbb1c24cb6ec0a453f6cc', + 'NodeHistory': '1.1-0879ccda2fce5e24cc0ada4116ada6b6', + 'NodeInventory': '1.1-acc176aeb9358c3866ceecdd13832b44', + 'FirmwareComponent': '1.1-3fc6cfd07d01b681b69d0b654b42745a', + 'FirmwareComponentList': '1.1-b1b32f4ead70f94f71913e39ea628eda', + 'Runbook': '1.1-019383ff9ef3b62a0d0726cb1ae8cbbf', 'RunbookCRUDNotification': '1.0-59acc533c11d306f149846f922739c15', 'RunbookCRUDPayload': '1.0-f0c97f4ff29eb3401e53b34550a95e30', - 'InspectionRule': '1.0-517185d327442696e408781343c2b83f', + 'InspectionRule': '1.1-6ee14959b85a90a13f3c7b48c53522c7', 'InspectionRuleCRUDNotification': '1.0-59acc533c11d306f149846f922739c15', 'InspectionRuleCRUDPayload': '1.0-85d1cf2105308534a630299a897bf562', } diff --git a/ironic/tests/unit/objects/test_trait.py b/ironic/tests/unit/objects/test_trait.py index ba18f6ace49..8f1c27f4492 100644 --- a/ironic/tests/unit/objects/test_trait.py +++ b/ironic/tests/unit/objects/test_trait.py @@ -49,7 +49,7 @@ class TestTraitObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn): result = objects.TraitList.create(self.context, self.node_id, traits) - mock_set_traits.assert_called_once_with(self.node_id, traits, '1.0') + mock_set_traits.assert_called_once_with(self.node_id, traits, '1.1') self.assertEqual(self.context, result._context) self.assertEqual(2, len(result)) self.assertEqual(self.fake_trait['node_id'], result[0].node_id) @@ -72,7 +72,7 @@ class TestTraitObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn): trait.create() - mock_add_trait.assert_called_once_with(self.node_id, 'fake', '1.0') + mock_add_trait.assert_called_once_with(self.node_id, 'fake', '1.1') self.assertEqual(self.fake_trait['trait'], trait.trait) self.assertEqual(self.fake_trait['node_id'], trait.node_id) diff --git a/releasenotes/notes/remotable-api-92d7b9bc7e843cd4.yaml b/releasenotes/notes/remotable-api-92d7b9bc7e843cd4.yaml new file mode 100644 index 00000000000..1b08643e59e --- /dev/null +++ b/releasenotes/notes/remotable-api-92d7b9bc7e843cd4.yaml @@ -0,0 +1,23 @@ +--- +features: + - | + Adds the capability for the Ironic API services to operate without + a direct connection to the Ironic database backend. Instead the + RPC Object model through the concept of remotable objects. + The ``[default]use_rpc_for_database`` setting can be utilized to + leverage this mode of operation, however it is also implied when + the ``[default]rpc_transport`` option is set to ``none`` or ``local``. +upgrade: + - | + The introduction of the capability to utilize remotable objects with + the API has resulted in object versions internally being incremented + without actual schema changes. This may result in an upgrade taking + a little longer, depending on the size of the database, + as object versions are updated during the upgrade sequence. +deprecations: + - | + Use of the API DBHook feature, i.e. the resulting ``api.request.dbapi`` + pattern in API service code is deprecated and the DBHook will be removed + in a future release of Ironic. Any downstream maintainers which utilize + this pattern are encouraged to utilize an object to serve as an + intermediary stepping stone between the API and the database.