Add portgroups to support LAG interfaces - RPC
Ironic should be able to provide the requisite connectivity information to the Neutron ML2 plugin to allow drivers to provision the top-of-rack switch for the bare metal server. The addition of portgroups in Ironic allows the concept of link aggregation to be handled in Ironic in order to provide support for cases where multiple interfaces on the bare metal server connect to switch ports of a single LAG. This commit includes changes to: - the RPC API (to include portgroup methods) - the RPC tests Partial-bug: #1526403 DocImpact Co-Authored-By: Jenny Moorehead (jenny.moorehead@sap.com) Co-Authored-By: Will Stevenson (will.stevenson@sap.com) Change-Id: Iac6355e615e57e6ed002facd6795c9ff06188998
This commit is contained in:
parent
134ad4cbf6
commit
a603e3c12c
|
@ -184,7 +184,7 @@ class ConductorManager(base_manager.BaseConductorManager):
|
||||||
"""Ironic Conductor manager main class."""
|
"""Ironic Conductor manager main class."""
|
||||||
|
|
||||||
# NOTE(rloo): This must be in sync with rpcapi.ConductorAPI's.
|
# NOTE(rloo): This must be in sync with rpcapi.ConductorAPI's.
|
||||||
RPC_API_VERSION = '1.32'
|
RPC_API_VERSION = '1.33'
|
||||||
|
|
||||||
target = messaging.Target(version=RPC_API_VERSION)
|
target = messaging.Target(version=RPC_API_VERSION)
|
||||||
|
|
||||||
|
@ -1511,6 +1511,30 @@ class ConductorManager(base_manager.BaseConductorManager):
|
||||||
'%(node)s'),
|
'%(node)s'),
|
||||||
{'port': port.uuid, 'node': task.node.uuid})
|
{'port': port.uuid, 'node': task.node.uuid})
|
||||||
|
|
||||||
|
@messaging.expected_exceptions(exception.NodeLocked,
|
||||||
|
exception.NodeNotFound,
|
||||||
|
exception.PortgroupNotEmpty)
|
||||||
|
def destroy_portgroup(self, context, portgroup):
|
||||||
|
"""Delete a portgroup.
|
||||||
|
|
||||||
|
:param context: request context.
|
||||||
|
:param portgroup: portgroup object
|
||||||
|
:raises: NodeLocked if node is locked by another conductor.
|
||||||
|
:raises: NodeNotFound if the node associated with the portgroup does
|
||||||
|
not exist.
|
||||||
|
:raises: PortgroupNotEmpty if portgroup is not empty
|
||||||
|
|
||||||
|
"""
|
||||||
|
LOG.debug('RPC destroy_portgroup called for portgroup %(portgroup)s',
|
||||||
|
{'portgroup': portgroup.uuid})
|
||||||
|
with task_manager.acquire(context, portgroup.node_id,
|
||||||
|
purpose='portgroup deletion') as task:
|
||||||
|
portgroup.destroy()
|
||||||
|
LOG.info(_LI('Successfully deleted portgroup %(portgroup)s. '
|
||||||
|
'The node associated with the portgroup was '
|
||||||
|
'%(node)s'),
|
||||||
|
{'portgroup': portgroup.uuid, 'node': task.node.uuid})
|
||||||
|
|
||||||
@messaging.expected_exceptions(exception.NodeLocked,
|
@messaging.expected_exceptions(exception.NodeLocked,
|
||||||
exception.UnsupportedDriverExtension,
|
exception.UnsupportedDriverExtension,
|
||||||
exception.NodeConsoleNotEnabled,
|
exception.NodeConsoleNotEnabled,
|
||||||
|
@ -1616,7 +1640,8 @@ class ConductorManager(base_manager.BaseConductorManager):
|
||||||
|
|
||||||
@messaging.expected_exceptions(exception.NodeLocked,
|
@messaging.expected_exceptions(exception.NodeLocked,
|
||||||
exception.FailedToUpdateMacOnPort,
|
exception.FailedToUpdateMacOnPort,
|
||||||
exception.MACAlreadyExists)
|
exception.MACAlreadyExists,
|
||||||
|
exception.InvalidState)
|
||||||
def update_port(self, context, port_obj):
|
def update_port(self, context, port_obj):
|
||||||
"""Update a port.
|
"""Update a port.
|
||||||
|
|
||||||
|
@ -1627,6 +1652,9 @@ class ConductorManager(base_manager.BaseConductorManager):
|
||||||
failed.
|
failed.
|
||||||
:raises: MACAlreadyExists if the update is setting a MAC which is
|
:raises: MACAlreadyExists if the update is setting a MAC which is
|
||||||
registered on another port already.
|
registered on another port already.
|
||||||
|
:raises: InvalidState if port connectivity attributes
|
||||||
|
are updated while node not in a MANAGEABLE or ENROLL or
|
||||||
|
INSPECTING state or not in MAINTENANCE mode.
|
||||||
"""
|
"""
|
||||||
port_uuid = port_obj.uuid
|
port_uuid = port_obj.uuid
|
||||||
LOG.debug("RPC update_port called for port %s.", port_uuid)
|
LOG.debug("RPC update_port called for port %s.", port_uuid)
|
||||||
|
@ -1634,6 +1662,32 @@ class ConductorManager(base_manager.BaseConductorManager):
|
||||||
with task_manager.acquire(context, port_obj.node_id,
|
with task_manager.acquire(context, port_obj.node_id,
|
||||||
purpose='port update') as task:
|
purpose='port update') as task:
|
||||||
node = task.node
|
node = task.node
|
||||||
|
|
||||||
|
# If port update is modifying the portgroup membership of the port
|
||||||
|
# or modifying the local_link_connection or pxe_enabled flags then
|
||||||
|
# node should be in MANAGEABLE/INSPECTING/ENROLL provisioning state
|
||||||
|
# or in maintenance mode.
|
||||||
|
# Otherwise InvalidState exception is raised.
|
||||||
|
connectivity_attr = {'portgroup_uuid',
|
||||||
|
'pxe_enabled',
|
||||||
|
'local_link_connection'}
|
||||||
|
allowed_update_states = [states.ENROLL,
|
||||||
|
states.INSPECTING,
|
||||||
|
states.MANAGEABLE]
|
||||||
|
if (set(port_obj.obj_what_changed()) & connectivity_attr
|
||||||
|
and not (task.node.provision_state in allowed_update_states
|
||||||
|
or task.node.maintenance)):
|
||||||
|
action = _("Port %(port)s can not have any connectivity "
|
||||||
|
"attributes (%(connect)s) updated unless "
|
||||||
|
"node %(node)s is in a %(allowed)s state "
|
||||||
|
"or in maintenance mode.")
|
||||||
|
|
||||||
|
raise exception.InvalidState(
|
||||||
|
action % {'port': port_uuid,
|
||||||
|
'node': task.node.uuid,
|
||||||
|
'connect': ', '.join(connectivity_attr),
|
||||||
|
'allowed': ', '.join(allowed_update_states)})
|
||||||
|
|
||||||
if 'address' in port_obj.obj_what_changed():
|
if 'address' in port_obj.obj_what_changed():
|
||||||
vif = port_obj.extra.get('vif_port_id')
|
vif = port_obj.extra.get('vif_port_id')
|
||||||
if vif:
|
if vif:
|
||||||
|
@ -1653,6 +1707,51 @@ class ConductorManager(base_manager.BaseConductorManager):
|
||||||
|
|
||||||
return port_obj
|
return port_obj
|
||||||
|
|
||||||
|
@messaging.expected_exceptions(exception.NodeLocked,
|
||||||
|
exception.FailedToUpdateMacOnPort,
|
||||||
|
exception.PortgroupMACAlreadyExists)
|
||||||
|
def update_portgroup(self, context, portgroup_obj):
|
||||||
|
"""Update a portgroup.
|
||||||
|
|
||||||
|
:param context: request context.
|
||||||
|
:param portgroup_obj: a changed (but not saved) portgroup object.
|
||||||
|
:raises: DHCPLoadError if the dhcp_provider cannot be loaded.
|
||||||
|
:raises: FailedToUpdateMacOnPort if MAC address changed and update
|
||||||
|
failed.
|
||||||
|
:raises: PortgroupMACAlreadyExists if the update is setting a MAC which
|
||||||
|
is registered on another portgroup already.
|
||||||
|
"""
|
||||||
|
portgroup_uuid = portgroup_obj.uuid
|
||||||
|
LOG.debug("RPC update_portgroup called for portgroup %s.",
|
||||||
|
portgroup_uuid)
|
||||||
|
lock_purpose = 'update portgroup'
|
||||||
|
with task_manager.acquire(context,
|
||||||
|
portgroup_obj.node_id,
|
||||||
|
purpose=lock_purpose) as task:
|
||||||
|
node = task.node
|
||||||
|
if 'address' in portgroup_obj.obj_what_changed():
|
||||||
|
vif = portgroup_obj.extra.get('vif_portgroup_id')
|
||||||
|
if vif:
|
||||||
|
api = dhcp_factory.DHCPFactory()
|
||||||
|
api.provider.update_port_address(
|
||||||
|
vif,
|
||||||
|
portgroup_obj.address,
|
||||||
|
token=context.auth_token)
|
||||||
|
# Log warning if there is no vif_portgroup_id and an instance
|
||||||
|
# is associated with the node.
|
||||||
|
elif node.instance_uuid:
|
||||||
|
LOG.warning(_LW(
|
||||||
|
"No VIF was found for instance %(instance)s "
|
||||||
|
"on node %(node)s, when attempting to update "
|
||||||
|
"portgroup %(portgroup)s MAC address."),
|
||||||
|
{'portgroup': portgroup_uuid,
|
||||||
|
'instance': node.instance_uuid,
|
||||||
|
'node': node.uuid})
|
||||||
|
|
||||||
|
portgroup_obj.save()
|
||||||
|
|
||||||
|
return portgroup_obj
|
||||||
|
|
||||||
@messaging.expected_exceptions(exception.DriverNotFound)
|
@messaging.expected_exceptions(exception.DriverNotFound)
|
||||||
def get_driver_properties(self, context, driver_name):
|
def get_driver_properties(self, context, driver_name):
|
||||||
"""Get the properties of the driver.
|
"""Get the properties of the driver.
|
||||||
|
|
|
@ -79,11 +79,12 @@ class ConductorAPI(object):
|
||||||
| object_class_action_versions, object_action and
|
| object_class_action_versions, object_action and
|
||||||
| object_backport_versions
|
| object_backport_versions
|
||||||
| 1.32 - Add do_node_clean
|
| 1.32 - Add do_node_clean
|
||||||
|
| 1.33 - Added update and destroy portgroup.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# NOTE(rloo): This must be in sync with manager.ConductorManager's.
|
# NOTE(rloo): This must be in sync with manager.ConductorManager's.
|
||||||
RPC_API_VERSION = '1.32'
|
RPC_API_VERSION = '1.33'
|
||||||
|
|
||||||
def __init__(self, topic=None):
|
def __init__(self, topic=None):
|
||||||
super(ConductorAPI, self).__init__()
|
super(ConductorAPI, self).__init__()
|
||||||
|
@ -435,6 +436,38 @@ class ConductorAPI(object):
|
||||||
cctxt = self.client.prepare(topic=topic or self.topic, version='1.13')
|
cctxt = self.client.prepare(topic=topic or self.topic, version='1.13')
|
||||||
return cctxt.call(context, 'update_port', port_obj=port_obj)
|
return cctxt.call(context, 'update_port', port_obj=port_obj)
|
||||||
|
|
||||||
|
def update_portgroup(self, context, portgroup_obj, topic=None):
|
||||||
|
"""Synchronously, have a conductor update the portgroup's information.
|
||||||
|
|
||||||
|
Update the portgroup's information in the database and return a
|
||||||
|
portgroup object.
|
||||||
|
The conductor will lock related node and trigger specific driver
|
||||||
|
actions if they are needed.
|
||||||
|
|
||||||
|
:param context: request context.
|
||||||
|
:param portgroup_obj: a changed (but not saved) portgroup object.
|
||||||
|
:param topic: RPC topic. Defaults to self.topic.
|
||||||
|
:returns: updated portgroup object, including all fields.
|
||||||
|
|
||||||
|
"""
|
||||||
|
cctxt = self.client.prepare(topic=topic or self.topic, version='1.33')
|
||||||
|
return cctxt.call(context, 'update_portgroup',
|
||||||
|
portgroup_obj=portgroup_obj)
|
||||||
|
|
||||||
|
def destroy_portgroup(self, context, portgroup, topic=None):
|
||||||
|
"""Delete a portgroup.
|
||||||
|
|
||||||
|
:param context: request context.
|
||||||
|
:param portgroup: portgroup object
|
||||||
|
:param topic: RPC topic. Defaults to self.topic.
|
||||||
|
:raises: NodeLocked if node is locked by another conductor.
|
||||||
|
:raises: NodeNotFound if the node associated with the portgroup does
|
||||||
|
not exist.
|
||||||
|
:raises: PortgroupNotEmpty if portgroup is not empty
|
||||||
|
"""
|
||||||
|
cctxt = self.client.prepare(topic=topic or self.topic, version='1.33')
|
||||||
|
return cctxt.call(context, 'destroy_portgroup', portgroup=portgroup)
|
||||||
|
|
||||||
def get_driver_properties(self, context, driver_name, topic=None):
|
def get_driver_properties(self, context, driver_name, topic=None):
|
||||||
"""Get the properties of the driver.
|
"""Get the properties of the driver.
|
||||||
|
|
||||||
|
|
|
@ -204,7 +204,10 @@ class TaskManager(object):
|
||||||
else:
|
else:
|
||||||
self._debug_timer.restart()
|
self._debug_timer.restart()
|
||||||
self.node = objects.Node.get(context, node_id)
|
self.node = objects.Node.get(context, node_id)
|
||||||
|
|
||||||
self.ports = objects.Port.list_by_node_id(context, self.node.id)
|
self.ports = objects.Port.list_by_node_id(context, self.node.id)
|
||||||
|
self.portgroups = objects.Portgroup.list_by_node_id(context,
|
||||||
|
self.node.id)
|
||||||
self.driver = driver_factory.get_driver(driver_name or
|
self.driver = driver_factory.get_driver(driver_name or
|
||||||
self.node.driver)
|
self.node.driver)
|
||||||
|
|
||||||
|
@ -313,6 +316,7 @@ class TaskManager(object):
|
||||||
self.node = None
|
self.node = None
|
||||||
self.driver = None
|
self.driver = None
|
||||||
self.ports = None
|
self.ports = None
|
||||||
|
self.portgroups = None
|
||||||
self.fsm = None
|
self.fsm = None
|
||||||
|
|
||||||
def _thread_release_resources(self, t):
|
def _thread_release_resources(self, t):
|
||||||
|
|
|
@ -2580,6 +2580,44 @@ class UpdatePortTestCase(mgr_utils.ServiceSetUpMixin,
|
||||||
self.assertEqual(new_address, res.address)
|
self.assertEqual(new_address, res.address)
|
||||||
self.assertFalse(mac_update_mock.called)
|
self.assertFalse(mac_update_mock.called)
|
||||||
|
|
||||||
|
def test_update_port_node_deleting_state(self):
|
||||||
|
node = obj_utils.create_test_node(self.context, driver='fake',
|
||||||
|
provision_state=states.DELETING)
|
||||||
|
port = obj_utils.create_test_port(self.context,
|
||||||
|
node_id=node.id,
|
||||||
|
extra={'foo': 'bar'})
|
||||||
|
old_pxe = port.pxe_enabled
|
||||||
|
port.pxe_enabled = True
|
||||||
|
exc = self.assertRaises(messaging.rpc.ExpectedException,
|
||||||
|
self.service.update_port,
|
||||||
|
self.context, port)
|
||||||
|
self.assertEqual(exception.InvalidState, exc.exc_info[0])
|
||||||
|
port.refresh()
|
||||||
|
self.assertEqual(old_pxe, port.pxe_enabled)
|
||||||
|
|
||||||
|
def test_update_port_node_manageable_state(self):
|
||||||
|
node = obj_utils.create_test_node(self.context, driver='fake',
|
||||||
|
provision_state=states.MANAGEABLE)
|
||||||
|
port = obj_utils.create_test_port(self.context,
|
||||||
|
node_id=node.id,
|
||||||
|
extra={'foo': 'bar'})
|
||||||
|
port.pxe_enabled = True
|
||||||
|
self.service.update_port(self.context, port)
|
||||||
|
port.refresh()
|
||||||
|
self.assertEqual(True, port.pxe_enabled)
|
||||||
|
|
||||||
|
def test_update_port_node_active_state_and_maintenance(self):
|
||||||
|
node = obj_utils.create_test_node(self.context, driver='fake',
|
||||||
|
provision_state=states.ACTIVE,
|
||||||
|
maintenance=True)
|
||||||
|
port = obj_utils.create_test_port(self.context,
|
||||||
|
node_id=node.id,
|
||||||
|
extra={'foo': 'bar'})
|
||||||
|
port.pxe_enabled = True
|
||||||
|
self.service.update_port(self.context, port)
|
||||||
|
port.refresh()
|
||||||
|
self.assertEqual(True, port.pxe_enabled)
|
||||||
|
|
||||||
def test__filter_out_unsupported_types_all(self):
|
def test__filter_out_unsupported_types_all(self):
|
||||||
self._start_service()
|
self._start_service()
|
||||||
CONF.set_override('send_sensor_data_types', ['All'], group='conductor')
|
CONF.set_override('send_sensor_data_types', ['All'], group='conductor')
|
||||||
|
@ -2780,6 +2818,80 @@ class UpdatePortTestCase(mgr_utils.ServiceSetUpMixin,
|
||||||
exc.exc_info[0])
|
exc.exc_info[0])
|
||||||
|
|
||||||
|
|
||||||
|
@mgr_utils.mock_record_keepalive
|
||||||
|
class UpdatePortgroupTestCase(mgr_utils.ServiceSetUpMixin,
|
||||||
|
tests_db_base.DbTestCase):
|
||||||
|
def test_update_portgroup(self):
|
||||||
|
node = obj_utils.create_test_node(self.context, driver='fake')
|
||||||
|
portgroup = obj_utils.create_test_portgroup(self.context,
|
||||||
|
node_id=node.id,
|
||||||
|
extra={'foo': 'bar'})
|
||||||
|
new_extra = {'foo': 'baz'}
|
||||||
|
portgroup.extra = new_extra
|
||||||
|
self.service.update_portgroup(self.context, portgroup)
|
||||||
|
portgroup.refresh()
|
||||||
|
self.assertEqual(new_extra, portgroup.extra)
|
||||||
|
|
||||||
|
def test_update_portgroup_node_locked(self):
|
||||||
|
node = obj_utils.create_test_node(self.context, driver='fake',
|
||||||
|
reservation='fake-reserv')
|
||||||
|
portgroup = obj_utils.create_test_portgroup(self.context,
|
||||||
|
node_id=node.id)
|
||||||
|
old_extra = portgroup.extra
|
||||||
|
portgroup.extra = {'foo': 'baz'}
|
||||||
|
exc = self.assertRaises(messaging.rpc.ExpectedException,
|
||||||
|
self.service.update_portgroup,
|
||||||
|
self.context, portgroup)
|
||||||
|
# Compare true exception hidden by @messaging.expected_exceptions
|
||||||
|
self.assertEqual(exception.NodeLocked, exc.exc_info[0])
|
||||||
|
portgroup.refresh()
|
||||||
|
self.assertEqual(old_extra, portgroup.extra)
|
||||||
|
|
||||||
|
@mock.patch('ironic.dhcp.neutron.NeutronDHCPApi.update_port_address')
|
||||||
|
def test_update_portgroup_address(self, mac_update_mock):
|
||||||
|
node = obj_utils.create_test_node(self.context, driver='fake')
|
||||||
|
pg = obj_utils.create_test_portgroup(
|
||||||
|
self.context, node_id=node.id,
|
||||||
|
extra={'vif_portgroup_id': 'fake-id'})
|
||||||
|
new_address = '11:22:33:44:55:bb'
|
||||||
|
pg.address = new_address
|
||||||
|
self.service.update_portgroup(self.context, pg)
|
||||||
|
pg.refresh()
|
||||||
|
self.assertEqual(new_address, pg.address)
|
||||||
|
mac_update_mock.assert_called_once_with('fake-id', new_address,
|
||||||
|
token=self.context.auth_token)
|
||||||
|
|
||||||
|
@mock.patch('ironic.dhcp.neutron.NeutronDHCPApi.update_port_address')
|
||||||
|
def test_update_portgroup_address_fail(self, mac_update_mock):
|
||||||
|
node = obj_utils.create_test_node(self.context, driver='fake')
|
||||||
|
pg = obj_utils.create_test_portgroup(
|
||||||
|
self.context, node_id=node.id,
|
||||||
|
extra={'vif_portgroup_id': 'fake-id'})
|
||||||
|
old_address = pg.address
|
||||||
|
pg.address = '11:22:33:44:55:bb'
|
||||||
|
mac_update_mock.side_effect = (
|
||||||
|
exception.FailedToUpdateMacOnPort(port_id=pg.uuid))
|
||||||
|
exc = self.assertRaises(messaging.rpc.ExpectedException,
|
||||||
|
self.service.update_portgroup,
|
||||||
|
self.context, pg)
|
||||||
|
# Compare true exception hidden by @messaging.expected_exceptions
|
||||||
|
self.assertEqual(exception.FailedToUpdateMacOnPort, exc.exc_info[0])
|
||||||
|
pg.refresh()
|
||||||
|
self.assertEqual(old_address, pg.address)
|
||||||
|
|
||||||
|
@mock.patch('ironic.dhcp.neutron.NeutronDHCPApi.update_port_address')
|
||||||
|
def test_update_portgroup_address_no_vif_id(self, mac_update_mock):
|
||||||
|
node = obj_utils.create_test_node(self.context, driver='fake')
|
||||||
|
pg = obj_utils.create_test_port(self.context, node_id=node.id)
|
||||||
|
|
||||||
|
new_address = '11:22:33:44:55:bb'
|
||||||
|
pg.address = new_address
|
||||||
|
self.service.update_portgroup(self.context, pg)
|
||||||
|
pg.refresh()
|
||||||
|
self.assertEqual(new_address, pg.address)
|
||||||
|
self.assertFalse(mac_update_mock.called)
|
||||||
|
|
||||||
|
|
||||||
@mgr_utils.mock_record_keepalive
|
@mgr_utils.mock_record_keepalive
|
||||||
class RaidTestCases(mgr_utils.ServiceSetUpMixin, tests_db_base.DbTestCase):
|
class RaidTestCases(mgr_utils.ServiceSetUpMixin, tests_db_base.DbTestCase):
|
||||||
|
|
||||||
|
@ -4284,6 +4396,28 @@ class DestroyPortTestCase(mgr_utils.ServiceSetUpMixin,
|
||||||
self.assertEqual(exception.NodeLocked, exc.exc_info[0])
|
self.assertEqual(exception.NodeLocked, exc.exc_info[0])
|
||||||
|
|
||||||
|
|
||||||
|
@mgr_utils.mock_record_keepalive
|
||||||
|
class DestroyPortgroupTestCase(mgr_utils.ServiceSetUpMixin,
|
||||||
|
tests_db_base.DbTestCase):
|
||||||
|
def test_destroy_portgroup(self):
|
||||||
|
node = obj_utils.create_test_node(self.context, driver='fake')
|
||||||
|
portgroup = obj_utils.create_test_portgroup(self.context,
|
||||||
|
node_id=node.id)
|
||||||
|
self.service.destroy_portgroup(self.context, portgroup)
|
||||||
|
self.assertRaises(exception.PortgroupNotFound, portgroup.refresh)
|
||||||
|
|
||||||
|
def test_destroy_portgroup_node_locked(self):
|
||||||
|
node = obj_utils.create_test_node(self.context, driver='fake',
|
||||||
|
reservation='fake-reserv')
|
||||||
|
portgroup = obj_utils.create_test_portgroup(self.context,
|
||||||
|
node_id=node.id)
|
||||||
|
exc = self.assertRaises(messaging.rpc.ExpectedException,
|
||||||
|
self.service.destroy_portgroup,
|
||||||
|
self.context, portgroup)
|
||||||
|
# Compare true exception hidden by @messaging.expected_exceptions
|
||||||
|
self.assertEqual(exception.NodeLocked, exc.exc_info[0])
|
||||||
|
|
||||||
|
|
||||||
@mgr_utils.mock_record_keepalive
|
@mgr_utils.mock_record_keepalive
|
||||||
@mock.patch.object(manager.ConductorManager, '_fail_if_in_state')
|
@mock.patch.object(manager.ConductorManager, '_fail_if_in_state')
|
||||||
@mock.patch.object(manager.ConductorManager, '_mapped_to_this_conductor')
|
@mock.patch.object(manager.ConductorManager, '_mapped_to_this_conductor')
|
||||||
|
|
|
@ -53,6 +53,7 @@ class RPCAPITestCase(base.DbTestCase):
|
||||||
self.fake_node = dbutils.get_test_node(driver='fake-driver')
|
self.fake_node = dbutils.get_test_node(driver='fake-driver')
|
||||||
self.fake_node_obj = objects.Node._from_db_object(
|
self.fake_node_obj = objects.Node._from_db_object(
|
||||||
objects.Node(self.context), self.fake_node)
|
objects.Node(self.context), self.fake_node)
|
||||||
|
self.fake_portgroup = dbutils.get_test_portgroup()
|
||||||
|
|
||||||
def test_serialized_instance_has_uuid(self):
|
def test_serialized_instance_has_uuid(self):
|
||||||
self.assertTrue('uuid' in self.fake_node)
|
self.assertTrue('uuid' in self.fake_node)
|
||||||
|
@ -380,3 +381,15 @@ class RPCAPITestCase(base.DbTestCase):
|
||||||
rpcapi.object_backport_versions, self.context,
|
rpcapi.object_backport_versions, self.context,
|
||||||
objinst='fake-object',
|
objinst='fake-object',
|
||||||
object_versions={'fake-object': '1.0'})
|
object_versions={'fake-object': '1.0'})
|
||||||
|
|
||||||
|
def test_update_portgroup(self):
|
||||||
|
self._test_rpcapi('update_portgroup',
|
||||||
|
'call',
|
||||||
|
version='1.33',
|
||||||
|
portgroup_obj=self.fake_portgroup)
|
||||||
|
|
||||||
|
def test_destroy_portgroup(self):
|
||||||
|
self._test_rpcapi('destroy_portgroup',
|
||||||
|
'call',
|
||||||
|
version='1.33',
|
||||||
|
portgroup=self.fake_portgroup)
|
||||||
|
|
|
@ -38,6 +38,7 @@ from ironic.tests.unit.objects import utils as obj_utils
|
||||||
@mock.patch.object(objects.Node, 'reserve')
|
@mock.patch.object(objects.Node, 'reserve')
|
||||||
@mock.patch.object(driver_factory, 'get_driver')
|
@mock.patch.object(driver_factory, 'get_driver')
|
||||||
@mock.patch.object(objects.Port, 'list_by_node_id')
|
@mock.patch.object(objects.Port, 'list_by_node_id')
|
||||||
|
@mock.patch.object(objects.Portgroup, 'list_by_node_id')
|
||||||
class TaskManagerTestCase(tests_db_base.DbTestCase):
|
class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TaskManagerTestCase, self).setUp()
|
super(TaskManagerTestCase, self).setUp()
|
||||||
|
@ -47,68 +48,77 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
self.config(node_locked_retry_interval=0, group='conductor')
|
self.config(node_locked_retry_interval=0, group='conductor')
|
||||||
self.node = obj_utils.create_test_node(self.context)
|
self.node = obj_utils.create_test_node(self.context)
|
||||||
|
|
||||||
def test_excl_lock(self, get_ports_mock, get_driver_mock,
|
def test_excl_lock(self, get_portgroups_mock, get_ports_mock,
|
||||||
reserve_mock, release_mock, node_get_mock):
|
get_driver_mock, reserve_mock, release_mock,
|
||||||
|
node_get_mock):
|
||||||
reserve_mock.return_value = self.node
|
reserve_mock.return_value = self.node
|
||||||
with task_manager.TaskManager(self.context, 'fake-node-id') as task:
|
with task_manager.TaskManager(self.context, 'fake-node-id') as task:
|
||||||
self.assertEqual(self.context, task.context)
|
self.assertEqual(self.context, task.context)
|
||||||
self.assertEqual(self.node, task.node)
|
self.assertEqual(self.node, task.node)
|
||||||
self.assertEqual(get_ports_mock.return_value, task.ports)
|
self.assertEqual(get_ports_mock.return_value, task.ports)
|
||||||
|
self.assertEqual(get_portgroups_mock.return_value, task.portgroups)
|
||||||
self.assertEqual(get_driver_mock.return_value, task.driver)
|
self.assertEqual(get_driver_mock.return_value, task.driver)
|
||||||
self.assertFalse(task.shared)
|
self.assertFalse(task.shared)
|
||||||
|
|
||||||
reserve_mock.assert_called_once_with(self.context, self.host,
|
reserve_mock.assert_called_once_with(self.context, self.host,
|
||||||
'fake-node-id')
|
'fake-node-id')
|
||||||
get_ports_mock.assert_called_once_with(self.context, self.node.id)
|
get_ports_mock.assert_called_once_with(self.context, self.node.id)
|
||||||
|
get_portgroups_mock.assert_called_once_with(self.context, self.node.id)
|
||||||
get_driver_mock.assert_called_once_with(self.node.driver)
|
get_driver_mock.assert_called_once_with(self.node.driver)
|
||||||
release_mock.assert_called_once_with(self.context, self.host,
|
release_mock.assert_called_once_with(self.context, self.host,
|
||||||
self.node.id)
|
self.node.id)
|
||||||
self.assertFalse(node_get_mock.called)
|
self.assertFalse(node_get_mock.called)
|
||||||
|
|
||||||
def test_excl_lock_with_driver(self, get_ports_mock, get_driver_mock,
|
def test_excl_lock_with_driver(
|
||||||
reserve_mock, release_mock,
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
node_get_mock):
|
reserve_mock, release_mock, node_get_mock):
|
||||||
reserve_mock.return_value = self.node
|
reserve_mock.return_value = self.node
|
||||||
with task_manager.TaskManager(self.context, 'fake-node-id',
|
with task_manager.TaskManager(self.context, 'fake-node-id',
|
||||||
driver_name='fake-driver') as task:
|
driver_name='fake-driver') as task:
|
||||||
self.assertEqual(self.context, task.context)
|
self.assertEqual(self.context, task.context)
|
||||||
self.assertEqual(self.node, task.node)
|
self.assertEqual(self.node, task.node)
|
||||||
self.assertEqual(get_ports_mock.return_value, task.ports)
|
self.assertEqual(get_ports_mock.return_value, task.ports)
|
||||||
|
self.assertEqual(get_portgroups_mock.return_value, task.portgroups)
|
||||||
self.assertEqual(get_driver_mock.return_value, task.driver)
|
self.assertEqual(get_driver_mock.return_value, task.driver)
|
||||||
self.assertFalse(task.shared)
|
self.assertFalse(task.shared)
|
||||||
|
|
||||||
reserve_mock.assert_called_once_with(self.context, self.host,
|
reserve_mock.assert_called_once_with(self.context, self.host,
|
||||||
'fake-node-id')
|
'fake-node-id')
|
||||||
get_ports_mock.assert_called_once_with(self.context, self.node.id)
|
get_ports_mock.assert_called_once_with(self.context, self.node.id)
|
||||||
|
get_portgroups_mock.assert_called_once_with(self.context, self.node.id)
|
||||||
get_driver_mock.assert_called_once_with('fake-driver')
|
get_driver_mock.assert_called_once_with('fake-driver')
|
||||||
release_mock.assert_called_once_with(self.context, self.host,
|
release_mock.assert_called_once_with(self.context, self.host,
|
||||||
self.node.id)
|
self.node.id)
|
||||||
self.assertFalse(node_get_mock.called)
|
self.assertFalse(node_get_mock.called)
|
||||||
|
|
||||||
def test_excl_nested_acquire(self, get_ports_mock, get_driver_mock,
|
def test_excl_nested_acquire(
|
||||||
reserve_mock, release_mock,
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
node_get_mock):
|
reserve_mock, release_mock, node_get_mock):
|
||||||
node2 = obj_utils.create_test_node(self.context,
|
node2 = obj_utils.create_test_node(self.context,
|
||||||
uuid=uuidutils.generate_uuid(),
|
uuid=uuidutils.generate_uuid(),
|
||||||
driver='fake')
|
driver='fake')
|
||||||
|
|
||||||
reserve_mock.return_value = self.node
|
reserve_mock.return_value = self.node
|
||||||
get_ports_mock.return_value = mock.sentinel.ports1
|
get_ports_mock.return_value = mock.sentinel.ports1
|
||||||
|
get_portgroups_mock.return_value = mock.sentinel.portgroups1
|
||||||
get_driver_mock.return_value = mock.sentinel.driver1
|
get_driver_mock.return_value = mock.sentinel.driver1
|
||||||
|
|
||||||
with task_manager.TaskManager(self.context, 'node-id1') as task:
|
with task_manager.TaskManager(self.context, 'node-id1') as task:
|
||||||
reserve_mock.return_value = node2
|
reserve_mock.return_value = node2
|
||||||
get_ports_mock.return_value = mock.sentinel.ports2
|
get_ports_mock.return_value = mock.sentinel.ports2
|
||||||
|
get_portgroups_mock.return_value = mock.sentinel.portgroups2
|
||||||
get_driver_mock.return_value = mock.sentinel.driver2
|
get_driver_mock.return_value = mock.sentinel.driver2
|
||||||
with task_manager.TaskManager(self.context, 'node-id2') as task2:
|
with task_manager.TaskManager(self.context, 'node-id2') as task2:
|
||||||
self.assertEqual(self.context, task.context)
|
self.assertEqual(self.context, task.context)
|
||||||
self.assertEqual(self.node, task.node)
|
self.assertEqual(self.node, task.node)
|
||||||
self.assertEqual(mock.sentinel.ports1, task.ports)
|
self.assertEqual(mock.sentinel.ports1, task.ports)
|
||||||
|
self.assertEqual(mock.sentinel.portgroups1, task.portgroups)
|
||||||
self.assertEqual(mock.sentinel.driver1, task.driver)
|
self.assertEqual(mock.sentinel.driver1, task.driver)
|
||||||
self.assertFalse(task.shared)
|
self.assertFalse(task.shared)
|
||||||
self.assertEqual(self.context, task2.context)
|
self.assertEqual(self.context, task2.context)
|
||||||
self.assertEqual(node2, task2.node)
|
self.assertEqual(node2, task2.node)
|
||||||
self.assertEqual(mock.sentinel.ports2, task2.ports)
|
self.assertEqual(mock.sentinel.ports2, task2.ports)
|
||||||
|
self.assertEqual(mock.sentinel.portgroups2, task2.portgroups)
|
||||||
self.assertEqual(mock.sentinel.driver2, task2.driver)
|
self.assertEqual(mock.sentinel.driver2, task2.driver)
|
||||||
self.assertFalse(task2.shared)
|
self.assertFalse(task2.shared)
|
||||||
|
|
||||||
|
@ -127,9 +137,9 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
release_mock.call_args_list)
|
release_mock.call_args_list)
|
||||||
self.assertFalse(node_get_mock.called)
|
self.assertFalse(node_get_mock.called)
|
||||||
|
|
||||||
def test_excl_lock_exception_then_lock(self, get_ports_mock,
|
def test_excl_lock_exception_then_lock(
|
||||||
get_driver_mock, reserve_mock,
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
release_mock, node_get_mock):
|
reserve_mock, release_mock, node_get_mock):
|
||||||
retry_attempts = 3
|
retry_attempts = 3
|
||||||
self.config(node_locked_retry_attempts=retry_attempts,
|
self.config(node_locked_retry_attempts=retry_attempts,
|
||||||
group='conductor')
|
group='conductor')
|
||||||
|
@ -147,9 +157,9 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
reserve_mock.assert_has_calls(expected_calls)
|
reserve_mock.assert_has_calls(expected_calls)
|
||||||
self.assertEqual(2, reserve_mock.call_count)
|
self.assertEqual(2, reserve_mock.call_count)
|
||||||
|
|
||||||
def test_excl_lock_reserve_exception(self, get_ports_mock,
|
def test_excl_lock_reserve_exception(
|
||||||
get_driver_mock, reserve_mock,
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
release_mock, node_get_mock):
|
reserve_mock, release_mock, node_get_mock):
|
||||||
retry_attempts = 3
|
retry_attempts = 3
|
||||||
self.config(node_locked_retry_attempts=retry_attempts,
|
self.config(node_locked_retry_attempts=retry_attempts,
|
||||||
group='conductor')
|
group='conductor')
|
||||||
|
@ -165,13 +175,14 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
'fake-node-id')
|
'fake-node-id')
|
||||||
self.assertEqual(retry_attempts, reserve_mock.call_count)
|
self.assertEqual(retry_attempts, reserve_mock.call_count)
|
||||||
self.assertFalse(get_ports_mock.called)
|
self.assertFalse(get_ports_mock.called)
|
||||||
|
self.assertFalse(get_portgroups_mock.called)
|
||||||
self.assertFalse(get_driver_mock.called)
|
self.assertFalse(get_driver_mock.called)
|
||||||
self.assertFalse(release_mock.called)
|
self.assertFalse(release_mock.called)
|
||||||
self.assertFalse(node_get_mock.called)
|
self.assertFalse(node_get_mock.called)
|
||||||
|
|
||||||
def test_excl_lock_get_ports_exception(self, get_ports_mock,
|
def test_excl_lock_get_ports_exception(
|
||||||
get_driver_mock, reserve_mock,
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
release_mock, node_get_mock):
|
reserve_mock, release_mock, node_get_mock):
|
||||||
reserve_mock.return_value = self.node
|
reserve_mock.return_value = self.node
|
||||||
get_ports_mock.side_effect = exception.IronicException('foo')
|
get_ports_mock.side_effect = exception.IronicException('foo')
|
||||||
|
|
||||||
|
@ -188,9 +199,28 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
self.node.id)
|
self.node.id)
|
||||||
self.assertFalse(node_get_mock.called)
|
self.assertFalse(node_get_mock.called)
|
||||||
|
|
||||||
def test_excl_lock_get_driver_exception(self, get_ports_mock,
|
def test_excl_lock_get_portgroups_exception(
|
||||||
get_driver_mock, reserve_mock,
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
release_mock, node_get_mock):
|
reserve_mock, release_mock, node_get_mock):
|
||||||
|
reserve_mock.return_value = self.node
|
||||||
|
get_portgroups_mock.side_effect = exception.IronicException('foo')
|
||||||
|
|
||||||
|
self.assertRaises(exception.IronicException,
|
||||||
|
task_manager.TaskManager,
|
||||||
|
self.context,
|
||||||
|
'fake-node-id')
|
||||||
|
|
||||||
|
reserve_mock.assert_called_once_with(self.context, self.host,
|
||||||
|
'fake-node-id')
|
||||||
|
get_portgroups_mock.assert_called_once_with(self.context, self.node.id)
|
||||||
|
self.assertFalse(get_driver_mock.called)
|
||||||
|
release_mock.assert_called_once_with(self.context, self.host,
|
||||||
|
self.node.id)
|
||||||
|
self.assertFalse(node_get_mock.called)
|
||||||
|
|
||||||
|
def test_excl_lock_get_driver_exception(
|
||||||
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
|
reserve_mock, release_mock, node_get_mock):
|
||||||
reserve_mock.return_value = self.node
|
reserve_mock.return_value = self.node
|
||||||
get_driver_mock.side_effect = (
|
get_driver_mock.side_effect = (
|
||||||
exception.DriverNotFound(driver_name='foo'))
|
exception.DriverNotFound(driver_name='foo'))
|
||||||
|
@ -203,19 +233,22 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
reserve_mock.assert_called_once_with(self.context, self.host,
|
reserve_mock.assert_called_once_with(self.context, self.host,
|
||||||
'fake-node-id')
|
'fake-node-id')
|
||||||
get_ports_mock.assert_called_once_with(self.context, self.node.id)
|
get_ports_mock.assert_called_once_with(self.context, self.node.id)
|
||||||
|
get_portgroups_mock.assert_called_once_with(self.context, self.node.id)
|
||||||
get_driver_mock.assert_called_once_with(self.node.driver)
|
get_driver_mock.assert_called_once_with(self.node.driver)
|
||||||
release_mock.assert_called_once_with(self.context, self.host,
|
release_mock.assert_called_once_with(self.context, self.host,
|
||||||
self.node.id)
|
self.node.id)
|
||||||
self.assertFalse(node_get_mock.called)
|
self.assertFalse(node_get_mock.called)
|
||||||
|
|
||||||
def test_shared_lock(self, get_ports_mock, get_driver_mock,
|
def test_shared_lock(
|
||||||
reserve_mock, release_mock, node_get_mock):
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
|
reserve_mock, release_mock, node_get_mock):
|
||||||
node_get_mock.return_value = self.node
|
node_get_mock.return_value = self.node
|
||||||
with task_manager.TaskManager(self.context, 'fake-node-id',
|
with task_manager.TaskManager(self.context, 'fake-node-id',
|
||||||
shared=True) as task:
|
shared=True) as task:
|
||||||
self.assertEqual(self.context, task.context)
|
self.assertEqual(self.context, task.context)
|
||||||
self.assertEqual(self.node, task.node)
|
self.assertEqual(self.node, task.node)
|
||||||
self.assertEqual(get_ports_mock.return_value, task.ports)
|
self.assertEqual(get_ports_mock.return_value, task.ports)
|
||||||
|
self.assertEqual(get_portgroups_mock.return_value, task.portgroups)
|
||||||
self.assertEqual(get_driver_mock.return_value, task.driver)
|
self.assertEqual(get_driver_mock.return_value, task.driver)
|
||||||
self.assertTrue(task.shared)
|
self.assertTrue(task.shared)
|
||||||
|
|
||||||
|
@ -223,11 +256,12 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
self.assertFalse(release_mock.called)
|
self.assertFalse(release_mock.called)
|
||||||
node_get_mock.assert_called_once_with(self.context, 'fake-node-id')
|
node_get_mock.assert_called_once_with(self.context, 'fake-node-id')
|
||||||
get_ports_mock.assert_called_once_with(self.context, self.node.id)
|
get_ports_mock.assert_called_once_with(self.context, self.node.id)
|
||||||
|
get_portgroups_mock.assert_called_once_with(self.context, self.node.id)
|
||||||
get_driver_mock.assert_called_once_with(self.node.driver)
|
get_driver_mock.assert_called_once_with(self.node.driver)
|
||||||
|
|
||||||
def test_shared_lock_with_driver(self, get_ports_mock, get_driver_mock,
|
def test_shared_lock_with_driver(
|
||||||
reserve_mock, release_mock,
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
node_get_mock):
|
reserve_mock, release_mock, node_get_mock):
|
||||||
node_get_mock.return_value = self.node
|
node_get_mock.return_value = self.node
|
||||||
with task_manager.TaskManager(self.context,
|
with task_manager.TaskManager(self.context,
|
||||||
'fake-node-id',
|
'fake-node-id',
|
||||||
|
@ -236,6 +270,7 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
self.assertEqual(self.context, task.context)
|
self.assertEqual(self.context, task.context)
|
||||||
self.assertEqual(self.node, task.node)
|
self.assertEqual(self.node, task.node)
|
||||||
self.assertEqual(get_ports_mock.return_value, task.ports)
|
self.assertEqual(get_ports_mock.return_value, task.ports)
|
||||||
|
self.assertEqual(get_portgroups_mock.return_value, task.portgroups)
|
||||||
self.assertEqual(get_driver_mock.return_value, task.driver)
|
self.assertEqual(get_driver_mock.return_value, task.driver)
|
||||||
self.assertTrue(task.shared)
|
self.assertTrue(task.shared)
|
||||||
|
|
||||||
|
@ -243,11 +278,12 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
self.assertFalse(release_mock.called)
|
self.assertFalse(release_mock.called)
|
||||||
node_get_mock.assert_called_once_with(self.context, 'fake-node-id')
|
node_get_mock.assert_called_once_with(self.context, 'fake-node-id')
|
||||||
get_ports_mock.assert_called_once_with(self.context, self.node.id)
|
get_ports_mock.assert_called_once_with(self.context, self.node.id)
|
||||||
|
get_portgroups_mock.assert_called_once_with(self.context, self.node.id)
|
||||||
get_driver_mock.assert_called_once_with('fake-driver')
|
get_driver_mock.assert_called_once_with('fake-driver')
|
||||||
|
|
||||||
def test_shared_lock_node_get_exception(self, get_ports_mock,
|
def test_shared_lock_node_get_exception(
|
||||||
get_driver_mock, reserve_mock,
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
release_mock, node_get_mock):
|
reserve_mock, release_mock, node_get_mock):
|
||||||
node_get_mock.side_effect = exception.NodeNotFound(node='foo')
|
node_get_mock.side_effect = exception.NodeNotFound(node='foo')
|
||||||
|
|
||||||
self.assertRaises(exception.NodeNotFound,
|
self.assertRaises(exception.NodeNotFound,
|
||||||
|
@ -260,11 +296,12 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
self.assertFalse(release_mock.called)
|
self.assertFalse(release_mock.called)
|
||||||
node_get_mock.assert_called_once_with(self.context, 'fake-node-id')
|
node_get_mock.assert_called_once_with(self.context, 'fake-node-id')
|
||||||
self.assertFalse(get_ports_mock.called)
|
self.assertFalse(get_ports_mock.called)
|
||||||
|
self.assertFalse(get_portgroups_mock.called)
|
||||||
self.assertFalse(get_driver_mock.called)
|
self.assertFalse(get_driver_mock.called)
|
||||||
|
|
||||||
def test_shared_lock_get_ports_exception(self, get_ports_mock,
|
def test_shared_lock_get_ports_exception(
|
||||||
get_driver_mock, reserve_mock,
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
release_mock, node_get_mock):
|
reserve_mock, release_mock, node_get_mock):
|
||||||
node_get_mock.return_value = self.node
|
node_get_mock.return_value = self.node
|
||||||
get_ports_mock.side_effect = exception.IronicException('foo')
|
get_ports_mock.side_effect = exception.IronicException('foo')
|
||||||
|
|
||||||
|
@ -280,9 +317,27 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
get_ports_mock.assert_called_once_with(self.context, self.node.id)
|
get_ports_mock.assert_called_once_with(self.context, self.node.id)
|
||||||
self.assertFalse(get_driver_mock.called)
|
self.assertFalse(get_driver_mock.called)
|
||||||
|
|
||||||
def test_shared_lock_get_driver_exception(self, get_ports_mock,
|
def test_shared_lock_get_portgroups_exception(
|
||||||
get_driver_mock, reserve_mock,
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
release_mock, node_get_mock):
|
reserve_mock, release_mock, node_get_mock):
|
||||||
|
node_get_mock.return_value = self.node
|
||||||
|
get_portgroups_mock.side_effect = exception.IronicException('foo')
|
||||||
|
|
||||||
|
self.assertRaises(exception.IronicException,
|
||||||
|
task_manager.TaskManager,
|
||||||
|
self.context,
|
||||||
|
'fake-node-id',
|
||||||
|
shared=True)
|
||||||
|
|
||||||
|
self.assertFalse(reserve_mock.called)
|
||||||
|
self.assertFalse(release_mock.called)
|
||||||
|
node_get_mock.assert_called_once_with(self.context, 'fake-node-id')
|
||||||
|
get_portgroups_mock.assert_called_once_with(self.context, self.node.id)
|
||||||
|
self.assertFalse(get_driver_mock.called)
|
||||||
|
|
||||||
|
def test_shared_lock_get_driver_exception(
|
||||||
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
|
reserve_mock, release_mock, node_get_mock):
|
||||||
node_get_mock.return_value = self.node
|
node_get_mock.return_value = self.node
|
||||||
get_driver_mock.side_effect = (
|
get_driver_mock.side_effect = (
|
||||||
exception.DriverNotFound(driver_name='foo'))
|
exception.DriverNotFound(driver_name='foo'))
|
||||||
|
@ -297,10 +352,12 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
self.assertFalse(release_mock.called)
|
self.assertFalse(release_mock.called)
|
||||||
node_get_mock.assert_called_once_with(self.context, 'fake-node-id')
|
node_get_mock.assert_called_once_with(self.context, 'fake-node-id')
|
||||||
get_ports_mock.assert_called_once_with(self.context, self.node.id)
|
get_ports_mock.assert_called_once_with(self.context, self.node.id)
|
||||||
|
get_portgroups_mock.assert_called_once_with(self.context, self.node.id)
|
||||||
get_driver_mock.assert_called_once_with(self.node.driver)
|
get_driver_mock.assert_called_once_with(self.node.driver)
|
||||||
|
|
||||||
def test_upgrade_lock(self, get_ports_mock, get_driver_mock,
|
def test_upgrade_lock(
|
||||||
reserve_mock, release_mock, node_get_mock):
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
|
reserve_mock, release_mock, node_get_mock):
|
||||||
node_get_mock.return_value = self.node
|
node_get_mock.return_value = self.node
|
||||||
reserve_mock.return_value = self.node
|
reserve_mock.return_value = self.node
|
||||||
with task_manager.TaskManager(self.context, 'fake-node-id',
|
with task_manager.TaskManager(self.context, 'fake-node-id',
|
||||||
|
@ -308,6 +365,7 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
self.assertEqual(self.context, task.context)
|
self.assertEqual(self.context, task.context)
|
||||||
self.assertEqual(self.node, task.node)
|
self.assertEqual(self.node, task.node)
|
||||||
self.assertEqual(get_ports_mock.return_value, task.ports)
|
self.assertEqual(get_ports_mock.return_value, task.ports)
|
||||||
|
self.assertEqual(get_portgroups_mock.return_value, task.portgroups)
|
||||||
self.assertEqual(get_driver_mock.return_value, task.driver)
|
self.assertEqual(get_driver_mock.return_value, task.driver)
|
||||||
self.assertTrue(task.shared)
|
self.assertTrue(task.shared)
|
||||||
self.assertFalse(reserve_mock.called)
|
self.assertFalse(reserve_mock.called)
|
||||||
|
@ -325,10 +383,12 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
self.node.id)
|
self.node.id)
|
||||||
node_get_mock.assert_called_once_with(self.context, 'fake-node-id')
|
node_get_mock.assert_called_once_with(self.context, 'fake-node-id')
|
||||||
get_ports_mock.assert_called_once_with(self.context, self.node.id)
|
get_ports_mock.assert_called_once_with(self.context, self.node.id)
|
||||||
|
get_portgroups_mock.assert_called_once_with(self.context, self.node.id)
|
||||||
get_driver_mock.assert_called_once_with(self.node.driver)
|
get_driver_mock.assert_called_once_with(self.node.driver)
|
||||||
|
|
||||||
def test_spawn_after(self, get_ports_mock, get_driver_mock,
|
def test_spawn_after(
|
||||||
reserve_mock, release_mock, node_get_mock):
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
|
reserve_mock, release_mock, node_get_mock):
|
||||||
thread_mock = mock.Mock(spec_set=['link', 'cancel'])
|
thread_mock = mock.Mock(spec_set=['link', 'cancel'])
|
||||||
spawn_mock = mock.Mock(return_value=thread_mock)
|
spawn_mock = mock.Mock(return_value=thread_mock)
|
||||||
task_release_mock = mock.Mock()
|
task_release_mock = mock.Mock()
|
||||||
|
@ -347,11 +407,9 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
# thread
|
# thread
|
||||||
self.assertFalse(task_release_mock.called)
|
self.assertFalse(task_release_mock.called)
|
||||||
|
|
||||||
def test_spawn_after_exception_while_yielded(self, get_ports_mock,
|
def test_spawn_after_exception_while_yielded(
|
||||||
get_driver_mock,
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
reserve_mock,
|
reserve_mock, release_mock, node_get_mock):
|
||||||
release_mock,
|
|
||||||
node_get_mock):
|
|
||||||
spawn_mock = mock.Mock()
|
spawn_mock = mock.Mock()
|
||||||
task_release_mock = mock.Mock()
|
task_release_mock = mock.Mock()
|
||||||
reserve_mock.return_value = self.node
|
reserve_mock.return_value = self.node
|
||||||
|
@ -366,9 +424,9 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
self.assertFalse(spawn_mock.called)
|
self.assertFalse(spawn_mock.called)
|
||||||
task_release_mock.assert_called_once_with()
|
task_release_mock.assert_called_once_with()
|
||||||
|
|
||||||
def test_spawn_after_spawn_fails(self, get_ports_mock, get_driver_mock,
|
def test_spawn_after_spawn_fails(
|
||||||
reserve_mock, release_mock,
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
node_get_mock):
|
reserve_mock, release_mock, node_get_mock):
|
||||||
spawn_mock = mock.Mock(side_effect=exception.IronicException('foo'))
|
spawn_mock = mock.Mock(side_effect=exception.IronicException('foo'))
|
||||||
task_release_mock = mock.Mock()
|
task_release_mock = mock.Mock()
|
||||||
reserve_mock.return_value = self.node
|
reserve_mock.return_value = self.node
|
||||||
|
@ -383,9 +441,9 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
spawn_mock.assert_called_once_with(1, 2, foo='bar', cat='meow')
|
spawn_mock.assert_called_once_with(1, 2, foo='bar', cat='meow')
|
||||||
task_release_mock.assert_called_once_with()
|
task_release_mock.assert_called_once_with()
|
||||||
|
|
||||||
def test_spawn_after_link_fails(self, get_ports_mock, get_driver_mock,
|
def test_spawn_after_link_fails(
|
||||||
reserve_mock, release_mock,
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
node_get_mock):
|
reserve_mock, release_mock, node_get_mock):
|
||||||
thread_mock = mock.Mock(spec_set=['link', 'cancel'])
|
thread_mock = mock.Mock(spec_set=['link', 'cancel'])
|
||||||
thread_mock.link.side_effect = exception.IronicException('foo')
|
thread_mock.link.side_effect = exception.IronicException('foo')
|
||||||
spawn_mock = mock.Mock(return_value=thread_mock)
|
spawn_mock = mock.Mock(return_value=thread_mock)
|
||||||
|
@ -405,9 +463,9 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
thread_mock.cancel.assert_called_once_with()
|
thread_mock.cancel.assert_called_once_with()
|
||||||
task_release_mock.assert_called_once_with()
|
task_release_mock.assert_called_once_with()
|
||||||
|
|
||||||
def test_spawn_after_on_error_hook(self, get_ports_mock, get_driver_mock,
|
def test_spawn_after_on_error_hook(
|
||||||
reserve_mock, release_mock,
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
node_get_mock):
|
reserve_mock, release_mock, node_get_mock):
|
||||||
expected_exception = exception.IronicException('foo')
|
expected_exception = exception.IronicException('foo')
|
||||||
spawn_mock = mock.Mock(side_effect=expected_exception)
|
spawn_mock = mock.Mock(side_effect=expected_exception)
|
||||||
task_release_mock = mock.Mock()
|
task_release_mock = mock.Mock()
|
||||||
|
@ -427,9 +485,9 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
on_error_handler.assert_called_once_with(expected_exception,
|
on_error_handler.assert_called_once_with(expected_exception,
|
||||||
'fake-argument')
|
'fake-argument')
|
||||||
|
|
||||||
def test_spawn_after_on_error_hook_exception(self, get_ports_mock,
|
def test_spawn_after_on_error_hook_exception(
|
||||||
get_driver_mock, reserve_mock,
|
self, get_portgroups_mock, get_ports_mock, get_driver_mock,
|
||||||
release_mock, node_get_mock):
|
reserve_mock, release_mock, node_get_mock):
|
||||||
expected_exception = exception.IronicException('foo')
|
expected_exception = exception.IronicException('foo')
|
||||||
spawn_mock = mock.Mock(side_effect=expected_exception)
|
spawn_mock = mock.Mock(side_effect=expected_exception)
|
||||||
task_release_mock = mock.Mock()
|
task_release_mock = mock.Mock()
|
||||||
|
@ -454,8 +512,8 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
||||||
|
|
||||||
@mock.patch.object(states.machine, 'copy')
|
@mock.patch.object(states.machine, 'copy')
|
||||||
def test_init_prepares_fsm(
|
def test_init_prepares_fsm(
|
||||||
self, copy_mock, get_ports_mock, get_driver_mock, reserve_mock,
|
self, copy_mock, get_portgroups_mock, get_ports_mock,
|
||||||
release_mock, node_get_mock):
|
get_driver_mock, reserve_mock, release_mock, node_get_mock):
|
||||||
m = mock.Mock(spec=fsm.FSM)
|
m = mock.Mock(spec=fsm.FSM)
|
||||||
reserve_mock.return_value = self.node
|
reserve_mock.return_value = self.node
|
||||||
copy_mock.return_value = m
|
copy_mock.return_value = m
|
||||||
|
@ -481,6 +539,7 @@ class TaskManagerStateModelTestCases(tests_base.TestCase):
|
||||||
t.release_resources = task_manager.TaskManager.release_resources
|
t.release_resources = task_manager.TaskManager.release_resources
|
||||||
t.driver = mock.Mock()
|
t.driver = mock.Mock()
|
||||||
t.ports = mock.Mock()
|
t.ports = mock.Mock()
|
||||||
|
t.portgroups = mock.Mock()
|
||||||
t.shared = True
|
t.shared = True
|
||||||
t._purpose = 'purpose'
|
t._purpose = 'purpose'
|
||||||
t._debug_timer = mock.Mock()
|
t._debug_timer = mock.Mock()
|
||||||
|
@ -489,6 +548,7 @@ class TaskManagerStateModelTestCases(tests_base.TestCase):
|
||||||
self.assertIsNone(t.node)
|
self.assertIsNone(t.node)
|
||||||
self.assertIsNone(t.driver)
|
self.assertIsNone(t.driver)
|
||||||
self.assertIsNone(t.ports)
|
self.assertIsNone(t.ports)
|
||||||
|
self.assertIsNone(t.portgroups)
|
||||||
self.assertIsNone(t.fsm)
|
self.assertIsNone(t.fsm)
|
||||||
|
|
||||||
def test_process_event_fsm_raises(self):
|
def test_process_event_fsm_raises(self):
|
||||||
|
|
Loading…
Reference in New Issue