ironic/ironic/tests/unit/objects/utils.py

427 lines
14 KiB
Python

# Copyright 2014 Rackspace Hosting
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Ironic object test utilities."""
import functools
import inspect
from ironic.common import exception
from ironic.common.i18n import _
from ironic import objects
from ironic.objects import notification
from ironic.tests.unit.db import utils as db_utils
def check_keyword_arguments(func):
@functools.wraps(func)
def wrapper(**kw):
obj_type = kw.pop('object_type')
result = func(**kw)
extra_args = set(kw) - set(result)
if extra_args:
raise exception.InvalidParameterValue(
_("Unknown keyword arguments (%(extra)s) were passed "
"while creating a test %(object_type)s object.") %
{"extra": ", ".join(extra_args),
"object_type": obj_type})
return result
return wrapper
def get_test_node(ctxt, **kw):
"""Return a Node object with appropriate attributes.
NOTE: The object leaves the attributes marked as changed, such
that a create() could be used to commit it to the DB.
"""
kw['object_type'] = 'node'
get_db_node_checked = check_keyword_arguments(db_utils.get_test_node)
db_node = get_db_node_checked(**kw)
# Let DB generate ID if it isn't specified explicitly
if 'id' not in kw:
del db_node['id']
node = objects.Node(ctxt)
for key in db_node:
if key == 'traits':
# convert list of strings to object
raw_traits = db_node['traits']
trait_list = []
for raw_trait in raw_traits:
trait = objects.Trait(ctxt, trait=raw_trait)
trait_list.append(trait)
node.traits = objects.TraitList(ctxt, objects=trait_list)
node.traits.obj_reset_changes()
else:
setattr(node, key, db_node[key])
return node
def create_test_node(ctxt, **kw):
"""Create and return a test node object.
Create a node in the DB and return a Node object with appropriate
attributes.
"""
node = get_test_node(ctxt, **kw)
node.create()
return node
def get_test_port(ctxt, **kw):
"""Return a Port object with appropriate attributes.
NOTE: The object leaves the attributes marked as changed, such
that a create() could be used to commit it to the DB.
"""
kw['object_type'] = 'port'
get_db_port_checked = check_keyword_arguments(
db_utils.get_test_port)
db_port = get_db_port_checked(**kw)
# Let DB generate ID if it isn't specified explicitly
if 'id' not in kw:
del db_port['id']
port = objects.Port(ctxt)
for key in db_port:
setattr(port, key, db_port[key])
return port
def create_test_port(ctxt, **kw):
"""Create and return a test port object.
Create a port in the DB and return a Port object with appropriate
attributes.
"""
port = get_test_port(ctxt, **kw)
port.create()
return port
def get_test_chassis(ctxt, **kw):
"""Return a Chassis object with appropriate attributes.
NOTE: The object leaves the attributes marked as changed, such
that a create() could be used to commit it to the DB.
"""
kw['object_type'] = 'chassis'
get_db_chassis_checked = check_keyword_arguments(
db_utils.get_test_chassis)
db_chassis = get_db_chassis_checked(**kw)
# Let DB generate ID if it isn't specified explicitly
if 'id' not in kw:
del db_chassis['id']
chassis = objects.Chassis(ctxt)
for key in db_chassis:
setattr(chassis, key, db_chassis[key])
return chassis
def create_test_chassis(ctxt, **kw):
"""Create and return a test chassis object.
Create a chassis in the DB and return a Chassis object with appropriate
attributes.
"""
chassis = get_test_chassis(ctxt, **kw)
chassis.create()
return chassis
def get_test_portgroup(ctxt, **kw):
"""Return a Portgroup object with appropriate attributes.
NOTE: The object leaves the attributes marked as changed, such
that a create() could be used to commit it to the DB.
"""
kw['object_type'] = 'portgroup'
get_db_port_group_checked = check_keyword_arguments(
db_utils.get_test_portgroup)
db_portgroup = get_db_port_group_checked(**kw)
# Let DB generate ID if it isn't specified explicitly
if 'id' not in kw:
del db_portgroup['id']
portgroup = objects.Portgroup(ctxt)
for key in db_portgroup:
setattr(portgroup, key, db_portgroup[key])
return portgroup
def create_test_portgroup(ctxt, **kw):
"""Create and return a test portgroup object.
Create a portgroup in the DB and return a Portgroup object with appropriate
attributes.
"""
portgroup = get_test_portgroup(ctxt, **kw)
portgroup.create()
return portgroup
def get_test_volume_connector(ctxt, **kw):
"""Return a VolumeConnector object with appropriate attributes.
NOTE: The object leaves the attributes marked as changed, such
that a create() could be used to commit it to the DB.
"""
db_volume_connector = db_utils.get_test_volume_connector(**kw)
# Let DB generate ID if it isn't specified explicitly
if 'id' not in kw:
del db_volume_connector['id']
volume_connector = objects.VolumeConnector(ctxt)
for key in db_volume_connector:
setattr(volume_connector, key, db_volume_connector[key])
return volume_connector
def create_test_volume_connector(ctxt, **kw):
"""Create and return a test volume connector object.
Create a volume connector in the DB and return a VolumeConnector object
with appropriate attributes.
"""
volume_connector = get_test_volume_connector(ctxt, **kw)
volume_connector.create()
return volume_connector
def get_test_volume_target(ctxt, **kw):
"""Return a VolumeTarget object with appropriate attributes.
NOTE: The object leaves the attributes marked as changed, such
that a create() could be used to commit it to the DB.
"""
db_volume_target = db_utils.get_test_volume_target(**kw)
# Let DB generate ID if it isn't specified explicitly
if 'id' not in kw:
del db_volume_target['id']
volume_target = objects.VolumeTarget(ctxt)
for key in db_volume_target:
setattr(volume_target, key, db_volume_target[key])
return volume_target
def create_test_volume_target(ctxt, **kw):
"""Create and return a test volume target object.
Create a volume target in the DB and return a VolumeTarget object with
appropriate attributes.
"""
volume_target = get_test_volume_target(ctxt, **kw)
volume_target.create()
return volume_target
def get_test_bios_setting(ctxt, **kw):
"""Return a BiosSettingList object with appropriate attributes.
NOTE: The object leaves the attributes marked as changed, such
that a create() could be used to commit it to the DB.
"""
kw['object_type'] = 'bios'
db_bios_setting = db_utils.get_test_bios_setting(**kw)
bios_setting = objects.BIOSSetting(ctxt)
for key in db_bios_setting:
setattr(bios_setting, key, db_bios_setting[key])
return bios_setting
def create_test_bios_setting(ctxt, **kw):
"""Create and return a test bios setting list object.
Create a BIOS setting list in the DB and return a BIOSSettingList
object with appropriate attributes.
"""
bios_setting = get_test_bios_setting(ctxt, **kw)
bios_setting.create()
return bios_setting
def create_test_conductor(ctxt, **kw):
"""Register and return a test conductor object."""
args = db_utils.get_test_conductor(**kw)
conductor = objects.Conductor.register(ctxt, args['hostname'],
args['drivers'],
args['conductor_group'],
update_existing=True)
return conductor
def get_test_allocation(ctxt, **kw):
"""Return an Allocation object with appropriate attributes.
NOTE: The object leaves the attributes marked as changed, such
that a create() could be used to commit it to the DB.
"""
kw['object_type'] = 'allocation'
get_db_allocation_checked = check_keyword_arguments(
db_utils.get_test_allocation)
db_allocation = get_db_allocation_checked(**kw)
# Let DB generate ID if it isn't specified explicitly
if 'id' not in kw:
del db_allocation['id']
allocation = objects.Allocation(ctxt)
for key in db_allocation:
setattr(allocation, key, db_allocation[key])
return allocation
def create_test_allocation(ctxt, **kw):
"""Create and return a test allocation object.
Create an allocation in the DB and return an Allocation object with
appropriate attributes.
"""
allocation = get_test_allocation(ctxt, **kw)
allocation.create()
return allocation
def get_test_deploy_template(ctxt, **kw):
"""Return a DeployTemplate object with appropriate attributes.
NOTE: The object leaves the attributes marked as changed, such
that a create() could be used to commit it to the DB.
"""
db_template = db_utils.get_test_deploy_template(**kw)
# Let DB generate ID if it isn't specified explicitly
if 'id' not in kw:
del db_template['id']
if 'steps' not in kw:
for step in db_template['steps']:
del step['id']
del step['deploy_template_id']
else:
for kw_step, template_step in zip(kw['steps'], db_template['steps']):
if 'id' not in kw_step and 'id' in template_step:
del template_step['id']
template = objects.DeployTemplate(ctxt)
for key in db_template:
setattr(template, key, db_template[key])
return template
def create_test_deploy_template(ctxt, **kw):
"""Create and return a test deploy template object.
NOTE: The object leaves the attributes marked as changed, such
that a create() could be used to commit it to the DB.
"""
template = get_test_deploy_template(ctxt, **kw)
template.create()
return template
def get_payloads_with_schemas(from_module):
"""Get the Payload classes with SCHEMAs defined.
:param from_module: module from which to get the classes.
:returns: list of Payload classes that have SCHEMAs defined.
"""
payloads = []
for name, payload in inspect.getmembers(from_module, inspect.isclass):
# Assume that Payload class names end in 'Payload'.
if name.endswith("Payload"):
base_classes = inspect.getmro(payload)
if notification.NotificationPayloadBase not in base_classes:
# The class may have the desired name but it isn't a REAL
# Payload class; skip it.
continue
# First class is this payload class, parent class is the 2nd
# one in the tuple
parent = base_classes[1]
if (not hasattr(parent, 'SCHEMA')
or parent.SCHEMA != payload.SCHEMA):
payloads.append(payload)
return payloads
class SchemasTestMixIn(object):
def _check_payload_schemas(self, from_module, fields):
"""Assert that the Payload SCHEMAs have the expected properties.
A payload's SCHEMA should:
1. Have each of its keys in the payload's fields
2. Have each member of the schema match with a corresponding field
in the object
"""
resource = from_module.__name__.split('.')[-1]
payloads = get_payloads_with_schemas(from_module)
for payload in payloads:
for schema_key in payload.SCHEMA:
self.assertIn(schema_key, payload.fields,
"for %s, schema key %s is not in fields"
% (payload, schema_key))
key = payload.SCHEMA[schema_key][1]
self.assertIn(key, fields,
"for %s, schema key %s has invalid %s "
"field %s" % (payload, schema_key, resource,
key))
def create_test_inventory(ctxt, node, **kw):
"""Create and return a test node inventory object."""
inv = objects.NodeInventory(ctxt)
if not isinstance(node, str):
node = node.id
kw['node_id'] = node
for key, value in kw.items():
setattr(inv, key, value)
inv.create()
return inv
def get_test_firmware_component(ctxt, **kw):
"""Return a FirmwareComponent object with appropriate attributes.
NOTE: The object leaves the attributes marked as changed, such
that a create() could be used to commit it to the DB.
"""
kw['object_type'] = 'firmware'
get_db_fw_checked = check_keyword_arguments(
db_utils.get_test_firmware_component)
db_fw_cmp = get_db_fw_checked(**kw)
if 'id' not in kw:
del db_fw_cmp['id']
fw_cmp = objects.FirmwareComponent(ctxt)
for key in db_fw_cmp:
setattr(fw_cmp, key, db_fw_cmp[key])
return fw_cmp
def create_test_firmware_component(ctxt, **kw):
"""Create and return a test Firmware Component object.
Create a Firmware Component in the DB and return a FirmwareComponent
object with appropriate attributes.
"""
fw_cmp = get_test_firmware_component(ctxt, **kw)
fw_cmp.create()
return fw_cmp