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:
parent
e6ece052ec
commit
3accdfbbc6
@ -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 '
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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 "
|
||||
|
@ -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},
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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 = [
|
||||
|
@ -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)
|
||||
|
@ -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'})
|
||||
|
@ -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)
|
||||
|
@ -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]])
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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}
|
||||
|
@ -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')
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user