Merge "Supports filtering port by address"
This commit is contained in:
commit
bc0d9ccb29
@ -159,8 +159,9 @@ class PortsController(rest.RestController):
|
|||||||
def __init__(self, from_nodes=False):
|
def __init__(self, from_nodes=False):
|
||||||
self._from_nodes = from_nodes
|
self._from_nodes = from_nodes
|
||||||
|
|
||||||
def _get_ports_collection(self, node_uuid, marker, limit, sort_key,
|
def _get_ports_collection(self, node_uuid, address, marker, limit,
|
||||||
sort_dir, expand=False, resource_url=None):
|
sort_key, sort_dir, expand=False,
|
||||||
|
resource_url=None):
|
||||||
if self._from_nodes and not node_uuid:
|
if self._from_nodes and not node_uuid:
|
||||||
raise exception.InvalidParameterValue(_(
|
raise exception.InvalidParameterValue(_(
|
||||||
"Node id not specified."))
|
"Node id not specified."))
|
||||||
@ -178,6 +179,8 @@ class PortsController(rest.RestController):
|
|||||||
marker_obj,
|
marker_obj,
|
||||||
sort_key=sort_key,
|
sort_key=sort_key,
|
||||||
sort_dir=sort_dir)
|
sort_dir=sort_dir)
|
||||||
|
elif address:
|
||||||
|
ports = self._get_ports_by_address(address)
|
||||||
else:
|
else:
|
||||||
ports = pecan.request.dbapi.get_port_list(limit, marker_obj,
|
ports = pecan.request.dbapi.get_port_list(limit, marker_obj,
|
||||||
sort_key=sort_key,
|
sort_key=sort_key,
|
||||||
@ -189,28 +192,46 @@ class PortsController(rest.RestController):
|
|||||||
sort_key=sort_key,
|
sort_key=sort_key,
|
||||||
sort_dir=sort_dir)
|
sort_dir=sort_dir)
|
||||||
|
|
||||||
@wsme_pecan.wsexpose(PortCollection, types.uuid, types.uuid, int,
|
def _get_ports_by_address(self, address):
|
||||||
wtypes.text, wtypes.text)
|
"""Retrieve a port by its address.
|
||||||
def get_all(self, node_uuid=None, marker=None, limit=None,
|
|
||||||
|
:param address: MAC address of a port, to get the port which has
|
||||||
|
this MAC address.
|
||||||
|
:returns: a list with the port, or an empty list if no port is found.
|
||||||
|
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
port = pecan.request.dbapi.get_port(address)
|
||||||
|
return [port]
|
||||||
|
except exception.PortNotFound:
|
||||||
|
return []
|
||||||
|
|
||||||
|
@wsme_pecan.wsexpose(PortCollection, types.uuid, types.macaddress,
|
||||||
|
types.uuid, int, wtypes.text, wtypes.text)
|
||||||
|
def get_all(self, node_uuid=None, address=None, marker=None, limit=None,
|
||||||
sort_key='id', sort_dir='asc'):
|
sort_key='id', sort_dir='asc'):
|
||||||
"""Retrieve a list of ports.
|
"""Retrieve a list of ports.
|
||||||
|
|
||||||
:param node_uuid: UUID of a node, to get only ports for that node.
|
:param node_uuid: UUID of a node, to get only ports for that node.
|
||||||
|
:param address: MAC address of a port, to get the port which has
|
||||||
|
this MAC address.
|
||||||
:param marker: pagination marker for large data sets.
|
:param marker: pagination marker for large data sets.
|
||||||
:param limit: maximum number of resources to return in a single result.
|
:param limit: maximum number of resources to return in a single result.
|
||||||
:param sort_key: column to sort results by. Default: id.
|
:param sort_key: column to sort results by. Default: id.
|
||||||
:param sort_dir: direction to sort. "asc" or "desc". Default: asc.
|
:param sort_dir: direction to sort. "asc" or "desc". Default: asc.
|
||||||
"""
|
"""
|
||||||
return self._get_ports_collection(node_uuid, marker, limit,
|
return self._get_ports_collection(node_uuid, address, marker, limit,
|
||||||
sort_key, sort_dir)
|
sort_key, sort_dir)
|
||||||
|
|
||||||
@wsme_pecan.wsexpose(PortCollection, types.uuid, types.uuid, int,
|
@wsme_pecan.wsexpose(PortCollection, types.uuid, types.macaddress,
|
||||||
wtypes.text, wtypes.text)
|
types.uuid, int, wtypes.text, wtypes.text)
|
||||||
def detail(self, node_uuid=None, marker=None, limit=None,
|
def detail(self, node_uuid=None, address=None, marker=None, limit=None,
|
||||||
sort_key='id', sort_dir='asc'):
|
sort_key='id', sort_dir='asc'):
|
||||||
"""Retrieve a list of ports with detail.
|
"""Retrieve a list of ports with detail.
|
||||||
|
|
||||||
:param node_uuid: UUID of a node, to get only ports for that node.
|
:param node_uuid: UUID of a node, to get only ports for that node.
|
||||||
|
:param address: MAC address of a port, to get the port which has
|
||||||
|
this MAC address.
|
||||||
:param marker: pagination marker for large data sets.
|
:param marker: pagination marker for large data sets.
|
||||||
:param limit: maximum number of resources to return in a single result.
|
:param limit: maximum number of resources to return in a single result.
|
||||||
:param sort_key: column to sort results by. Default: id.
|
:param sort_key: column to sort results by. Default: id.
|
||||||
@ -223,8 +244,9 @@ class PortsController(rest.RestController):
|
|||||||
|
|
||||||
expand = True
|
expand = True
|
||||||
resource_url = '/'.join(['ports', 'detail'])
|
resource_url = '/'.join(['ports', 'detail'])
|
||||||
return self._get_ports_collection(node_uuid, marker, limit, sort_key,
|
return self._get_ports_collection(node_uuid, address, marker, limit,
|
||||||
sort_dir, expand, resource_url)
|
sort_key, sort_dir, expand,
|
||||||
|
resource_url)
|
||||||
|
|
||||||
@wsme_pecan.wsexpose(Port, types.uuid)
|
@wsme_pecan.wsexpose(Port, types.uuid)
|
||||||
def get_one(self, port_uuid):
|
def get_one(self, port_uuid):
|
||||||
|
@ -28,6 +28,11 @@ class MacAddressType(wtypes.UserType):
|
|||||||
|
|
||||||
basetype = wtypes.text
|
basetype = wtypes.text
|
||||||
name = 'macaddress'
|
name = 'macaddress'
|
||||||
|
# FIXME(lucasagomes): When used with wsexpose decorator WSME will try
|
||||||
|
# to get the name of the type by accessing it's __name__ attribute.
|
||||||
|
# Remove this __name__ attribute once it's fixed in WSME.
|
||||||
|
# https://bugs.launchpad.net/wsme/+bug/1265590
|
||||||
|
__name__ = name
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def validate(value):
|
def validate(value):
|
||||||
@ -35,6 +40,8 @@ class MacAddressType(wtypes.UserType):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def frombasetype(value):
|
def frombasetype(value):
|
||||||
|
if value is None:
|
||||||
|
return None
|
||||||
return MacAddressType.validate(value)
|
return MacAddressType.validate(value)
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import datetime
|
|||||||
import fixtures
|
import fixtures
|
||||||
import mock
|
import mock
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
|
from testtools.matchers import HasLength
|
||||||
|
|
||||||
from ironic.common import utils
|
from ironic.common import utils
|
||||||
from ironic.conductor import manager
|
from ironic.conductor import manager
|
||||||
@ -141,6 +142,36 @@ class TestListPorts(base.FunctionalTest):
|
|||||||
next_marker = data['ports'][-1]['uuid']
|
next_marker = data['ports'][-1]['uuid']
|
||||||
self.assertIn(next_marker, data['next'])
|
self.assertIn(next_marker, data['next'])
|
||||||
|
|
||||||
|
def test_port_by_address(self):
|
||||||
|
address_template = "aa:bb:cc:dd:ee:f%d"
|
||||||
|
for id_ in range(3):
|
||||||
|
pdict = dbutils.get_test_port(id=id_,
|
||||||
|
uuid=utils.generate_uuid(),
|
||||||
|
address=address_template % id_)
|
||||||
|
self.dbapi.create_port(pdict)
|
||||||
|
|
||||||
|
target_address = address_template % 1
|
||||||
|
data = self.get_json('/ports?address=%s' % target_address)
|
||||||
|
self.assertThat(data['ports'], HasLength(1))
|
||||||
|
self.assertEqual(target_address, data['ports'][0]['address'])
|
||||||
|
|
||||||
|
def test_port_by_address_non_existent_address(self):
|
||||||
|
pdict = dbutils.get_test_port()
|
||||||
|
self.dbapi.create_port(pdict)
|
||||||
|
# non-existent address
|
||||||
|
data = self.get_json('/ports?address=%s' % 'aa:bb:cc:dd:ee:ff')
|
||||||
|
self.assertThat(data['ports'], HasLength(0))
|
||||||
|
|
||||||
|
def test_port_by_address_invalid_address_format(self):
|
||||||
|
pdict = dbutils.get_test_port()
|
||||||
|
self.dbapi.create_port(pdict)
|
||||||
|
invalid_address = 'invalid-mac-format'
|
||||||
|
response = self.get_json('/ports?address=%s' % invalid_address,
|
||||||
|
expect_errors=True)
|
||||||
|
self.assertEqual(400, response.status_int)
|
||||||
|
self.assertEqual('application/json', response.content_type)
|
||||||
|
self.assertIn(invalid_address, response.json['error_message'])
|
||||||
|
|
||||||
|
|
||||||
class TestPatch(base.FunctionalTest):
|
class TestPatch(base.FunctionalTest):
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user