Use openstacksdk for ironic module

This patches removes the ironic-client dependency from the
ironic module in favor of openstacksdk.

Increase minimum required version of openstacksdk to use
recent added features.

Change-Id: I31964179835ad454e8205a59f483b419de4fb62d
This commit is contained in:
Riccardo Pittau 2019-07-22 23:14:06 +02:00
parent e6ece052ec
commit 3accdfbbc6
25 changed files with 442 additions and 471 deletions

View File

@ -13,9 +13,9 @@
import socket
from ironicclient import client
from ironicclient import exceptions as ironic_exc
import netaddr
import openstack
from openstack import exceptions as os_exc
from oslo_config import cfg
import retrying
@ -26,23 +26,14 @@ from ironic_inspector import utils
CONF = cfg.CONF
LOG = utils.getProcessingLogger(__name__)
# See https://docs.openstack.org/ironic/latest/contributor/states.html # noqa
# See https://docs.openstack.org/ironic/latest/contributor/states.html
VALID_STATES = frozenset(['enroll', 'manageable', 'inspecting', 'inspect wait',
'inspect failed'])
# States where an instance is deployed and an admin may be doing something.
VALID_ACTIVE_STATES = frozenset(['active', 'rescue'])
# 1.38 is the latest API version in the Queens release series, 10.1.0.
# 1.46 is the latest API version in the Rocky release series, 11.1.0.
# 1.56 is the latest API version in the Stein release series, 12.1.0
# NOTE(mgoddard): This should be updated with each release to ensure that
# inspector is able to use the latest ironic API. In particular, this version
# is used when processing introspection rules, and is the default version used
# by processing plugins.
DEFAULT_IRONIC_API_VERSION = ['1.38', '1.46', '1.56']
IRONIC_SESSION = None
_IRONIC_SESSION = None
class NotFound(utils.Error):
@ -53,13 +44,34 @@ class NotFound(utils.Error):
super(NotFound, self).__init__(msg, code, *args, **kwargs)
def _get_ironic_session():
global _IRONIC_SESSION
if not _IRONIC_SESSION:
_IRONIC_SESSION = keystone.get_session('ironic')
return _IRONIC_SESSION
def get_client(token=None):
"""Get an ironic client connection."""
session = _get_ironic_session()
try:
return openstack.connection.Connection(
session=session, oslo_conf=CONF).baremetal
except Exception as exc:
LOG.error('Failed to establish a connection with ironic, '
'reason: %s', exc)
raise
def reset_ironic_session():
"""Reset the global session variable.
Mostly useful for unit tests.
"""
global IRONIC_SESSION
IRONIC_SESSION = None
global _IRONIC_SESSION
_IRONIC_SESSION = None
def get_ipmi_address(node):
@ -111,33 +123,6 @@ def get_ipmi_address(node):
return none_address
def get_client(token=None,
api_version=DEFAULT_IRONIC_API_VERSION): # pragma: no cover
"""Get Ironic client instance."""
global IRONIC_SESSION
if not IRONIC_SESSION:
IRONIC_SESSION = keystone.get_session('ironic')
args = {
'session': IRONIC_SESSION,
'os_ironic_api_version': api_version,
'max_retries': CONF.ironic.max_retries,
'retry_interval': CONF.ironic.retry_interval
}
if token is not None:
args['token'] = token
endpoint = keystone.get_adapter('ironic',
session=IRONIC_SESSION).get_endpoint()
if not endpoint:
raise utils.Error(
_('Cannot find the bare metal endpoint either in Keystone or '
'in the configuration'), code=500)
return client.get_client(1, endpoint=endpoint, **args)
def check_provision_state(node):
"""Sanity checks the provision state of the node.
@ -188,16 +173,18 @@ def get_node(node_id, ironic=None, **kwargs):
ironic = ironic if ironic is not None else get_client()
try:
return ironic.node.get(node_id, **kwargs)
except ironic_exc.NotFound:
node = ironic.get_node(node_id, **kwargs)
node.uuid = node.id
except os_exc.ResourceNotFound:
raise NotFound(node_id)
except ironic_exc.HttpError as exc:
except os_exc.BadRequestException as exc:
raise utils.Error(_("Cannot get node %(node)s: %(exc)s") %
{'node': node_id, 'exc': exc})
return node
@retrying.retry(
retry_on_exception=lambda exc: isinstance(exc, ironic_exc.ClientException),
retry_on_exception=lambda exc: isinstance(exc, os_exc.SDKException),
stop_max_attempt_number=5, wait_fixed=1000)
def call_with_retries(func, *args, **kwargs):
"""Call an ironic client function retrying all errors.
@ -217,15 +204,16 @@ def lookup_node_by_macs(macs, introspection_data=None,
nodes = set()
for mac in macs:
ports = ironic.port.list(address=mac, fields=["uuid", "node_uuid"])
ports = ironic.ports(address=mac, fields=["uuid", "node_uuid"])
ports = list(ports)
if not ports:
continue
elif fail:
raise utils.Error(
_('Port %(mac)s already exists, uuid: %(uuid)s') %
{'mac': mac, 'uuid': ports[0].uuid}, data=introspection_data)
{'mac': mac, 'uuid': ports[0].id}, data=introspection_data)
else:
nodes.update(p.node_uuid for p in ports)
nodes.update(p.node_id for p in ports)
if len(nodes) > 1:
raise utils.Error(_('MAC addresses %(macs)s correspond to more than '
@ -233,6 +221,7 @@ def lookup_node_by_macs(macs, introspection_data=None,
{'macs': ', '.join(macs),
'nodes': ', '.join(nodes)},
data=introspection_data)
elif nodes:
return nodes.pop()
@ -245,7 +234,7 @@ def lookup_node_by_bmc_addresses(addresses, introspection_data=None,
# FIXME(aarefiev): it's not effective to fetch all nodes, and may
# impact on performance on big clusters
nodes = ironic.node.list(fields=('uuid', 'driver_info'), limit=0)
nodes = ironic.nodes(fields=('id', 'driver_info'), limit=None)
found = set()
for node in nodes:
bmc_address, bmc_ipv4, bmc_ipv6 = get_ipmi_address(node)
@ -255,10 +244,10 @@ def lookup_node_by_bmc_addresses(addresses, introspection_data=None,
elif fail:
raise utils.Error(
_('Node %(uuid)s already has BMC address %(addr)s') %
{'addr': addr, 'uuid': node.uuid},
{'addr': addr, 'uuid': node.id},
data=introspection_data)
else:
found.add(node.uuid)
found.add(node.id)
if len(found) > 1:
raise utils.Error(_('BMC addresses %(addr)s correspond to more than '

View File

@ -90,6 +90,7 @@ class ConductorManager(object):
(periodic_clean_up_, None, None)],
executor_factory=periodics.ExistingExecutor(utils.executor()),
on_failure=self._periodics_watchdog)
utils.executor().submit(self._periodics_worker.start)
if CONF.enable_mdns:
@ -203,6 +204,6 @@ def periodic_clean_up(): # pragma: no cover
def sync_with_ironic():
ironic = ir_utils.get_client()
# TODO(yuikotakada): pagination
ironic_nodes = ironic.node.list(limit=0)
ironic_node_uuids = {node.uuid for node in ironic_nodes}
ironic_nodes = ironic.nodes(fields=["uuid"], limit=None)
ironic_node_uuids = {node.id for node in ironic_nodes}
node_cache.delete_nodes_not_in_list(ironic_node_uuids)

View File

@ -16,6 +16,7 @@
import time
from eventlet import semaphore
from openstack import exceptions as os_exc
from oslo_config import cfg
from oslo_utils import strutils
@ -48,15 +49,15 @@ def introspect(node_id, manage_boot=True, token=None):
ir_utils.check_provision_state(node)
if manage_boot:
validation = ironic.node.validate(node.uuid)
if not validation.power['result']:
msg = _('Failed validation of power interface, reason: %s')
raise utils.Error(msg % validation.power['reason'],
node_info=node)
try:
ironic.validate_node(node.id, required='power')
except os_exc.ValidationException as exc:
msg = _('Failed validation of power interface: %s')
raise utils.Error(msg % exc, node_info=node)
bmc_address, bmc_ipv4, bmc_ipv6 = ir_utils.get_ipmi_address(node)
lookup_attrs = list(filter(None, [bmc_ipv4, bmc_ipv6]))
node_info = node_cache.start_introspection(node.uuid,
node_info = node_cache.start_introspection(node.id,
bmc_address=lookup_attrs,
manage_boot=manage_boot,
ironic=ironic)
@ -114,7 +115,7 @@ def _background_introspect_locked(node_info, ironic):
if node_info.manage_boot:
try:
ironic.node.set_boot_device(
ironic.set_node_boot_device(
node_info.uuid, 'pxe',
persistent=_persistent_ramdisk_boot(node_info.node()))
except Exception as exc:
@ -122,9 +123,9 @@ def _background_introspect_locked(node_info, ironic):
node_info=node_info)
try:
ironic.node.set_power_state(node_info.uuid, 'reboot')
ironic.set_node_power_state(node_info.uuid, 'rebooting')
except Exception as exc:
raise utils.Error(_('Failed to power on the node, check it\'s '
raise utils.Error(_('Failed to power on the node, check its '
'power management configuration: %s') % exc,
node_info=node_info)
LOG.info('Introspection started successfully',
@ -164,7 +165,7 @@ def _abort(node_info, ironic):
LOG.debug('Forcing power-off', node_info=node_info)
if node_info.manage_boot:
try:
ironic.node.set_power_state(node_info.uuid, 'off')
ironic.set_node_power_state(node_info.uuid, 'power off')
except Exception as exc:
LOG.warning('Failed to power off node: %s', exc,
node_info=node_info)

View File

@ -22,7 +22,7 @@ import json
import operator
from automaton import exceptions as automaton_errors
from ironicclient import exceptions
from openstack import exceptions as os_exc
from oslo_config import cfg
from oslo_db.sqlalchemy import utils as db_utils
from oslo_utils import excutils
@ -339,17 +339,17 @@ class NodeInfo(object):
for port in ports:
mac = port
extra = {}
pxe_enabled = True
is_pxe_enabled = True
if isinstance(port, dict):
mac = port['mac']
client_id = port.get('client_id')
if client_id:
extra = {'client-id': client_id}
pxe_enabled = port.get('pxe', True)
is_pxe_enabled = port.get('pxe', True)
if mac not in self.ports():
self._create_port(mac, ironic=ironic, extra=extra,
pxe_enabled=pxe_enabled)
is_pxe_enabled=is_pxe_enabled)
else:
existing_macs.append(mac)
@ -366,21 +366,21 @@ class NodeInfo(object):
"""
if self._ports is None:
ironic = ironic or self.ironic
port_list = ironic.node.list_ports(self.uuid, limit=0, detail=True)
port_list = ironic.ports(node=self.uuid, limit=None, details=True)
self._ports = {p.address: p for p in port_list}
return self._ports
def _create_port(self, mac, ironic=None, **kwargs):
ironic = ironic or self.ironic
try:
port = ironic.port.create(
port = ironic.create_port(
node_uuid=self.uuid, address=mac, **kwargs)
LOG.info('Port %(uuid)s was created successfully, MAC: %(mac)s,'
'attributes: %(attrs)s',
{'uuid': port.uuid, 'mac': port.address,
{'uuid': port.id, 'mac': port.address,
'attrs': kwargs},
node_info=self)
except exceptions.Conflict:
except os_exc.ConflictException:
LOG.warning('Port %s already exists, skipping',
mac, node_info=self)
# NOTE(dtantsur): we didn't get port object back, so we have to
@ -397,7 +397,7 @@ class NodeInfo(object):
:param patches: JSON patches to apply
:param ironic: Ironic client to use instead of self.ironic
:param kwargs: Arguments to pass to ironicclient.
:raises: ironicclient exceptions
:raises: openstacksdk exceptions
"""
ironic = ironic or self.ironic
# NOTE(aarefiev): support path w/o ahead forward slash
@ -407,7 +407,7 @@ class NodeInfo(object):
patch['path'] = '/' + patch['path']
LOG.debug('Updating node with patches %s', patches, node_info=self)
self._node = ironic.node.update(self.uuid, patches, **kwargs)
self._node = ironic.patch_node(self.uuid, patches, **kwargs)
def patch_port(self, port, patches, ironic=None):
"""Apply JSON patches to a port.
@ -424,7 +424,7 @@ class NodeInfo(object):
LOG.debug('Updating port %(mac)s with patches %(patches)s',
{'mac': port.address, 'patches': patches},
node_info=self)
new_port = ironic.port.update(port.uuid, patches)
new_port = ironic.patch_port(port.id, patches)
ports[port.address] = new_port
def update_properties(self, ironic=None, **props):
@ -458,7 +458,7 @@ class NodeInfo(object):
:param ironic: Ironic client to use instead of self.ironic
"""
ironic = ironic or self.ironic
ironic.node.add_trait(self.uuid, trait)
ironic.add_node_trait(self.uuid, trait)
def remove_trait(self, trait, ironic=None):
"""Remove a trait from the node.
@ -468,8 +468,8 @@ class NodeInfo(object):
"""
ironic = ironic or self.ironic
try:
ironic.node.remove_trait(self.uuid, trait)
except exceptions.NotFound:
ironic.remove_node_trait(self.uuid, trait)
except os_exc.NotFoundException:
LOG.debug('Trait %s is not set, cannot remove', trait,
node_info=self)
@ -484,7 +484,7 @@ class NodeInfo(object):
if isinstance(port, str):
port = ports[port]
ironic.port.delete(port.uuid)
ironic.delete_port(port.id)
del ports[port.address]
def get_by_path(self, path):
@ -919,12 +919,12 @@ def create_node(driver, ironic=None, **attributes):
if ironic is None:
ironic = ir_utils.get_client()
try:
node = ironic.node.create(driver=driver, **attributes)
except exceptions.InvalidAttribute as e:
node = ironic.create_node(driver=driver, **attributes)
except os_exc.SDKException as e:
LOG.error('Failed to create new node: %s', e)
else:
LOG.info('Node %s was created successfully', node.uuid)
return add_node(node.uuid, istate.States.enrolling, ironic=ironic)
LOG.info('Node %s was created successfully', node.id)
return add_node(node.id, istate.States.enrolling, ironic=ironic)
def record_node(ironic=None, bmc_addresses=None, macs=None):
@ -953,7 +953,7 @@ def record_node(ironic=None, bmc_addresses=None, macs=None):
"and BMC address(es) %(addr)s") %
{'macs': macs, 'addr': bmc_addresses})
node = ironic.node.get(node, fields=['uuid', 'provision_state'])
node = ironic.get_node(node, fields=['uuid', 'provision_state'])
# TODO(dtantsur): do we want to allow updates in all states?
if node.provision_state not in ir_utils.VALID_ACTIVE_STATES:
raise utils.Error(_("Node %(node)s is not active, its provision "

View File

@ -68,9 +68,15 @@ def enroll_node_not_found_hook(introspection_data, **kwargs):
node_driver_info = _extract_node_driver_info(introspection_data)
node_attr['driver_info'] = node_driver_info
# NOTE(rpittau) by default, if the provision_state is None, it will
# be set to 'available' by openstacksdk, blocking the inspection of the
# node in this phase, as it's not a valid state for inspection.
node_attr['provision_state'] = 'enroll'
node_driver = CONF.discovery.enroll_node_driver
_check_existing_nodes(introspection_data, node_driver_info, ironic)
LOG.debug('Creating discovered node with driver %(driver)s and '
'attributes: %(attr)s',
{'driver': node_driver, 'attr': node_attr},

View File

@ -16,8 +16,8 @@
import operator
import re
from ironicclient import exceptions as ironic_exc
import netaddr
from openstack import exceptions as os_exc
from ironic_inspector.common.i18n import _
from ironic_inspector.plugins import base
@ -138,7 +138,7 @@ class SetAttributeAction(base.RuleActionPlugin):
try:
node_info.patch([{'op': 'add', 'path': params['path'],
'value': params['value']}], **kwargs)
except (TypeError, ironic_exc.NotAcceptable):
except (TypeError, os_exc.SDKException):
# TODO(dtantsur): remove support for old ironicclient and Queens
if 'reset_interfaces' in params:
# An explicit request, report an error.

View File

@ -296,7 +296,7 @@ class ValidateInterfacesHook(base.ProcessingHook):
node_info.delete_port(port)
if CONF.processing.overwrite_existing:
# Make sure pxe_enabled is up-to-date
# Make sure is_pxe_enabled is up-to-date
ports = node_info.ports()
for iface in introspection_data['interfaces'].values():
try:
@ -305,8 +305,8 @@ class ValidateInterfacesHook(base.ProcessingHook):
continue
real_pxe = iface.get('pxe', True)
if port.pxe_enabled != real_pxe:
LOG.info('Fixing pxe_enabled=%(val)s on port %(port)s '
if port.is_pxe_enabled != real_pxe:
LOG.info('Fixing is_pxe_enabled=%(val)s on port %(port)s '
'to match introspected data',
{'port': port.address, 'val': real_pxe},
node_info=node_info, data=introspection_data)

View File

@ -283,7 +283,7 @@ def _process_node(node_info, node, introspection_data):
node_info.invalidate_cache()
rules.apply(node_info, introspection_data)
resp = {'uuid': node.uuid}
resp = {'uuid': node.id}
# determine how to handle power
if keep_power_on or not node_info.manage_boot:
@ -301,7 +301,7 @@ def _finish(node_info, ironic, introspection_data, power_off=True):
if power_off:
LOG.debug('Forcing power off of node %s', node_info.uuid)
try:
ironic.node.set_power_state(node_info.uuid, 'off')
ironic.set_node_power_state(node_info.uuid, 'power off')
except Exception as exc:
if node_info.node().provision_state == 'enroll':
LOG.info("Failed to power off the node in"

View File

@ -182,11 +182,14 @@ class BaseFilter(interface.FilterDriver):
:raises: periodics.NeverAgain
:returns: a periodic task to be run in the background.
"""
ironic = ir_utils.get_client()
_cached_client = None
def periodic_sync_task():
nonlocal _cached_client
if _cached_client is None:
_cached_client = ir_utils.get_client()
try:
self.sync(ironic)
self.sync(_cached_client)
except InvalidFilterDriverState as e:
LOG.warning('Filter driver %s disabling periodic sync '
'task because of an invalid state.', self)

View File

@ -87,7 +87,7 @@ class DnsmasqFilter(pxe_filter.BaseFilter):
active_macs = node_cache.active_macs()
# ironic_macs are all the MACs know to ironic (all ironic ports)
ironic_macs = set(port.address for port in
ir_utils.call_with_retries(ironic.port.list, limit=0,
ir_utils.call_with_retries(ironic.ports, limit=None,
fields=['address']))
blacklist, whitelist = _get_black_white_lists()
# removedlist are the MACs that are in either blacklist or whitelist,

View File

@ -232,7 +232,7 @@ def _ib_mac_to_rmac_mapping(ports):
def _get_blacklist(ironic):
ports = [port for port in
ir_utils.call_with_retries(ironic.port.list, limit=0,
ir_utils.call_with_retries(ironic.ports, limit=None,
fields=['address', 'extra'])
if port.address not in node_cache.active_macs()]
_ib_mac_to_rmac_mapping(ports)

View File

@ -171,17 +171,23 @@ class NodeTest(InventoryTest):
def setUp(self):
super(NodeTest, self).setUp()
self.uuid = uuidutils.generate_uuid()
fake_node = {
'driver': 'ipmi',
'driver_info': {'ipmi_address': self.bmc_address},
'properties': {'cpu_arch': 'i386', 'local_gb': 40},
'uuid': self.uuid,
'id': self.uuid,
'power_state': 'power on',
'provision_state': 'inspecting',
'extra': {},
'instance_uuid': None,
'maintenance': False
}
# TODO(rpittau) the correct value is id, not uuid, based on the
# openstacksdk schema. The code and the fake_node date are correct
# but all the tests still use uuid, so just making it equal to id
# until we find the courage to change it in all tests.
fake_node['uuid'] = fake_node['id']
mock_to_dict = mock.Mock(return_value=fake_node)
self.node = mock.Mock(**fake_node)

View File

@ -114,9 +114,9 @@ class Base(base.NodeTest):
self.cli_fixture = self.useFixture(
fixtures.MockPatchObject(ir_utils, 'get_client'))
self.cli = self.cli_fixture.mock.return_value
self.cli.node.get.return_value = self.node
self.cli.node.update.return_value = self.node
self.cli.node.list.return_value = [self.node]
self.cli.get_node.return_value = self.node
self.cli.patch_node.return_value = self.node
self.cli.nodes.return_value = [self.node]
self.patch = [
{'op': 'add', 'path': '/properties/cpus', 'value': '4'},
@ -249,8 +249,8 @@ class Test(Base):
def test_bmc(self):
self.call_introspect(self.uuid)
eventlet.greenthread.sleep(DEFAULT_SLEEP)
self.cli.node.set_power_state.assert_called_once_with(self.uuid,
'reboot')
self.cli.set_node_power_state.assert_called_once_with(self.uuid,
'rebooting')
status = self.call_get_status(self.uuid)
self.check_status(status, finished=False, state=istate.States.waiting)
@ -259,12 +259,12 @@ class Test(Base):
self.assertEqual({'uuid': self.uuid}, res)
eventlet.greenthread.sleep(DEFAULT_SLEEP)
self.cli.node.update.assert_called_with(self.uuid, mock.ANY)
self.assertCalledWithPatch(self.patch, self.cli.node.update)
self.cli.port.create.assert_called_once_with(
self.cli.patch_node.assert_called_with(self.uuid, mock.ANY)
self.assertCalledWithPatch(self.patch, self.cli.patch_node)
self.cli.create_port.assert_called_once_with(
node_uuid=self.uuid, address='11:22:33:44:55:66', extra={},
pxe_enabled=True)
self.assertTrue(self.cli.node.set_boot_device.called)
is_pxe_enabled=True)
self.assertTrue(self.cli.set_node_boot_device.called)
status = self.call_get_status(self.uuid)
self.check_status(status, finished=True, state=istate.States.finished)
@ -275,22 +275,22 @@ class Test(Base):
uuid_to_delete = uuidutils.generate_uuid()
uuid_to_update = uuidutils.generate_uuid()
# Two ports already exist: one with incorrect pxe_enabled, the other
# Two ports already exist: one with incorrect is_pxe_enabled, the other
# should be deleted.
self.cli.node.list_ports.return_value = [
mock.Mock(address=self.macs[1], uuid=uuid_to_update,
node_uuid=self.uuid, extra={}, pxe_enabled=True),
mock.Mock(address='foobar', uuid=uuid_to_delete,
node_uuid=self.uuid, extra={}, pxe_enabled=True),
self.cli.ports.return_value = [
mock.Mock(address=self.macs[1], id=uuid_to_update,
node_id=self.uuid, extra={}, is_pxe_enabled=True),
mock.Mock(address='foobar', id=uuid_to_delete,
node_id=self.uuid, extra={}, is_pxe_enabled=True),
]
# Two more ports are created, one with client_id. Make sure the
# returned object has the same properties as requested in create().
self.cli.port.create.side_effect = mock.Mock
self.cli.create_port.side_effect = mock.Mock
self.call_introspect(self.uuid)
eventlet.greenthread.sleep(DEFAULT_SLEEP)
self.cli.node.set_power_state.assert_called_once_with(self.uuid,
'reboot')
self.cli.set_node_power_state.assert_called_once_with(self.uuid,
'rebooting')
status = self.call_get_status(self.uuid)
self.check_status(status, finished=False, state=istate.States.waiting)
@ -299,17 +299,18 @@ class Test(Base):
self.assertEqual({'uuid': self.uuid}, res)
eventlet.greenthread.sleep(DEFAULT_SLEEP)
self.cli.node.update.assert_called_with(self.uuid, mock.ANY)
self.assertCalledWithPatch(self.patch, self.cli.node.update)
self.cli.patch_node.assert_called_with(self.uuid, mock.ANY)
self.assertCalledWithPatch(self.patch, self.cli.patch_node)
calls = [
mock.call(node_uuid=self.uuid, address=self.macs[0],
extra={}, pxe_enabled=True),
extra={}, is_pxe_enabled=True),
mock.call(node_uuid=self.uuid, address=self.macs[2],
extra={'client-id': self.client_id}, pxe_enabled=False),
extra={'client-id': self.client_id},
is_pxe_enabled=False),
]
self.cli.port.create.assert_has_calls(calls, any_order=True)
self.cli.port.delete.assert_called_once_with(uuid_to_delete)
self.cli.port.update.assert_called_once_with(
self.cli.create_port.assert_has_calls(calls, any_order=True)
self.cli.delete_port.assert_called_once_with(uuid_to_delete)
self.cli.patch_port.assert_called_once_with(
uuid_to_update,
[{'op': 'replace', 'path': '/pxe_enabled', 'value': False}])
@ -369,7 +370,7 @@ class Test(Base):
def test_manage_boot(self):
self.call_introspect(self.uuid, manage_boot=False)
eventlet.greenthread.sleep(DEFAULT_SLEEP)
self.assertFalse(self.cli.node.set_power_state.called)
self.assertFalse(self.cli.set_node_power_state.called)
status = self.call_get_status(self.uuid)
self.check_status(status, finished=False, state=istate.States.waiting)
@ -378,8 +379,8 @@ class Test(Base):
self.assertEqual({'uuid': self.uuid}, res)
eventlet.greenthread.sleep(DEFAULT_SLEEP)
self.cli.node.update.assert_called_with(self.uuid, mock.ANY)
self.assertFalse(self.cli.node.set_boot_device.called)
self.cli.patch_node.assert_called_with(self.uuid, mock.ANY)
self.assertFalse(self.cli.set_node_boot_device.called)
status = self.call_get_status(self.uuid)
self.check_status(status, finished=True, state=istate.States.finished)
@ -476,7 +477,7 @@ class Test(Base):
self.call_continue(self.data)
eventlet.greenthread.sleep(DEFAULT_SLEEP)
self.cli.node.update.assert_any_call(
self.cli.patch_node.assert_any_call(
self.uuid,
[{'op': 'add', 'path': '/extra/foo', 'value': 'bar'}])
@ -514,11 +515,11 @@ class Test(Base):
self.call_continue(self.data)
eventlet.greenthread.sleep(DEFAULT_SLEEP)
self.cli.node.update.assert_any_call(
self.cli.patch_node.assert_any_call(
self.uuid,
[{'op': 'add', 'path': '/extra/foo', 'value': 'bar'}])
self.cli.node.update.assert_any_call(
self.cli.patch_node.assert_any_call(
self.uuid,
[{'op': 'add', 'path': '/driver_info/ipmi_address',
'value': self.data['inventory']['bmc_address']}])
@ -528,8 +529,8 @@ class Test(Base):
self.call_introspect(self.uuid)
eventlet.greenthread.sleep(DEFAULT_SLEEP)
self.cli.node.set_power_state.assert_called_once_with(self.uuid,
'reboot')
self.cli.set_node_power_state.assert_called_once_with(self.uuid,
'rebooting')
status = self.call_get_status(self.uuid)
self.check_status(status, finished=False, state=istate.States.waiting)
@ -538,10 +539,10 @@ class Test(Base):
self.assertEqual({'uuid': self.uuid}, res)
eventlet.greenthread.sleep(DEFAULT_SLEEP)
self.assertCalledWithPatch(self.patch_root_hints, self.cli.node.update)
self.cli.port.create.assert_called_once_with(
self.assertCalledWithPatch(self.patch_root_hints, self.cli.patch_node)
self.cli.create_port.assert_called_once_with(
node_uuid=self.uuid, address='11:22:33:44:55:66', extra={},
pxe_enabled=True)
is_pxe_enabled=True)
status = self.call_get_status(self.uuid)
self.check_status(status, finished=True, state=istate.States.finished)
@ -549,8 +550,8 @@ class Test(Base):
def test_abort_introspection(self):
self.call_introspect(self.uuid)
eventlet.greenthread.sleep(DEFAULT_SLEEP)
self.cli.node.set_power_state.assert_called_once_with(self.uuid,
'reboot')
self.cli.set_node_power_state.assert_called_once_with(self.uuid,
'rebooting')
status = self.call_get_status(self.uuid)
self.check_status(status, finished=False, state=istate.States.waiting)
@ -573,8 +574,8 @@ class Test(Base):
def test_stored_data_processing(self):
self.call_introspect(self.uuid)
eventlet.greenthread.sleep(DEFAULT_SLEEP)
self.cli.node.set_power_state.assert_called_once_with(self.uuid,
'reboot')
self.cli.set_node_power_state.assert_called_once_with(self.uuid,
'rebooting')
res = self.call_continue(self.data)
self.assertEqual({'uuid': self.uuid}, res)
@ -681,8 +682,8 @@ class Test(Base):
self.call_introspect(self.uuid)
eventlet.greenthread.sleep(DEFAULT_SLEEP)
self.cli.node.set_power_state.assert_called_once_with(self.uuid,
'reboot')
self.cli.set_node_power_state.assert_called_once_with(self.uuid,
'rebooting')
status = self.call_get_status(self.uuid)
self.check_status(status, finished=False, state=istate.States.waiting)
@ -691,11 +692,11 @@ class Test(Base):
self.assertEqual({'uuid': self.uuid}, res)
eventlet.greenthread.sleep(DEFAULT_SLEEP)
self.cli.node.update.assert_called_with(self.uuid, mock.ANY)
self.assertCalledWithPatch(self.patch, self.cli.node.update)
self.cli.port.create.assert_called_once_with(
self.cli.patch_node.assert_called_with(self.uuid, mock.ANY)
self.assertCalledWithPatch(self.patch, self.cli.patch_node)
self.cli.create_port.assert_called_once_with(
node_uuid=self.uuid, extra={}, address='11:22:33:44:55:66',
pxe_enabled=True)
is_pxe_enabled=True)
status = self.call_get_status(self.uuid)
self.check_status(status, finished=True, state=istate.States.finished)
@ -703,8 +704,8 @@ class Test(Base):
def test_lldp_plugin(self):
self.call_introspect(self.uuid)
eventlet.greenthread.sleep(DEFAULT_SLEEP)
self.cli.node.set_power_state.assert_called_once_with(self.uuid,
'reboot')
self.cli.set_node_power_state.assert_called_once_with(self.uuid,
'rebooting')
status = self.call_get_status(self.uuid)
self.check_status(status, finished=False, state=istate.States.waiting)
@ -730,8 +731,8 @@ class Test(Base):
cfg.CONF.set_override('permit_active_introspection', True,
'processing')
self.node.provision_state = 'active'
self.cli.node.list_ports.return_value = [
mock.Mock(address='11:22:33:44:55:66', node_uuid=self.node.uuid)
self.cli.ports.return_value = [
mock.Mock(address='11:22:33:44:55:66', node_id=self.node.uuid)
]
# NOTE(dtantsur): we're not starting introspection in this test.
@ -739,10 +740,10 @@ class Test(Base):
self.assertEqual({'uuid': self.uuid}, res)
eventlet.greenthread.sleep(DEFAULT_SLEEP)
self.cli.node.update.assert_called_with(self.uuid, mock.ANY)
self.assertCalledWithPatch(self.patch, self.cli.node.update)
self.assertFalse(self.cli.port.create.called)
self.assertFalse(self.cli.node.set_boot_device.called)
self.cli.patch_node.assert_called_with(self.uuid, mock.ANY)
self.assertCalledWithPatch(self.patch, self.cli.patch_node)
self.assertFalse(self.cli.create_port.called)
self.assertFalse(self.cli.set_node_boot_device.called)
status = self.call_get_status(self.uuid)
self.check_status(status, finished=True, state=istate.States.finished)
@ -751,9 +752,9 @@ class Test(Base):
# Start with a normal introspection as a pre-requisite
self.test_bmc()
self.cli.node.update.reset_mock()
self.cli.node.set_boot_device.reset_mock()
self.cli.port.create.reset_mock()
self.cli.patch_node.reset_mock()
self.cli.set_node_boot_device.reset_mock()
self.cli.create_port.reset_mock()
# Provide some updates
self.data['inventory']['memory']['physical_mb'] = 16384
self.patch = [

View File

@ -14,10 +14,9 @@
import socket
import unittest
from ironicclient import client
from ironicclient import exc as ironic_exc
import mock
from oslo_config import cfg
import openstack
from openstack import exceptions as os_exc
from ironic_inspector.common import ironic as ir_utils
from ironic_inspector.common import keystone
@ -25,59 +24,16 @@ from ironic_inspector.test import base
from ironic_inspector import utils
CONF = cfg.CONF
class TestGetClientBase(object):
def test_get_client_with_auth_token(self, mock_client, mock_load,
mock_opts, mock_adapter):
fake_token = 'token'
mock_sess = mock.Mock()
mock_load.return_value = mock_sess
ir_utils.get_client(fake_token)
args = {'token': fake_token,
'session': mock_sess,
'os_ironic_api_version': ir_utils.DEFAULT_IRONIC_API_VERSION,
'max_retries': CONF.ironic.max_retries,
'retry_interval': CONF.ironic.retry_interval}
endpoint = mock_adapter.return_value.get_endpoint.return_value
mock_client.assert_called_once_with(1, endpoint=endpoint, **args)
def test_get_client_without_auth_token(self, mock_client, mock_load,
mock_opts, mock_adapter):
mock_sess = mock.Mock()
mock_load.return_value = mock_sess
ir_utils.get_client(None)
args = {'session': mock_sess,
'os_ironic_api_version': ir_utils.DEFAULT_IRONIC_API_VERSION,
'max_retries': CONF.ironic.max_retries,
'retry_interval': CONF.ironic.retry_interval}
endpoint = mock_adapter.return_value.get_endpoint.return_value
mock_client.assert_called_once_with(1, endpoint=endpoint, **args)
@mock.patch.object(keystone, 'get_adapter')
@mock.patch.object(keystone, 'register_auth_opts')
@mock.patch.object(keystone, 'get_session')
@mock.patch.object(client, 'get_client', autospec=True)
class TestGetClientAuth(TestGetClientBase, base.BaseTest):
@mock.patch.object(openstack.connection, 'Connection', autospec=True)
class TestGetClientBase(base.BaseTest):
def setUp(self):
super(TestGetClientAuth, self).setUp()
super(TestGetClientBase, self).setUp()
ir_utils.reset_ironic_session()
self.cfg.config(auth_strategy='keystone')
self.addCleanup(ir_utils.reset_ironic_session)
@mock.patch.object(keystone, 'get_adapter')
@mock.patch.object(keystone, 'register_auth_opts')
@mock.patch.object(keystone, 'get_session')
@mock.patch.object(client, 'get_client', autospec=True)
class TestGetClientNoAuth(TestGetClientBase, base.BaseTest):
def setUp(self):
super(TestGetClientNoAuth, self).setUp()
ir_utils.reset_ironic_session()
self.cfg.config(auth_strategy='noauth')
self.addCleanup(ir_utils.reset_ironic_session)
def test_get_client(self, mock_connection, mock_session):
ir_utils.get_client()
self.assertEqual(1, mock_session.call_count)
class TestGetIpmiAddress(base.BaseTest):
@ -178,7 +134,7 @@ class TestCallWithRetries(unittest.TestCase):
@mock.patch('time.sleep', lambda _x: None)
def test_retries_on_ironicclient_error(self):
self.call.side_effect = [
ironic_exc.ClientException('boom')
os_exc.SDKException('boom')
] * 3 + [mock.sentinel.result]
result = ir_utils.call_with_retries(self.call, 'meow', answer=42)
@ -188,8 +144,8 @@ class TestCallWithRetries(unittest.TestCase):
@mock.patch('time.sleep', lambda _x: None)
def test_retries_on_ironicclient_error_with_failure(self):
self.call.side_effect = ironic_exc.ClientException('boom')
self.assertRaisesRegexp(ironic_exc.ClientException, 'boom',
self.call.side_effect = os_exc.SDKException('boom')
self.assertRaisesRegexp(os_exc.SDKException, 'boom',
ir_utils.call_with_retries,
self.call, 'meow', answer=42)
self.call.assert_called_with('meow', answer=42)
@ -199,13 +155,13 @@ class TestCallWithRetries(unittest.TestCase):
class TestLookupNode(base.NodeTest):
def setUp(self):
super(TestLookupNode, self).setUp()
self.ironic = mock.Mock(spec=['node', 'port'],
node=mock.Mock(spec=['list']),
port=mock.Mock(spec=['list']))
self.ironic.node.list.return_value = [self.node]
self.ironic = mock.Mock(spec=['nodes', 'ports'],
nodes=mock.Mock(spec=['list']),
ports=mock.Mock(spec=['list']))
self.ironic.nodes.return_value = [self.node]
# Simulate only the PXE port enrolled
self.port = mock.Mock(address=self.pxe_mac, node_uuid=self.node.uuid)
self.ironic.port.list.side_effect = [
self.port = mock.Mock(address=self.pxe_mac, node_id=self.node.uuid)
self.ironic.ports.side_effect = [
[self.port]
] + [[]] * (len(self.macs) - 1)
@ -215,20 +171,20 @@ class TestLookupNode(base.NodeTest):
def test_lookup_by_mac_only(self):
uuid = ir_utils.lookup_node(macs=self.macs, ironic=self.ironic)
self.assertEqual(self.node.uuid, uuid)
self.ironic.port.list.assert_has_calls([
self.ironic.ports.assert_has_calls([
mock.call(address=mac,
fields=['uuid', 'node_uuid']) for mac in self.macs
])
def test_lookup_by_mac_duplicates(self):
self.ironic.port.list.side_effect = [
self.ironic.ports.side_effect = [
[self.port],
[mock.Mock(address=self.inactive_mac, node_uuid='another')]
[mock.Mock(address=self.inactive_mac, node_id='another')]
] + [[]] * (len(self.macs) - 1)
self.assertRaisesRegex(utils.Error, 'more than one node',
ir_utils.lookup_node,
macs=self.macs, ironic=self.ironic)
self.ironic.port.list.assert_has_calls([
self.ironic.ports.assert_has_calls([
mock.call(address=mac,
fields=['uuid', 'node_uuid']) for mac in self.macs
])
@ -238,12 +194,12 @@ class TestLookupNode(base.NodeTest):
'42.42.42.42'],
ironic=self.ironic)
self.assertEqual(self.node.uuid, uuid)
self.assertEqual(1, self.ironic.node.list.call_count)
self.assertEqual(1, self.ironic.nodes.call_count)
def test_lookup_by_bmc_duplicates(self):
self.ironic.node.list.return_value = [
self.ironic.nodes.return_value = [
self.node,
mock.Mock(uuid='another',
mock.Mock(id='another',
driver_info={'ipmi_address': '42.42.42.42'}),
]
self.assertRaisesRegex(utils.Error, 'more than one node',
@ -251,7 +207,7 @@ class TestLookupNode(base.NodeTest):
bmc_addresses=[self.bmc_address,
'42.42.42.42'],
ironic=self.ironic)
self.assertEqual(1, self.ironic.node.list.call_count)
self.assertEqual(1, self.ironic.nodes.call_count)
def test_lookup_by_both(self):
uuid = ir_utils.lookup_node(bmc_addresses=[self.bmc_address,
@ -259,15 +215,15 @@ class TestLookupNode(base.NodeTest):
macs=self.macs,
ironic=self.ironic)
self.assertEqual(self.node.uuid, uuid)
self.ironic.port.list.assert_has_calls([
self.ironic.ports.assert_has_calls([
mock.call(address=mac,
fields=['uuid', 'node_uuid']) for mac in self.macs
])
self.assertEqual(1, self.ironic.node.list.call_count)
self.assertEqual(1, self.ironic.nodes.call_count)
def test_lookup_by_both_duplicates(self):
self.ironic.port.list.side_effect = [
[mock.Mock(address=self.inactive_mac, node_uuid='another')]
self.ironic.ports.side_effect = [
[mock.Mock(address=self.inactive_mac, node_id='another')]
] + [[]] * (len(self.macs) - 1)
self.assertRaisesRegex(utils.Error, 'correspond to different nodes',
ir_utils.lookup_node,
@ -275,8 +231,8 @@ class TestLookupNode(base.NodeTest):
self.bmc_v6address],
macs=self.macs,
ironic=self.ironic)
self.ironic.port.list.assert_has_calls([
self.ironic.ports.assert_has_calls([
mock.call(address=mac,
fields=['uuid', 'node_uuid']) for mac in self.macs
])
self.assertEqual(1, self.ironic.node.list.call_count)
self.assertEqual(1, self.ironic.nodes.call_count)

View File

@ -20,8 +20,8 @@ import datetime
import os
import fixtures
from ironicclient import exc as ironic_exc
import mock
from openstack import exceptions as os_exc
from oslo_config import cfg
from ironic_inspector.common import ironic as ir_utils
@ -380,7 +380,7 @@ class TestSync(DnsmasqTestBase):
self.whitelist = {}
self.mock__get_black_white_lists.return_value = (self.blacklist,
self.whitelist)
self.mock_ironic.port.list.return_value = [
self.mock_ironic.ports.return_value = [
mock.Mock(address=address) for address in self.ironic_macs]
self.mock_active_macs.return_value = self.active_macs
self.mock_should_enable_unknown_hosts = self.useFixture(
@ -406,8 +406,8 @@ class TestSync(DnsmasqTestBase):
self.mock__whitelist_mac.assert_called_once_with('active_mac')
self.mock__blacklist_mac.assert_called_once_with('new_mac')
self.mock_ironic.port.list.assert_called_once_with(limit=0,
fields=['address'])
self.mock_ironic.ports.assert_called_once_with(
limit=None, fields=['address'])
self.mock_active_macs.assert_called_once_with()
self.mock__get_black_white_lists.assert_called_once_with()
self.mock__configure_unknown_hosts.assert_called_once_with()
@ -420,8 +420,8 @@ class TestSync(DnsmasqTestBase):
@mock.patch('time.sleep', lambda _x: None)
def test__sync_with_port_list_retries(self):
self.mock_ironic.port.list.side_effect = [
ironic_exc.ConnectionRefused('boom'),
self.mock_ironic.ports.side_effect = [
os_exc.SDKException('boom'),
[mock.Mock(address=address) for address in self.ironic_macs]
]
self.driver._sync(self.mock_ironic)
@ -429,8 +429,8 @@ class TestSync(DnsmasqTestBase):
self.mock__whitelist_mac.assert_called_once_with('active_mac')
self.mock__blacklist_mac.assert_called_once_with('new_mac')
self.mock_ironic.port.list.assert_called_with(limit=0,
fields=['address'])
self.mock_ironic.ports.assert_called_with(
limit=None, fields=['address'])
self.mock_active_macs.assert_called_once_with()
self.mock__get_black_white_lists.assert_called_once_with()
self.mock__configure_removedlist.assert_called_once_with({'gone_mac'})

View File

@ -15,8 +15,8 @@ import collections
import time
import fixtures
from ironicclient import exceptions
import mock
from openstack import exceptions as os_exc
from oslo_config import cfg
from ironic_inspector.common import ironic as ir_utils
@ -48,8 +48,8 @@ class BaseTest(test_base.NodeTest):
def _prepare(self, client_mock):
cli = client_mock.return_value
cli.node.get.return_value = self.node
cli.node.validate.return_value = mock.Mock(power={'result': True})
cli.get_node.return_value = self.node
cli.validate_node.return_value = mock.Mock(power={'result': True})
return cli
@ -62,22 +62,21 @@ class TestIntrospect(BaseTest):
introspect.introspect(self.node.uuid)
cli.node.get.assert_called_once_with(self.uuid)
cli.node.validate.assert_called_once_with(self.uuid)
cli.get_node.assert_called_once_with(self.uuid)
cli.validate_node.assert_called_once_with(self.uuid, required='power')
start_mock.assert_called_once_with(self.uuid,
bmc_address=[self.bmc_address],
manage_boot=True,
ironic=cli)
self.node_info.ports.assert_called_once_with()
self.node_info.add_attribute.assert_called_once_with('mac',
self.macs)
self.node_info.add_attribute.assert_called_once_with(
'mac', self.macs)
self.sync_filter_mock.assert_called_with(cli)
cli.node.set_boot_device.assert_called_once_with(self.uuid,
'pxe',
persistent=False)
cli.node.set_power_state.assert_called_once_with(self.uuid,
'reboot')
cli.set_node_boot_device.assert_called_once_with(
self.uuid, 'pxe', persistent=False)
cli.set_node_power_state.assert_called_once_with(self.uuid,
'rebooting')
self.node_info.acquire_lock.assert_called_once_with()
self.node_info.release_lock.assert_called_once_with()
@ -91,8 +90,8 @@ class TestIntrospect(BaseTest):
introspect.introspect(self.node.uuid)
cli.node.get.assert_called_once_with(self.uuid)
cli.node.validate.assert_called_once_with(self.uuid)
cli.get_node.assert_called_once_with(self.uuid)
cli.validate_node.assert_called_once_with(self.uuid, required='power')
start_mock.assert_called_once_with(self.uuid,
bmc_address=addresses,
@ -102,11 +101,11 @@ class TestIntrospect(BaseTest):
self.node_info.add_attribute.assert_called_once_with('mac',
self.macs)
self.sync_filter_mock.assert_called_with(cli)
cli.node.set_boot_device.assert_called_once_with(self.uuid,
cli.set_node_boot_device.assert_called_once_with(self.uuid,
'pxe',
persistent=False)
cli.node.set_power_state.assert_called_once_with(self.uuid,
'reboot')
cli.set_node_power_state.assert_called_once_with(self.uuid,
'rebooting')
self.node_info.acquire_lock.assert_called_once_with()
self.node_info.release_lock.assert_called_once_with()
@ -117,8 +116,8 @@ class TestIntrospect(BaseTest):
introspect.introspect(self.node.uuid)
cli.node.get.assert_called_once_with(self.uuid)
cli.node.validate.assert_called_once_with(self.uuid)
cli.get_node.assert_called_once_with(self.uuid)
cli.validate_node.assert_called_once_with(self.uuid, required='power')
start_mock.assert_called_once_with(self.uuid,
bmc_address=[],
@ -128,11 +127,11 @@ class TestIntrospect(BaseTest):
self.node_info.add_attribute.assert_called_once_with('mac',
self.macs)
self.sync_filter_mock.assert_called_with(cli)
cli.node.set_boot_device.assert_called_once_with(self.uuid,
cli.set_node_boot_device.assert_called_once_with(self.uuid,
'pxe',
persistent=False)
cli.node.set_power_state.assert_called_once_with(self.uuid,
'reboot')
cli.set_node_power_state.assert_called_once_with(self.uuid,
'rebooting')
self.node_info.acquire_lock.assert_called_once_with()
self.node_info.release_lock.assert_called_once_with()
@ -151,22 +150,22 @@ class TestIntrospect(BaseTest):
def test_power_failure(self, client_mock, start_mock):
cli = self._prepare(client_mock)
cli.node.set_power_state.side_effect = exceptions.BadRequest()
cli.set_node_power_state.side_effect = os_exc.BadRequestException()
start_mock.return_value = self.node_info
introspect.introspect(self.node.uuid)
cli.node.get.assert_called_once_with(self.uuid)
cli.get_node.assert_called_once_with(self.uuid)
start_mock.assert_called_once_with(self.uuid,
bmc_address=[self.bmc_address],
manage_boot=True,
ironic=cli)
cli.node.set_boot_device.assert_called_once_with(self.uuid,
cli.set_node_boot_device.assert_called_once_with(self.uuid,
'pxe',
persistent=False)
cli.node.set_power_state.assert_called_once_with(self.uuid,
'reboot')
cli.set_node_power_state.assert_called_once_with(self.uuid,
'rebooting')
start_mock.return_value.finished.assert_called_once_with(
introspect.istate.Events.error, error=mock.ANY)
self.node_info.acquire_lock.assert_called_once_with()
@ -179,13 +178,13 @@ class TestIntrospect(BaseTest):
introspect.introspect(self.node.uuid)
cli.node.get.assert_called_once_with(self.uuid)
cli.get_node.assert_called_once_with(self.uuid)
start_mock.assert_called_once_with(self.uuid,
bmc_address=[self.bmc_address],
manage_boot=True,
ironic=cli)
self.assertFalse(cli.node.set_boot_device.called)
self.assertFalse(cli.set_node_boot_device.called)
start_mock.return_value.finished.assert_called_once_with(
introspect.istate.Events.error, error=mock.ANY)
self.node_info.acquire_lock.assert_called_once_with()
@ -193,21 +192,21 @@ class TestIntrospect(BaseTest):
def test_set_boot_device_failure(self, client_mock, start_mock):
cli = self._prepare(client_mock)
cli.node.set_boot_device.side_effect = exceptions.BadRequest()
cli.set_node_boot_device.side_effect = os_exc.BadRequestException()
start_mock.return_value = self.node_info
introspect.introspect(self.node.uuid)
cli.node.get.assert_called_once_with(self.uuid)
cli.get_node.assert_called_once_with(self.uuid)
start_mock.assert_called_once_with(self.uuid,
bmc_address=[self.bmc_address],
manage_boot=True,
ironic=cli)
cli.node.set_boot_device.assert_called_once_with(self.uuid,
cli.set_node_boot_device.assert_called_once_with(self.uuid,
'pxe',
persistent=False)
cli.node.set_power_state.assert_not_called()
cli.set_node_power_state.assert_not_called()
start_mock.return_value.finished.assert_called_once_with(
introspect.istate.Events.error, error=mock.ANY)
self.node_info.acquire_lock.assert_called_once_with()
@ -228,11 +227,11 @@ class TestIntrospect(BaseTest):
ironic=cli)
self.assertFalse(self.node_info.add_attribute.called)
self.assertFalse(self.sync_filter_mock.called)
cli.node.set_boot_device.assert_called_once_with(self.uuid,
cli.set_node_boot_device.assert_called_once_with(self.uuid,
'pxe',
persistent=False)
cli.node.set_power_state.assert_called_once_with(self.uuid,
'reboot')
cli.set_node_power_state.assert_called_once_with(self.uuid,
'rebooting')
def test_forced_persistent_boot(self, client_mock, start_mock):
self.node.driver_info['force_persistent_boot_device'] = 'Always'
@ -241,8 +240,9 @@ class TestIntrospect(BaseTest):
introspect.introspect(self.node.uuid)
cli.node.get.assert_called_once_with(self.uuid)
cli.node.validate.assert_called_once_with(self.uuid)
cli.get_node.assert_called_once_with(self.uuid)
cli.validate_node.assert_called_once_with(self.uuid,
required='power')
start_mock.assert_called_once_with(self.uuid,
bmc_address=[self.bmc_address],
@ -252,11 +252,11 @@ class TestIntrospect(BaseTest):
self.node_info.add_attribute.assert_called_once_with('mac',
self.macs)
self.sync_filter_mock.assert_called_with(cli)
cli.node.set_boot_device.assert_called_once_with(self.uuid,
cli.set_node_boot_device.assert_called_once_with(self.uuid,
'pxe',
persistent=True)
cli.node.set_power_state.assert_called_once_with(self.uuid,
'reboot')
cli.set_node_power_state.assert_called_once_with(self.uuid,
'rebooting')
self.node_info.acquire_lock.assert_called_once_with()
self.node_info.release_lock.assert_called_once_with()
@ -267,8 +267,9 @@ class TestIntrospect(BaseTest):
introspect.introspect(self.node.uuid)
cli.node.get.assert_called_once_with(self.uuid)
cli.node.validate.assert_called_once_with(self.uuid)
cli.get_node.assert_called_once_with(self.uuid)
cli.validate_node.assert_called_once_with(self.uuid,
required='power')
start_mock.assert_called_once_with(self.uuid,
bmc_address=[self.bmc_address],
@ -278,11 +279,11 @@ class TestIntrospect(BaseTest):
self.node_info.add_attribute.assert_called_once_with('mac',
self.macs)
self.sync_filter_mock.assert_called_with(cli)
cli.node.set_boot_device.assert_called_once_with(self.uuid,
cli.set_node_boot_device.assert_called_once_with(self.uuid,
'pxe',
persistent=True)
cli.node.set_power_state.assert_called_once_with(self.uuid,
'reboot')
cli.set_node_power_state.assert_called_once_with(self.uuid,
'rebooting')
self.node_info.acquire_lock.assert_called_once_with()
self.node_info.release_lock.assert_called_once_with()
@ -298,7 +299,7 @@ class TestIntrospect(BaseTest):
self.node_info.finished.assert_called_once_with(
introspect.istate.Events.error, error=mock.ANY)
self.assertEqual(0, self.sync_filter_mock.call_count)
self.assertEqual(0, cli.node.set_power_state.call_count)
self.assertEqual(0, cli.set_node_power_state.call_count)
self.node_info.acquire_lock.assert_called_once_with()
self.node_info.release_lock.assert_called_once_with()
@ -314,52 +315,50 @@ class TestIntrospect(BaseTest):
self.node_info.ports.assert_called_once_with()
self.assertFalse(self.node_info.finished.called)
cli.node.set_boot_device.assert_called_once_with(self.uuid,
cli.set_node_boot_device.assert_called_once_with(self.uuid,
'pxe',
persistent=False)
cli.node.set_power_state.assert_called_once_with(self.uuid,
'reboot')
cli.set_node_power_state.assert_called_once_with(self.uuid,
'rebooting')
def test_failed_to_get_node(self, client_mock, start_mock):
cli = client_mock.return_value
cli.node.get.side_effect = exceptions.NotFound()
cli.get_node.side_effect = os_exc.NotFoundException()
self.assertRaisesRegex(utils.Error,
'Node %s was not found' % self.uuid,
introspect.introspect, self.uuid)
cli.node.get.side_effect = exceptions.BadRequest()
cli.get_node.side_effect = os_exc.BadRequestException()
self.assertRaisesRegex(utils.Error,
'%s: Bad Request' % self.uuid,
'Cannot get node %s: Error' % self.uuid,
introspect.introspect, self.uuid)
self.assertEqual(0, self.node_info.ports.call_count)
self.assertEqual(0, self.sync_filter_mock.call_count)
self.assertEqual(0, cli.node.set_power_state.call_count)
self.assertEqual(0, cli.set_node_power_state.call_count)
self.assertFalse(start_mock.called)
self.assertFalse(self.node_info.acquire_lock.called)
def test_failed_to_validate_node(self, client_mock, start_mock):
cli = client_mock.return_value
cli.node.get.return_value = self.node
cli.node.validate.return_value = mock.Mock(power={'result': False,
'reason': 'oops'})
cli.get_node.return_value = self.node
cli.validate_node.side_effect = os_exc.ValidationException()
self.assertRaisesRegex(
utils.Error,
'Failed validation of power interface',
'Failed validation of power interface: ValidationException',
introspect.introspect, self.uuid)
cli.node.validate.assert_called_once_with(self.uuid)
cli.validate_node.assert_called_once_with(self.uuid, required='power')
self.assertEqual(0, self.node_info.ports.call_count)
self.assertEqual(0, self.sync_filter_mock.call_count)
self.assertEqual(0, cli.node.set_power_state.call_count)
self.assertEqual(0, cli.set_node_power_state.call_count)
self.assertFalse(start_mock.called)
self.assertFalse(self.node_info.acquire_lock.called)
def test_wrong_provision_state(self, client_mock, start_mock):
self.node.provision_state = 'active'
cli = client_mock.return_value
cli.node.get.return_value = self.node
cli.get_node.return_value = self.node
self.assertRaisesRegex(
utils.Error, 'Invalid provision state for introspection: "active"',
@ -367,15 +366,15 @@ class TestIntrospect(BaseTest):
self.assertEqual(0, self.node_info.ports.call_count)
self.assertEqual(0, self.sync_filter_mock.call_count)
self.assertEqual(0, cli.node.set_power_state.call_count)
self.assertEqual(0, cli.set_node_power_state.call_count)
self.assertFalse(start_mock.called)
self.assertFalse(self.node_info.acquire_lock.called)
def test_inspect_wait_state_allowed(self, client_mock, start_mock):
self.node.provision_state = 'inspect wait'
cli = client_mock.return_value
cli.node.get.return_value = self.node
cli.node.validate.return_value = mock.Mock(power={'result': True})
cli.get_node.return_value = self.node
cli.validate_node.return_value = mock.Mock(power={'result': True})
introspect.introspect(self.uuid)
@ -393,11 +392,11 @@ class TestIntrospect(BaseTest):
introspect.introspect(self.uuid)
self.sleep_fixture.mock.assert_called_once_with(8)
cli.node.set_boot_device.assert_called_once_with(self.uuid,
cli.set_node_boot_device.assert_called_once_with(self.uuid,
'pxe',
persistent=False)
cli.node.set_power_state.assert_called_once_with(self.uuid,
'reboot')
cli.set_node_power_state.assert_called_once_with(self.uuid,
'rebooting')
# updated to the current time.time()
self.assertEqual(42, introspect._LAST_INTROSPECTION_TIME)
@ -415,11 +414,11 @@ class TestIntrospect(BaseTest):
introspect.introspect(self.uuid)
self.sleep_fixture.mock().assert_not_called()
cli.node.set_boot_device.assert_called_once_with(self.uuid,
cli.set_node_boot_device.assert_called_once_with(self.uuid,
'pxe',
persistent=False)
cli.node.set_power_state.assert_called_once_with(self.uuid,
'reboot')
cli.set_node_power_state.assert_called_once_with(self.uuid,
'rebooting')
# updated to the current time.time()
self.assertEqual(100, introspect._LAST_INTROSPECTION_TIME)
@ -430,7 +429,7 @@ class TestIntrospect(BaseTest):
introspect.introspect(self.node.uuid, manage_boot=False)
cli.node.get.assert_called_once_with(self.uuid)
cli.get_node.assert_called_once_with(self.uuid)
add_mock.assert_called_once_with(self.uuid,
bmc_address=[self.bmc_address],
@ -440,9 +439,9 @@ class TestIntrospect(BaseTest):
self.node_info.add_attribute.assert_called_once_with('mac',
self.macs)
self.sync_filter_mock.assert_called_with(cli)
self.assertFalse(cli.node.validate.called)
self.assertFalse(cli.node.set_boot_device.called)
self.assertFalse(cli.node.set_power_state.called)
self.assertFalse(cli.validate_node.called)
self.assertFalse(cli.set_node_boot_device.called)
self.assertFalse(cli.set_node_power_state.called)
@mock.patch.object(node_cache, 'get_node', autospec=True)
@ -469,7 +468,8 @@ class TestAbort(BaseTest):
get_mock.assert_called_once_with(self.uuid, ironic=cli)
self.node_info.acquire_lock.assert_called_once_with(blocking=False)
self.sync_filter_mock.assert_called_once_with(cli)
cli.node.set_power_state.assert_called_once_with(self.uuid, 'off')
cli.set_node_power_state.assert_called_once_with(self.uuid,
'power off')
self.node_info.finished.assert_called_once_with(
introspect.istate.Events.abort_end, error='Canceled by operator')
self.node_info.fsm_event.assert_has_calls(self.fsm_calls)
@ -487,7 +487,7 @@ class TestAbort(BaseTest):
get_mock.assert_called_once_with(self.uuid, ironic=cli)
self.node_info.acquire_lock.assert_called_once_with(blocking=False)
self.sync_filter_mock.assert_called_once_with(cli)
self.assertFalse(cli.node.set_power_state.called)
self.assertFalse(cli.set_node_power_state.called)
self.node_info.finished.assert_called_once_with(
introspect.istate.Events.abort_end, error='Canceled by operator')
self.node_info.fsm_event.assert_has_calls(self.fsm_calls)
@ -501,7 +501,7 @@ class TestAbort(BaseTest):
introspect.abort, self.uuid)
self.assertEqual(0, self.sync_filter_mock.call_count)
self.assertEqual(0, cli.node.set_power_state.call_count)
self.assertEqual(0, cli.set_node_power_state.call_count)
self.assertEqual(0, self.node_info.finished.call_count)
self.assertEqual(0, self.node_info.fsm_event.call_count)
@ -515,7 +515,7 @@ class TestAbort(BaseTest):
'retry later', introspect.abort, self.uuid)
self.assertEqual(0, self.sync_filter_mock.call_count)
self.assertEqual(0, cli.node.set_power_state.call_count)
self.assertEqual(0, cli.set_node_power_state.call_count)
self.assertEqual(0, self.node_info.finshed.call_count)
self.assertEqual(0, self.node_info.fsm_event.call_count)
@ -532,7 +532,8 @@ class TestAbort(BaseTest):
get_mock.assert_called_once_with(self.uuid, ironic=cli)
self.node_info.acquire_lock.assert_called_once_with(blocking=False)
self.sync_filter_mock.assert_called_once_with(cli)
cli.node.set_power_state.assert_called_once_with(self.uuid, 'off')
cli.set_node_power_state.assert_called_once_with(self.uuid,
'power off')
self.node_info.finished.assert_called_once_with(
introspect.istate.Events.abort_end, error='Canceled by operator')
self.node_info.fsm_event.assert_has_calls(self.fsm_calls)
@ -543,14 +544,15 @@ class TestAbort(BaseTest):
self.node_info.acquire_lock.return_value = True
self.node_info.started_at = time.time()
self.node_info.finished_at = None
cli.node.set_power_state.side_effect = Exception('BadaBoom')
cli.set_node_power_state.side_effect = Exception('BadaBoom')
introspect.abort(self.uuid)
get_mock.assert_called_once_with(self.uuid, ironic=cli)
self.node_info.acquire_lock.assert_called_once_with(blocking=False)
self.sync_filter_mock.assert_called_once_with(cli)
cli.node.set_power_state.assert_called_once_with(self.uuid, 'off')
cli.set_node_power_state.assert_called_once_with(self.uuid,
'power off')
self.node_info.finished.assert_called_once_with(
introspect.istate.Events.abort_end, error='Canceled by operator')
self.node_info.fsm_event.assert_has_calls(self.fsm_calls)

View File

@ -14,8 +14,8 @@
# under the License.
import fixtures
from ironicclient import exc as ironic_exc
import mock
from openstack import exceptions as os_exc
from oslo_config import cfg
from ironic_inspector import node_cache
@ -390,14 +390,14 @@ class TestGetBlacklist(test_base.BaseTest):
mock.Mock(address='foo'),
mock.Mock(address='bar'),
]
self.mock_ironic.port.list.return_value = mock_ports_list
self.mock_ironic.ports.return_value = mock_ports_list
self.mock_active_macs.return_value = {'foo'}
ports = iptables._get_blacklist(self.mock_ironic)
# foo is an active address so we expect the blacklist contains only bar
self.assertEqual(['bar'], ports)
self.mock_ironic.port.list.assert_called_once_with(
limit=0, fields=['address', 'extra'])
self.mock_ironic.ports.assert_called_once_with(
limit=None, fields=['address', 'extra'])
self.mock__ib_mac_to_rmac_mapping.assert_called_once_with(
[mock_ports_list[1]])
@ -407,8 +407,8 @@ class TestGetBlacklist(test_base.BaseTest):
mock.Mock(address='foo'),
mock.Mock(address='bar'),
]
self.mock_ironic.port.list.side_effect = [
ironic_exc.ConnectionRefused('boom'),
self.mock_ironic.ports.side_effect = [
os_exc.SDKException('boom'),
mock_ports_list
]
self.mock_active_macs.return_value = {'foo'}
@ -416,7 +416,7 @@ class TestGetBlacklist(test_base.BaseTest):
ports = iptables._get_blacklist(self.mock_ironic)
# foo is an active address so we expect the blacklist contains only bar
self.assertEqual(['bar'], ports)
self.mock_ironic.port.list.assert_called_with(
limit=0, fields=['address', 'extra'])
self.mock_ironic.ports.assert_called_with(
limit=None, fields=['address', 'extra'])
self.mock__ib_mac_to_rmac_mapping.assert_called_once_with(
[mock_ports_list[1]])

View File

@ -43,7 +43,6 @@ class BaseManagerTest(test_base.NodeTest):
self.mock__shutting_down.acquire.return_value = True
self.manager = manager.ConductorManager()
self.context = {}
self.token = None
class TestManagerInitHost(BaseManagerTest):
@ -327,18 +326,18 @@ class TestManagerPeriodicWatchDog(BaseManagerTest):
class TestManagerIntrospect(BaseManagerTest):
@mock.patch.object(introspect, 'introspect', autospec=True)
def test_do_introspect(self, introspect_mock):
self.manager.do_introspection(self.context, self.uuid, self.token)
self.manager.do_introspection(self.context, self.uuid)
introspect_mock.assert_called_once_with(self.uuid, token=self.token,
manage_boot=True)
introspect_mock.assert_called_once_with(self.uuid, manage_boot=True,
token=None)
@mock.patch.object(introspect, 'introspect', autospec=True)
def test_do_introspect_with_manage_boot(self, introspect_mock):
self.manager.do_introspection(self.context, self.uuid, self.token,
False)
self.manager.do_introspection(self.context, self.uuid,
manage_boot=False)
introspect_mock.assert_called_once_with(self.uuid, token=self.token,
manage_boot=False)
introspect_mock.assert_called_once_with(self.uuid, manage_boot=False,
token=None)
@mock.patch.object(introspect, 'introspect', autospec=True)
def test_introspect_failed(self, introspect_mock):
@ -346,19 +345,19 @@ class TestManagerIntrospect(BaseManagerTest):
exc = self.assertRaises(messaging.rpc.ExpectedException,
self.manager.do_introspection,
self.context, self.uuid, self.token)
self.context, self.uuid)
self.assertEqual(utils.Error, exc.exc_info[0])
introspect_mock.assert_called_once_with(self.uuid, token=None,
manage_boot=True)
introspect_mock.assert_called_once_with(self.uuid, manage_boot=True,
token=None)
class TestManagerAbort(BaseManagerTest):
@mock.patch.object(introspect, 'abort', autospec=True)
def test_abort_ok(self, abort_mock):
self.manager.do_abort(self.context, self.uuid, self.token)
self.manager.do_abort(self.context, self.uuid)
abort_mock.assert_called_once_with(self.uuid, token=self.token)
abort_mock.assert_called_once_with(self.uuid, token=None)
@mock.patch.object(introspect, 'abort', autospec=True)
def test_abort_node_not_found(self, abort_mock):
@ -366,7 +365,7 @@ class TestManagerAbort(BaseManagerTest):
exc = self.assertRaises(messaging.rpc.ExpectedException,
self.manager.do_abort,
self.context, self.uuid, self.token)
self.context, self.uuid)
self.assertEqual(utils.Error, exc.exc_info[0])
abort_mock.assert_called_once_with(self.uuid, token=None)
@ -378,7 +377,7 @@ class TestManagerAbort(BaseManagerTest):
exc = self.assertRaises(messaging.rpc.ExpectedException,
self.manager.do_abort,
self.context, self.uuid, self.token)
self.context, self.uuid)
self.assertEqual(utils.Error, exc.exc_info[0])
abort_mock.assert_called_once_with(self.uuid, token=None)

View File

@ -468,7 +468,7 @@ class TestNodeCacheGetNode(test_base.NodeTest):
state=istate.States.starting,
started_at=started_at).save(session)
ironic = mock.Mock()
ironic.node.get.return_value = self.node
ironic.get_node.return_value = self.node
info = node_cache.get_node('name', ironic=ironic)
@ -477,7 +477,7 @@ class TestNodeCacheGetNode(test_base.NodeTest):
self.assertIsNone(info.finished_at)
self.assertIsNone(info.error)
self.assertFalse(info._lock.is_locked())
ironic.node.get.assert_called_once_with('name')
ironic.get_node.assert_called_once_with('name')
@mock.patch.object(timeutils, 'utcnow', lambda: datetime.datetime(1, 1, 1))
@ -571,24 +571,26 @@ class TestNodeCacheIronicObjects(unittest.TestCase):
self.assertFalse(mock_ironic.called)
def test_node_not_provided(self, mock_ironic):
mock_ironic.return_value.node.get.return_value = mock.sentinel.node
mock_ironic.return_value.get_node.return_value = mock.sentinel.node
mock.sentinel.node.id = mock.Mock
node_info = node_cache.NodeInfo(uuid=self.uuid, started_at=0)
self.assertIs(mock.sentinel.node, node_info.node())
self.assertIs(node_info.node(), node_info.node())
mock_ironic.assert_called_once_with()
mock_ironic.return_value.node.get.assert_called_once_with(self.uuid)
mock_ironic.return_value.get_node.assert_called_once_with(self.uuid)
def test_node_ironic_preset(self, mock_ironic):
mock_ironic2 = mock.Mock()
mock_ironic2.node.get.return_value = mock.sentinel.node
mock_ironic2.get_node.return_value = mock.sentinel.node
mock.sentinel.node.id = mock.Mock
node_info = node_cache.NodeInfo(uuid=self.uuid, started_at=0,
ironic=mock_ironic2)
self.assertIs(mock.sentinel.node, node_info.node())
self.assertFalse(mock_ironic.called)
mock_ironic2.node.get.assert_called_once_with(self.uuid)
mock_ironic2.get_node.assert_called_once_with(self.uuid)
def test_ports_provided(self, mock_ironic):
node_info = node_cache.NodeInfo(uuid=self.uuid, started_at=0,
@ -603,7 +605,7 @@ class TestNodeCacheIronicObjects(unittest.TestCase):
self.assertFalse(mock_ironic.called)
def test_ports_not_provided(self, mock_ironic):
mock_ironic.return_value.node.list_ports.return_value = list(
mock_ironic.return_value.ports.return_value = list(
self.ports.values())
node_info = node_cache.NodeInfo(uuid=self.uuid, started_at=0)
@ -611,27 +613,27 @@ class TestNodeCacheIronicObjects(unittest.TestCase):
self.assertIs(node_info.ports(), node_info.ports())
mock_ironic.assert_called_once_with()
mock_ironic.return_value.node.list_ports.assert_called_once_with(
self.uuid, limit=0, detail=True)
mock_ironic.return_value.ports.assert_called_once_with(
node=self.uuid, limit=None, details=True)
def test_ports_ironic_preset(self, mock_ironic):
mock_ironic2 = mock.Mock()
mock_ironic2.node.list_ports.return_value = list(
mock_ironic2.ports.return_value = list(
self.ports.values())
node_info = node_cache.NodeInfo(uuid=self.uuid, started_at=0,
ironic=mock_ironic2)
self.assertEqual(self.ports, node_info.ports())
self.assertFalse(mock_ironic.called)
mock_ironic2.node.list_ports.assert_called_once_with(
self.uuid, limit=0, detail=True)
mock_ironic2.ports.assert_called_once_with(
node=self.uuid, limit=None, details=True)
class TestUpdate(test_base.NodeTest):
def setUp(self):
super(TestUpdate, self).setUp()
self.ironic = mock.Mock()
self.ports = {'mac%d' % i: mock.Mock(address='mac%d' % i, uuid=str(i))
self.ports = {'mac%d' % i: mock.Mock(address='mac%d' % i, id=str(i))
for i in range(2)}
self.node_info = node_cache.NodeInfo(uuid=self.uuid,
started_at=0,
@ -640,16 +642,16 @@ class TestUpdate(test_base.NodeTest):
ironic=self.ironic)
def test_patch(self):
self.ironic.node.update.return_value = mock.sentinel.node
self.ironic.patch_node.return_value = mock.sentinel.node
self.node_info.patch([{'patch': 'patch'}])
self.ironic.node.update.assert_called_once_with(self.uuid,
[{'patch': 'patch'}])
self.ironic.patch_node.assert_called_once_with(self.uuid,
[{'patch': 'patch'}])
self.assertIs(mock.sentinel.node, self.node_info.node())
def test_patch_path_wo_leading_slash(self):
self.ironic.node.update.return_value = mock.sentinel.node
self.ironic.patch_node.return_value = mock.sentinel.node
patch = [{'op': 'add', 'path': 'driver_info/test', 'value': 42}]
expected_patch = copy.deepcopy(patch)
@ -657,111 +659,111 @@ class TestUpdate(test_base.NodeTest):
self.node_info.patch(patch)
self.ironic.node.update.assert_called_once_with(self.uuid,
expected_patch)
self.ironic.patch_node.assert_called_once_with(self.uuid,
expected_patch)
self.assertIs(mock.sentinel.node, self.node_info.node())
def test_patch_path_with_leading_slash(self):
self.ironic.node.update.return_value = mock.sentinel.node
self.ironic.patch_node.return_value = mock.sentinel.node
patch = [{'op': 'add', 'path': '/driver_info/test', 'value': 42}]
self.node_info.patch(patch)
self.ironic.node.update.assert_called_once_with(self.uuid, patch)
self.ironic.patch_node.assert_called_once_with(self.uuid, patch)
self.assertIs(mock.sentinel.node, self.node_info.node())
def test_patch_with_args(self):
self.ironic.node.update.return_value = mock.sentinel.node
self.ironic.patch_node.return_value = mock.sentinel.node
self.node_info.patch([{'patch': 'patch'}], reset_interfaces=True)
self.ironic.node.update.assert_called_once_with(self.uuid,
[{'patch': 'patch'}],
reset_interfaces=True)
self.ironic.patch_node.assert_called_once_with(self.uuid,
[{'patch': 'patch'}],
reset_interfaces=True)
self.assertIs(mock.sentinel.node, self.node_info.node())
def test_update_properties(self):
self.ironic.node.update.return_value = mock.sentinel.node
self.ironic.patch_node.return_value = mock.sentinel.node
self.node_info.update_properties(prop=42)
patch = [{'op': 'add', 'path': '/properties/prop', 'value': 42}]
self.ironic.node.update.assert_called_once_with(self.uuid, patch)
self.ironic.patch_node.assert_called_once_with(self.uuid, patch)
self.assertIs(mock.sentinel.node, self.node_info.node())
def test_update_capabilities(self):
self.ironic.node.update.return_value = mock.sentinel.node
self.ironic.patch_node.return_value = mock.sentinel.node
self.node.properties['capabilities'] = 'foo:bar,x:y'
self.node_info.update_capabilities(x=1, y=2)
self.ironic.node.update.assert_called_once_with(self.uuid, mock.ANY)
patch = self.ironic.node.update.call_args[0][1]
self.ironic.patch_node.assert_called_once_with(self.uuid, mock.ANY)
patch = self.ironic.patch_node.call_args[0][1]
new_caps = ir_utils.capabilities_to_dict(patch[0]['value'])
self.assertEqual({'foo': 'bar', 'x': '1', 'y': '2'}, new_caps)
def test_replace_field(self):
self.ironic.node.update.return_value = mock.sentinel.node
self.ironic.patch_node.return_value = mock.sentinel.node
self.node.extra['foo'] = 'bar'
self.node_info.replace_field('/extra/foo', lambda v: v + '1')
patch = [{'op': 'replace', 'path': '/extra/foo', 'value': 'bar1'}]
self.ironic.node.update.assert_called_once_with(self.uuid, patch)
self.ironic.patch_node.assert_called_once_with(self.uuid, patch)
self.assertIs(mock.sentinel.node, self.node_info.node())
def test_replace_field_not_found(self):
self.ironic.node.update.return_value = mock.sentinel.node
self.ironic.patch_node.return_value = mock.sentinel.node
self.assertRaises(KeyError, self.node_info.replace_field,
'/extra/foo', lambda v: v + '1')
def test_replace_field_with_default(self):
self.ironic.node.update.return_value = mock.sentinel.node
self.ironic.patch_node.return_value = mock.sentinel.node
self.node_info.replace_field('/extra/foo', lambda v: v + [42],
default=[])
patch = [{'op': 'add', 'path': '/extra/foo', 'value': [42]}]
self.ironic.node.update.assert_called_once_with(self.uuid, patch)
self.ironic.patch_node.assert_called_once_with(self.uuid, patch)
self.assertIs(mock.sentinel.node, self.node_info.node())
def test_replace_field_same_value(self):
self.ironic.node.update.return_value = mock.sentinel.node
self.ironic.patch_node.return_value = mock.sentinel.node
self.node.extra['foo'] = 'bar'
self.node_info.replace_field('/extra/foo', lambda v: v)
self.assertFalse(self.ironic.node.update.called)
self.assertFalse(self.ironic.patch_node.called)
def test_patch_port(self):
self.ironic.port.update.return_value = mock.sentinel.port
self.ironic.patch_port.return_value = mock.sentinel.port
self.node_info.patch_port(self.ports['mac0'], ['patch'])
self.ironic.port.update.assert_called_once_with('0', ['patch'])
self.ironic.patch_port.assert_called_once_with('0', ['patch'])
self.assertIs(mock.sentinel.port,
self.node_info.ports()['mac0'])
def test_patch_port_by_mac(self):
self.ironic.port.update.return_value = mock.sentinel.port
self.ironic.patch_port.return_value = mock.sentinel.port
self.node_info.patch_port('mac0', ['patch'])
self.ironic.port.update.assert_called_once_with('0', ['patch'])
self.ironic.patch_port.assert_called_once_with('0', ['patch'])
self.assertIs(mock.sentinel.port,
self.node_info.ports()['mac0'])
def test_delete_port(self):
self.node_info.delete_port(self.ports['mac0'])
self.ironic.port.delete.assert_called_once_with('0')
self.ironic.delete_port.assert_called_once_with('0')
self.assertEqual(['mac1'], list(self.node_info.ports()))
def test_delete_port_by_mac(self):
self.node_info.delete_port('mac0')
self.ironic.port.delete.assert_called_once_with('0')
self.ironic.delete_port.assert_called_once_with('0')
self.assertEqual(['mac1'], list(self.node_info.ports()))
@mock.patch.object(node_cache.LOG, 'warning', autospec=True)
@ -778,13 +780,13 @@ class TestUpdate(test_base.NodeTest):
create_calls = [
mock.call(node_uuid=self.uuid, address='mac2', extra={},
pxe_enabled=True),
is_pxe_enabled=True),
mock.call(node_uuid=self.uuid, address='mac3',
extra={'client-id': '42'}, pxe_enabled=False),
extra={'client-id': '42'}, is_pxe_enabled=False),
mock.call(node_uuid=self.uuid, address='mac4', extra={},
pxe_enabled=True),
is_pxe_enabled=True),
]
self.assertEqual(create_calls, self.ironic.port.create.call_args_list)
self.assertEqual(create_calls, self.ironic.create_port.call_args_list)
# No conflicts - cache was not cleared - no calls to port.list
self.assertFalse(mock_warn.called)
self.assertFalse(self.ironic.port.list.called)
@ -793,12 +795,12 @@ class TestUpdate(test_base.NodeTest):
def test__create_port(self, mock_info):
uuid = uuidutils.generate_uuid()
address = 'mac1'
self.ironic.port.create.return_value = mock.Mock(uuid=uuid,
self.ironic.create_port.return_value = mock.Mock(id=uuid,
address=address)
self.node_info._create_port(address, client_id='42')
self.ironic.port.create.assert_called_once_with(
self.ironic.create_port.assert_called_once_with(
node_uuid=self.uuid, address='mac1', client_id='42')
mock_info.assert_called_once_with(
mock.ANY, {'uuid': uuid, 'mac': address,
@ -807,8 +809,8 @@ class TestUpdate(test_base.NodeTest):
@mock.patch.object(node_cache.LOG, 'warning', autospec=True)
def test_create_ports_with_conflicts(self, mock_warn):
self.ironic.port.create.return_value = mock.Mock(
uuid='fake', address='mac')
self.ironic.create_port.return_value = mock.Mock(
id='fake', address='mac')
ports = [
'mac',
@ -821,11 +823,11 @@ class TestUpdate(test_base.NodeTest):
create_calls = [
mock.call(node_uuid=self.uuid, address='mac', extra={},
pxe_enabled=True),
is_pxe_enabled=True),
mock.call(node_uuid=self.uuid, address='mac2',
extra={'client-id': '42'}, pxe_enabled=False),
extra={'client-id': '42'}, is_pxe_enabled=False),
]
self.assertEqual(create_calls, self.ironic.port.create.call_args_list)
self.assertEqual(create_calls, self.ironic.create_port.call_args_list)
mock_warn.assert_called_once_with(mock.ANY, ['mac0', 'mac1'],
node_info=self.node_info)
@ -899,11 +901,11 @@ class TestNodeCreate(test_base.NodeTest):
def test_default_create(self, mock_get_client, mock_add_node):
mock_get_client.return_value = self.mock_client
self.mock_client.node.create.return_value = self.node
self.mock_client.create_node.return_value = self.node
node_cache.create_node('fake')
self.mock_client.node.create.assert_called_once_with(driver='fake')
self.mock_client.create_node.assert_called_once_with(driver='fake')
mock_add_node.assert_called_once_with(
self.node.uuid,
istate.States.enrolling,
@ -911,12 +913,12 @@ class TestNodeCreate(test_base.NodeTest):
def test_create_with_args(self, mock_get_client, mock_add_node):
mock_get_client.return_value = self.mock_client
self.mock_client.node.create.return_value = self.node
self.mock_client.create_node.return_value = self.node
node_cache.create_node('agent_ipmitool', ironic=self.mock_client)
self.assertFalse(mock_get_client.called)
self.mock_client.node.create.assert_called_once_with(
self.mock_client.create_node.assert_called_once_with(
driver='agent_ipmitool')
mock_add_node.assert_called_once_with(
self.node.uuid,
@ -925,13 +927,13 @@ class TestNodeCreate(test_base.NodeTest):
def test_create_client_error(self, mock_get_client, mock_add_node):
mock_get_client.return_value = self.mock_client
self.mock_client.node.create.side_effect = (
node_cache.exceptions.InvalidAttribute)
self.mock_client.create_node.side_effect = (
node_cache.os_exc.SDKException)
node_cache.create_node('fake')
mock_get_client.assert_called_once_with()
self.mock_client.node.create.assert_called_once_with(driver='fake')
self.mock_client.create_node.assert_called_once_with(driver='fake')
self.assertFalse(mock_add_node.called)
@ -1334,9 +1336,8 @@ class TestRecordNode(test_base.NodeTest):
def setUp(self):
super(TestRecordNode, self).setUp()
self.node.provision_state = 'active'
self.ironic = mock.Mock(spec=['node'],
node=mock.Mock(spec=['get']))
self.ironic.node.get.return_value = self.node
self.ironic = mock.Mock(spec=['get_node'])
self.ironic.get_node.return_value = self.node
def test_no_lookup_data(self, mock_lookup):
self.assertRaisesRegex(utils.NotFoundInCacheError,

View File

@ -50,7 +50,8 @@ class TestEnrollNodeNotFoundHook(test_base.NodeTest):
mock_create_node.assert_called_once_with('fake-hardware',
ironic=self.ironic,
driver_info={})
driver_info={},
provision_state='enroll')
mock_check_existing.assert_called_once_with(
introspection_data, {}, self.ironic)
@ -67,7 +68,8 @@ class TestEnrollNodeNotFoundHook(test_base.NodeTest):
mock_create_node.assert_called_once_with(
'fake-hardware', ironic=self.ironic,
driver_info={'ipmi_address': self.bmc_address})
driver_info={'ipmi_address': self.bmc_address},
provision_state='enroll')
mock_check_existing.assert_called_once_with(
expected_data, {'ipmi_address': self.bmc_address}, self.ironic)
self.assertTrue(self.data['auto_discovered'])
@ -89,7 +91,8 @@ class TestEnrollNodeNotFoundHook(test_base.NodeTest):
mock_create_node.assert_called_once_with(
'fake-hardware', ironic=self.ironic,
driver_info={'ipmi_address': self.bmc_v6address})
driver_info={'ipmi_address': self.bmc_v6address},
provision_state='enroll')
mock_check_existing.assert_called_once_with(
expected_data, {'ipmi_address': self.bmc_v6address}, self.ironic)
self.assertTrue(self.data['auto_discovered'])
@ -108,13 +111,14 @@ class TestEnrollNodeNotFoundHook(test_base.NodeTest):
discovery.enroll_node_not_found_hook(introspection_data)
mock_create_node.assert_called_once_with('fake2', ironic=self.ironic,
driver_info={})
driver_info={},
provision_state='enroll')
mock_check_existing.assert_called_once_with(
{}, {}, self.ironic)
self.assertEqual({'auto_discovered': True}, introspection_data)
def test__check_existing_nodes_new_mac(self):
self.ironic.port.list.return_value = []
self.ironic.ports.return_value = []
introspection_data = {'macs': self.macs}
node_driver_info = {}
@ -122,7 +126,7 @@ class TestEnrollNodeNotFoundHook(test_base.NodeTest):
introspection_data, node_driver_info, self.ironic)
def test__check_existing_nodes_existing_mac(self):
self.ironic.port.list.return_value = [mock.MagicMock(
self.ironic.ports.return_value = [mock.MagicMock(
address=self.macs[0], uuid='fake_port')]
introspection_data = {
'all_interfaces': {'eth%d' % i: {'mac': m}
@ -135,7 +139,7 @@ class TestEnrollNodeNotFoundHook(test_base.NodeTest):
introspection_data, node_driver_info, self.ironic)
def test__check_existing_nodes_new_node(self):
self.ironic.node.list.return_value = [mock.MagicMock(
self.ironic.nodes.return_value = [mock.MagicMock(
driver_info={'ipmi_address': '1.2.4.3'}, uuid='fake_node')]
introspection_data = {}
node_driver_info = {'ipmi_address': self.bmc_address}
@ -144,7 +148,7 @@ class TestEnrollNodeNotFoundHook(test_base.NodeTest):
self.ironic)
def test__check_existing_nodes_existing_node(self):
self.ironic.node.list.return_value = [mock.MagicMock(
self.ironic.nodes.return_value = [mock.MagicMock(
driver_info={'ipmi_address': self.bmc_address}, uuid='fake_node')]
introspection_data = {}
node_driver_info = {'ipmi_address': self.bmc_address}

View File

@ -14,8 +14,8 @@
"""Tests for introspection rules plugins."""
from ironicclient import exceptions
import mock
from openstack import exceptions as os_exc
from ironic_inspector.common import ironic as ir_utils
from ironic_inspector import node_cache
@ -188,7 +188,7 @@ class TestSetAttributeAction(test_base.NodeTest):
@mock.patch.object(node_cache.NodeInfo, 'patch')
def test_apply_driver_not_supported(self, mock_patch):
for exc in (TypeError, exceptions.NotAcceptable):
for exc in (TypeError, os_exc.SDKException):
mock_patch.reset_mock()
mock_patch.side_effect = [exc, None]
params = {'path': '/driver', 'value': 'ipmi'}
@ -269,7 +269,7 @@ class TestAddTraitAction(test_base.NodeTest):
def test_add(self, mock_cli):
self.act.apply(self.node_info, self.params)
mock_cli.return_value.node.add_trait.assert_called_once_with(
mock_cli.return_value.add_node_trait.assert_called_once_with(
self.uuid, 'CUSTOM_FOO')
@ -284,12 +284,12 @@ class TestRemoveTraitAction(test_base.NodeTest):
def test_remove(self, mock_cli):
self.act.apply(self.node_info, self.params)
mock_cli.return_value.node.remove_trait.assert_called_once_with(
mock_cli.return_value.remove_node_trait.assert_called_once_with(
self.uuid, 'CUSTOM_FOO')
def test_remove_not_found(self, mock_cli):
mock_cli.return_value.node.remove_trait.side_effect = (
exceptions.NotFound('trait not found'))
mock_cli.return_value.remove_node_trait.side_effect = (
os_exc.NotFoundException('trait not found'))
self.act.apply(self.node_info, self.params)
mock_cli.return_value.node.remove_trait.assert_called_once_with(
mock_cli.return_value.remove_node_trait.assert_called_once_with(
self.uuid, 'CUSTOM_FOO')

View File

@ -343,15 +343,15 @@ class TestValidateInterfacesHookBeforeUpdatePXEEnabled(test_base.NodeTest):
sorted_interfaces = sorted(self.valid_interfaces.values(),
key=lambda i: i['mac'])
self.existing_ports = [
mock.Mock(spec=['address', 'uuid', 'pxe_enabled'],
address=iface['mac'], pxe_enabled=True)
mock.Mock(spec=['address', 'uuid', 'is_pxe_enabled'],
address=iface['mac'], is_pxe_enabled=True)
for iface in sorted_interfaces
]
self.node_info = node_cache.NodeInfo(uuid=self.uuid, started_at=0,
node=self.node,
ports=self.existing_ports)
def test_fix_pxe_enabled(self, mock_create_ports, mock_patch_port):
def test_fix_is_pxe_enabled(self, mock_create_ports, mock_patch_port):
self.hook.before_update(self.data, self.node_info)
# Note(milan) there are just 2 self.valid_interfaces, 'eth1' and 'ib0'
# eth1 is the PXE booting interface and eth1.mac < ib0.mac

View File

@ -20,8 +20,8 @@ import tempfile
import eventlet
import fixtures
from ironicclient import exceptions
import mock
from openstack import exceptions as os_exc
from oslo_config import cfg
from oslo_serialization import base64
from oslo_utils import timeutils
@ -73,7 +73,7 @@ class BaseProcessTest(BaseTest):
started_at=self.started_at)
self.node_info.finished = mock.Mock()
self.find_mock.return_value = self.node_info
self.cli.node.get.return_value = self.node
self.cli.get_node.return_value = self.node
self.process_mock = self.process_fixture.mock
self.process_mock.return_value = self.fake_result_json
self.addCleanup(self._cleanup_lock, self.node_info)
@ -93,7 +93,7 @@ class TestProcess(BaseProcessTest):
mac=mock.ANY)
actual_macs = self.find_mock.call_args[1]['mac']
self.assertEqual(sorted(self.all_macs), sorted(actual_macs))
self.cli.node.get.assert_called_once_with(self.uuid)
self.cli.get_node.assert_called_once_with(self.uuid)
self.process_mock.assert_called_once_with(
self.node_info, self.node, self.data)
@ -106,7 +106,7 @@ class TestProcess(BaseProcessTest):
mac=mock.ANY)
actual_macs = self.find_mock.call_args[1]['mac']
self.assertEqual(sorted(self.all_macs), sorted(actual_macs))
self.cli.node.get.assert_called_once_with(self.uuid)
self.cli.get_node.assert_called_once_with(self.uuid)
self.process_mock.assert_called_once_with(self.node_info, self.node,
self.data)
@ -119,7 +119,7 @@ class TestProcess(BaseProcessTest):
mac=mock.ANY)
actual_macs = self.find_mock.call_args[1]['mac']
self.assertEqual(sorted(self.all_macs), sorted(actual_macs))
self.cli.node.get.assert_called_once_with(self.uuid)
self.cli.get_node.assert_called_once_with(self.uuid)
self.process_mock.assert_called_once_with(self.node_info, self.node,
self.data)
@ -133,7 +133,7 @@ class TestProcess(BaseProcessTest):
mac=mock.ANY)
actual_macs = self.find_mock.call_args[1]['mac']
self.assertEqual(sorted(self.all_macs), sorted(actual_macs))
self.cli.node.get.assert_called_once_with(self.uuid)
self.cli.get_node.assert_called_once_with(self.uuid)
self.process_mock.assert_called_once_with(self.node_info, self.node,
self.data)
@ -142,14 +142,14 @@ class TestProcess(BaseProcessTest):
self.assertRaisesRegex(utils.Error,
'not found',
process.process, self.data)
self.assertFalse(self.cli.node.get.called)
self.assertFalse(self.cli.get_node.called)
self.assertFalse(self.process_mock.called)
@mock.patch.object(node_cache, 'record_node', autospec=True)
def test_not_found_in_cache_active_introspection(self, mock_record):
CONF.set_override('permit_active_introspection', True, 'processing')
self.find_mock.side_effect = utils.NotFoundInCacheError('not found')
self.cli.node.get.side_effect = exceptions.NotFound('boom')
self.cli.get_node.side_effect = os_exc.NotFoundException('boom')
self.cache_fixture.mock.acquire_lock = mock.Mock()
self.cache_fixture.mock.uuid = '1111'
self.cache_fixture.mock.finished_at = None
@ -169,7 +169,7 @@ class TestProcess(BaseProcessTest):
macs=mock.ANY)
actual_macs = mock_record.call_args[1]['macs']
self.assertEqual(sorted(self.all_macs), sorted(actual_macs))
self.cli.node.get.assert_not_called()
self.cli.get_node.assert_not_called()
self.process_mock.assert_called_once_with(
mock.ANY, mock.ANY, self.data)
@ -188,17 +188,17 @@ class TestProcess(BaseProcessTest):
mac=mock.ANY)
actual_macs = self.find_mock.call_args[1]['mac']
self.assertEqual(sorted(self.all_macs), sorted(actual_macs))
self.cli.node.get.assert_called_once_with(self.uuid)
self.cli.get_node.assert_called_once_with(self.uuid)
self.process_mock.assert_called_once_with(
mock.ANY, mock.ANY, self.data)
def test_not_found_in_ironic(self):
self.cli.node.get.side_effect = exceptions.NotFound()
self.cli.get_node.side_effect = os_exc.NotFoundException()
self.assertRaisesRegex(utils.Error,
'Node %s was not found' % self.uuid,
process.process, self.data)
self.cli.node.get.assert_called_once_with(self.uuid)
self.cli.get_node.assert_called_once_with(self.uuid)
self.assertFalse(self.process_mock.called)
self.node_info.finished.assert_called_once_with(
istate.Events.error, error=mock.ANY)
@ -367,7 +367,7 @@ class TestStoreLogs(BaseProcessTest):
self._check_contents()
def test_store_find_node_error(self, hook_mock):
self.cli.node.get.side_effect = exceptions.NotFound('boom')
self.cli.get_node.side_effect = os_exc.NotFoundException('boom')
self.assertRaises(utils.Error, process.process, self.data)
self._check_contents()
@ -431,11 +431,11 @@ class TestProcessNode(BaseTest):
self.data['interfaces'] = self.valid_interfaces
self.ports = self.all_ports
self.cli.node.get_boot_device.side_effect = (
self.cli.get_node.return_value.boot_device.side_effect = (
[RuntimeError()] * self.validate_attempts + [None])
self.cli.port.create.side_effect = self.ports
self.cli.node.update.return_value = self.node
self.cli.node.list_ports.return_value = []
self.cli.create_port.side_effect = self.ports
self.cli.update_node.return_value = self.node
self.cli.ports.return_value = []
self.useFixture(fixtures.MockPatchObject(
pxe_filter, 'driver', autospec=True))
@ -465,16 +465,17 @@ class TestProcessNode(BaseTest):
def test_ok(self, finished_mock, post_hook_mock):
process._process_node(self.node_info, self.node, self.data)
self.cli.port.create.assert_any_call(node_uuid=self.uuid,
self.cli.create_port.assert_any_call(node_uuid=self.uuid,
address=self.macs[0],
extra={},
pxe_enabled=True)
self.cli.port.create.assert_any_call(node_uuid=self.uuid,
is_pxe_enabled=True)
self.cli.create_port.assert_any_call(node_uuid=self.uuid,
address=self.macs[1],
extra={},
pxe_enabled=False)
self.cli.node.set_power_state.assert_called_once_with(self.uuid, 'off')
self.assertFalse(self.cli.node.validate.called)
is_pxe_enabled=False)
self.cli.set_node_power_state.assert_called_once_with(self.uuid,
'power off')
self.assertFalse(self.cli.validate_node.called)
post_hook_mock.assert_called_once_with(self.data, self.node_info)
finished_mock.assert_called_once_with(mock.ANY, istate.Events.finish)
@ -487,42 +488,43 @@ class TestProcessNode(BaseTest):
CONF.set_override('permit_active_introspection', True, 'processing')
process._process_node(self.node_info, self.node, self.data)
self.cli.port.create.assert_any_call(node_uuid=self.uuid,
self.cli.create_port.assert_any_call(node_uuid=self.uuid,
address=self.macs[0],
extra={},
pxe_enabled=True)
self.cli.port.create.assert_any_call(node_uuid=self.uuid,
is_pxe_enabled=True)
self.cli.create_port.assert_any_call(node_uuid=self.uuid,
address=self.macs[1],
extra={},
pxe_enabled=False)
is_pxe_enabled=False)
self.cli.node.set_power_state.assert_not_called()
self.assertFalse(self.cli.node.validate.called)
self.cli.set_node_power_state.assert_not_called()
self.assertFalse(self.cli.validate_node.called)
post_hook_mock.assert_called_once_with(mock.ANY, self.data,
self.node_info)
finished_mock.assert_called_once_with(mock.ANY, istate.Events.finish)
def test_port_failed(self):
self.cli.port.create.side_effect = (
[exceptions.Conflict()] + self.ports[1:])
self.cli.create_port.side_effect = (
[os_exc.ConflictException()] + self.ports[1:])
process._process_node(self.node_info, self.node, self.data)
self.cli.port.create.assert_any_call(node_uuid=self.uuid,
self.cli.create_port.assert_any_call(node_uuid=self.uuid,
address=self.macs[0],
extra={}, pxe_enabled=True)
self.cli.port.create.assert_any_call(node_uuid=self.uuid,
extra={}, is_pxe_enabled=True)
self.cli.create_port.assert_any_call(node_uuid=self.uuid,
address=self.macs[1],
extra={}, pxe_enabled=False)
extra={}, is_pxe_enabled=False)
@mock.patch.object(node_cache.NodeInfo, 'finished', autospec=True)
def test_power_off_failed(self, finished_mock):
self.cli.node.set_power_state.side_effect = RuntimeError('boom')
self.cli.set_node_power_state.side_effect = RuntimeError('boom')
process._process_node(self.node_info, self.node, self.data)
self.cli.node.set_power_state.assert_called_once_with(self.uuid, 'off')
self.cli.set_node_power_state.assert_called_once_with(self.uuid,
'power off')
finished_mock.assert_called_once_with(
mock.ANY, istate.Events.error,
error='Failed to power off node %s, check its power '
@ -538,7 +540,7 @@ class TestProcessNode(BaseTest):
process._process_node(self.node_info, self.node, self.data)
self.assertTrue(post_hook_mock.called)
self.assertTrue(self.cli.node.set_power_state.called)
self.assertTrue(self.cli.set_node_power_state.called)
finished_mock.assert_called_once_with(
self.node_info, istate.Events.finish)
@ -547,7 +549,7 @@ class TestProcessNode(BaseTest):
CONF.set_override('power_off', False, 'processing')
process._process_node(self.node_info, self.node, self.data)
self.assertFalse(self.cli.node.set_power_state.called)
self.assertFalse(self.cli.set_node_power_state.called)
finished_mock.assert_called_once_with(
self.node_info, istate.Events.finish)
@ -682,9 +684,9 @@ class TestReapplyNode(BaseTest):
node=self.node)
self.node_info.invalidate_cache = mock.Mock()
self.cli.port.create.side_effect = self.ports
self.cli.node.update.return_value = self.node
self.cli.node.list_ports.return_value = []
self.cli.create_port.side_effect = self.ports
self.cli.update_node.return_value = self.node
self.cli.ports.return_value = []
self.node_info._state = istate.States.finished
self.commit_fixture = self.useFixture(
fixtures.MockPatchObject(node_cache.NodeInfo, 'commit',
@ -721,7 +723,7 @@ class TestReapplyNode(BaseTest):
apply_mock.assert_called_once_with(self.node_info, self.data)
# assert no power operations were performed
self.assertFalse(self.cli.node.set_power_state.called)
self.assertFalse(self.cli.set_node_power_state.called)
finished_mock.assert_called_once_with(
self.node_info, istate.Events.finish)
@ -731,11 +733,11 @@ class TestReapplyNode(BaseTest):
# assert ports were created with whatever there was left
# behind validate_interfaces
self.cli.port.create.assert_called_once_with(
self.cli.create_port.assert_called_once_with(
node_uuid=self.uuid,
address=self.data['macs'][0],
extra={},
pxe_enabled=True
is_pxe_enabled=True
)
@prepare_mocks

View File

@ -19,7 +19,7 @@ keystonemiddleware==4.18.0
mock==3.0.0
netaddr==0.7.18
openstackdocstheme==1.20.0
openstacksdk==0.30.0
openstacksdk==0.40.0
os-api-ref==1.4.0
oslo.concurrency==3.26.0
oslo.config==5.2.0

View File

@ -17,7 +17,7 @@ netaddr>=0.7.18 # BSD
pbr!=2.1.0,>=2.0.0 # Apache-2.0
python-ironicclient!=2.5.2,!=2.7.1,!=3.0.0,>=2.3.0 # Apache-2.0
pytz>=2013.6 # MIT
openstacksdk>=0.30.0 # Apache-2.0
openstacksdk>=0.40.0 # Apache-2.0
oslo.concurrency>=3.26.0 # Apache-2.0
oslo.config>=5.2.0 # Apache-2.0
oslo.context>=2.19.2 # Apache-2.0