Merge "Add dbapi and objects functions to get a node by associated MAC addresses"
This commit is contained in:
commit
5dbb749af9
@ -604,3 +604,12 @@ class Connection(object):
|
||||
:param tag: A tag string.
|
||||
:returns: True if the tag exists otherwise False.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_node_by_port_addresses(self, addresses):
|
||||
"""Find a node by any matching port address.
|
||||
|
||||
:param addresses: list of port addresses (e.g. MACs).
|
||||
:returns: Node object.
|
||||
:raises: NodeNotFound if none or several nodes are found.
|
||||
"""
|
||||
|
@ -28,7 +28,7 @@ from oslo_log import log
|
||||
from oslo_utils import strutils
|
||||
from oslo_utils import timeutils
|
||||
from oslo_utils import uuidutils
|
||||
from sqlalchemy.orm.exc import NoResultFound
|
||||
from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
|
||||
from sqlalchemy.orm import joinedload
|
||||
from sqlalchemy import sql
|
||||
|
||||
@ -843,3 +843,18 @@ class Connection(api.Connection):
|
||||
def node_tag_exists(self, node_id, tag):
|
||||
q = model_query(models.NodeTag).filter_by(node_id=node_id, tag=tag)
|
||||
return model_query(q.exists()).scalar()
|
||||
|
||||
def get_node_by_port_addresses(self, addresses):
|
||||
q = model_query(models.Node).distinct().join(models.Port)
|
||||
q = q.filter(models.Port.address.in_(addresses))
|
||||
|
||||
try:
|
||||
return q.one()
|
||||
except NoResultFound:
|
||||
raise exception.NodeNotFound(
|
||||
_('Node with port addresses %s was not found')
|
||||
% addresses)
|
||||
except MultipleResultsFound:
|
||||
raise exception.NodeNotFound(
|
||||
_('Multiple nodes with port addresses %s were found')
|
||||
% addresses)
|
||||
|
@ -45,7 +45,8 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat):
|
||||
# Version 1.13: Add touch_provisioning()
|
||||
# Version 1.14: Add _validate_property_values() and make create()
|
||||
# and save() validate the input of property values.
|
||||
VERSION = '1.14'
|
||||
# Version 1.15: Add get_by_port_addresses
|
||||
VERSION = '1.15'
|
||||
|
||||
dbapi = db_api.get_instance()
|
||||
|
||||
@ -364,3 +365,16 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat):
|
||||
def touch_provisioning(self, context=None):
|
||||
"""Touch the database record to mark the provisioning as alive."""
|
||||
self.dbapi.touch_node_provisioning(self.id)
|
||||
|
||||
@classmethod
|
||||
def get_by_port_addresses(cls, context, addresses):
|
||||
"""Get a node by associated port addresses.
|
||||
|
||||
:param context: Security context.
|
||||
:param addresses: A list of port addresses.
|
||||
:raises: NodeNotFound if the node is not found.
|
||||
:returns: a :class:`Node` object.
|
||||
"""
|
||||
db_node = cls.dbapi.get_node_by_port_addresses(addresses)
|
||||
node = Node._from_db_object(cls(context), db_node)
|
||||
return node
|
||||
|
@ -570,3 +570,57 @@ class DbNodeTestCase(base.DbTestCase):
|
||||
self.assertRaises(
|
||||
exception.NodeNotFound,
|
||||
self.dbapi.touch_node_provisioning, uuidutils.generate_uuid())
|
||||
|
||||
def test_get_node_by_port_addresses(self):
|
||||
wrong_node = utils.create_test_node(
|
||||
driver='driver-one',
|
||||
uuid=uuidutils.generate_uuid())
|
||||
node = utils.create_test_node(
|
||||
driver='driver-two',
|
||||
uuid=uuidutils.generate_uuid())
|
||||
addresses = []
|
||||
for i in (1, 2, 3):
|
||||
address = '52:54:00:cf:2d:4%s' % i
|
||||
utils.create_test_port(uuid=uuidutils.generate_uuid(),
|
||||
node_id=node.id, address=address)
|
||||
if i > 1:
|
||||
addresses.append(address)
|
||||
utils.create_test_port(uuid=uuidutils.generate_uuid(),
|
||||
node_id=wrong_node.id,
|
||||
address='aa:bb:cc:dd:ee:ff')
|
||||
|
||||
res = self.dbapi.get_node_by_port_addresses(addresses)
|
||||
self.assertEqual(node.uuid, res.uuid)
|
||||
|
||||
def test_get_node_by_port_addresses_not_found(self):
|
||||
node = utils.create_test_node(
|
||||
driver='driver',
|
||||
uuid=uuidutils.generate_uuid())
|
||||
utils.create_test_port(uuid=uuidutils.generate_uuid(),
|
||||
node_id=node.id,
|
||||
address='aa:bb:cc:dd:ee:ff')
|
||||
|
||||
self.assertRaisesRegexp(exception.NodeNotFound,
|
||||
'was not found',
|
||||
self.dbapi.get_node_by_port_addresses,
|
||||
['11:22:33:44:55:66'])
|
||||
|
||||
def test_get_node_by_port_addresses_multiple_found(self):
|
||||
node1 = utils.create_test_node(
|
||||
driver='driver',
|
||||
uuid=uuidutils.generate_uuid())
|
||||
node2 = utils.create_test_node(
|
||||
driver='driver',
|
||||
uuid=uuidutils.generate_uuid())
|
||||
addresses = ['52:54:00:cf:2d:4%s' % i for i in (1, 2)]
|
||||
utils.create_test_port(uuid=uuidutils.generate_uuid(),
|
||||
node_id=node1.id,
|
||||
address=addresses[0])
|
||||
utils.create_test_port(uuid=uuidutils.generate_uuid(),
|
||||
node_id=node2.id,
|
||||
address=addresses[1])
|
||||
|
||||
self.assertRaisesRegexp(exception.NodeNotFound,
|
||||
'Multiple nodes',
|
||||
self.dbapi.get_node_by_port_addresses,
|
||||
addresses)
|
||||
|
@ -54,6 +54,17 @@ class TestNodeObject(base.DbTestCase):
|
||||
self.assertRaises(exception.InvalidIdentity,
|
||||
objects.Node.get, self.context, 'not-a-uuid')
|
||||
|
||||
def test_get_by_port_addresses(self):
|
||||
with mock.patch.object(self.dbapi, 'get_node_by_port_addresses',
|
||||
autospec=True) as mock_get_node:
|
||||
mock_get_node.return_value = self.fake_node
|
||||
|
||||
node = objects.Node.get_by_port_addresses(self.context,
|
||||
['aa:bb:cc:dd:ee:ff'])
|
||||
|
||||
mock_get_node.assert_called_once_with(['aa:bb:cc:dd:ee:ff'])
|
||||
self.assertEqual(self.context, node._context)
|
||||
|
||||
def test_save(self):
|
||||
uuid = self.fake_node['uuid']
|
||||
with mock.patch.object(self.dbapi, 'get_node_by_uuid',
|
||||
|
@ -404,7 +404,7 @@ class TestObject(_LocalTest, _TestObject):
|
||||
# version bump. It is md5 hash of object fields and remotable methods.
|
||||
# The fingerprint values should only be changed if there is a version bump.
|
||||
expected_object_fingerprints = {
|
||||
'Node': '1.14-9ee8ab283b06398545880dfdedb49891',
|
||||
'Node': '1.15-9ee8ab283b06398545880dfdedb49891',
|
||||
'MyObj': '1.5-4f5efe8f0fcaf182bbe1c7fe3ba858db',
|
||||
'Chassis': '1.3-d656e039fd8ae9f34efc232ab3980905',
|
||||
'Port': '1.5-a224755c3da5bc5cf1a14a11c0d00f3f',
|
||||
|
Loading…
Reference in New Issue
Block a user