Add pagination support to {node, port, chassis}-list
the presence of a 'next' field is the indicator to continue pagination until there're no more values to be returned. On the CLI two new options were added to commands used to list resources: * --marker: Optional, the UUID of an item, eg the last item from a previous result set. Return the next result set. * --limit: The maximum number of results to return per request, if: 1) limit > 0, the maximum number of items to return. 2) limit == 0, return the entire list of items. 3) limit param is NOT specified (None), the number of items returned respect the maximum imposed by the Ironic API (see Ironic's api.max_limit option). Closes-Bug: #1314992 Change-Id: I77cc7a7df65c3d2a84144b12a001487ff6832045
This commit is contained in:
parent
d7218d83a2
commit
c3665d0916
ironicclient
@ -21,6 +21,8 @@ Base utilities to build API operation managers and objects on top of.
|
||||
|
||||
import copy
|
||||
|
||||
import six.moves.urllib.parse as urlparse
|
||||
|
||||
from ironicclient.openstack.common.apiclient import base
|
||||
|
||||
|
||||
@ -48,12 +50,7 @@ class Manager(object):
|
||||
if body:
|
||||
return self.resource_class(self, body)
|
||||
|
||||
def _list(self, url, response_key=None, obj_class=None, body=None):
|
||||
resp, body = self.api.json_request('GET', url)
|
||||
|
||||
if obj_class is None:
|
||||
obj_class = self.resource_class
|
||||
|
||||
def _format_body_data(self, body, response_key):
|
||||
if response_key:
|
||||
try:
|
||||
data = body[response_key]
|
||||
@ -61,9 +58,72 @@ class Manager(object):
|
||||
return []
|
||||
else:
|
||||
data = body
|
||||
|
||||
if not isinstance(data, list):
|
||||
data = [data]
|
||||
|
||||
return data
|
||||
|
||||
def _list_pagination(self, url, response_key=None, obj_class=None,
|
||||
limit=None):
|
||||
"""Retrieve a list of items.
|
||||
|
||||
The Ironic API is configured to return a maximum number of
|
||||
items per request, (see Ironic's api.max_limit option). This
|
||||
iterates over the 'next' link (pagination) in the responses,
|
||||
to get the number of items specified by 'limit'. If 'limit'
|
||||
is None this function will continue pagination until there are
|
||||
no more values to be returned.
|
||||
|
||||
:param url: a partial URL, e.g. '/nodes'
|
||||
:param response_key: the key to be looked up in response
|
||||
dictionary, e.g. 'nodes'
|
||||
:param obj_class: class for constructing the returned objects.
|
||||
:param limit: maximum number of items to return. If None returns
|
||||
everything.
|
||||
|
||||
"""
|
||||
if obj_class is None:
|
||||
obj_class = self.resource_class
|
||||
|
||||
if limit is not None:
|
||||
limit = int(limit)
|
||||
|
||||
object_list = []
|
||||
object_count = 0
|
||||
limit_reached = False
|
||||
while url:
|
||||
resp, body = self.api.json_request('GET', url)
|
||||
data = self._format_body_data(body, response_key)
|
||||
for obj in data:
|
||||
object_list.append(obj_class(self, obj, loaded=True))
|
||||
object_count += 1
|
||||
if limit and object_count >= limit:
|
||||
# break the for loop
|
||||
limit_reached = True
|
||||
break
|
||||
|
||||
# break the while loop and return
|
||||
if limit_reached:
|
||||
break
|
||||
|
||||
url = body.get('next')
|
||||
if url:
|
||||
# NOTE(lucasagomes): We need to edit the URL to remove
|
||||
# the scheme and netloc
|
||||
url_parts = list(urlparse.urlparse(url))
|
||||
url_parts[0] = url_parts[1] = ''
|
||||
url = urlparse.urlunparse(url_parts)
|
||||
|
||||
return object_list
|
||||
|
||||
def _list(self, url, response_key=None, obj_class=None, body=None):
|
||||
resp, body = self.api.json_request('GET', url)
|
||||
|
||||
if obj_class is None:
|
||||
obj_class = self.resource_class
|
||||
|
||||
data = self._format_body_data(body, response_key)
|
||||
return [obj_class(self, res, loaded=True) for res in data if res]
|
||||
|
||||
def _update(self, url, body, method='PATCH', response_key=None):
|
||||
|
@ -18,6 +18,7 @@
|
||||
import copy
|
||||
|
||||
import testtools
|
||||
from testtools.matchers import HasLength
|
||||
|
||||
from ironicclient.tests import utils
|
||||
import ironicclient.v1.chassis
|
||||
@ -27,6 +28,12 @@ CHASSIS = {'id': 42,
|
||||
'extra': {},
|
||||
'description': 'data-center-1-chassis'}
|
||||
|
||||
CHASSIS2 = {'id': 43,
|
||||
'uuid': 'eeeeeeee-dddd-cccc-bbbb-aaaaaaaaaaaa',
|
||||
'extra': {},
|
||||
'description': 'data-center-1-chassis'}
|
||||
|
||||
|
||||
NODE = {'id': 123,
|
||||
'uuid': '66666666-7777-8888-9999-000000000000',
|
||||
'chassis_id': 42,
|
||||
@ -79,6 +86,45 @@ fake_responses = {
|
||||
},
|
||||
}
|
||||
|
||||
fake_responses_pagination = {
|
||||
'/v1/chassis':
|
||||
{
|
||||
'GET': (
|
||||
{},
|
||||
{"chassis": [CHASSIS],
|
||||
"next": "http://127.0.0.1:6385/v1/chassis/?limit=1"}
|
||||
),
|
||||
},
|
||||
'/v1/chassis/?limit=1':
|
||||
{
|
||||
'GET': (
|
||||
{},
|
||||
{"chassis": [CHASSIS2]}
|
||||
),
|
||||
},
|
||||
'/v1/chassis/?marker=%s' % CHASSIS['uuid']:
|
||||
{
|
||||
'GET': (
|
||||
{},
|
||||
{"chassis": [CHASSIS2]}
|
||||
),
|
||||
},
|
||||
'/v1/chassis/%s/nodes?limit=1' % CHASSIS['uuid']:
|
||||
{
|
||||
'GET': (
|
||||
{},
|
||||
{"nodes": [NODE]},
|
||||
),
|
||||
},
|
||||
'/v1/chassis/%s/nodes?marker=%s' % (CHASSIS['uuid'], NODE['uuid']):
|
||||
{
|
||||
'GET': (
|
||||
{},
|
||||
{"nodes": [NODE]},
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class ChassisManagerTest(testtools.TestCase):
|
||||
|
||||
@ -95,6 +141,37 @@ class ChassisManagerTest(testtools.TestCase):
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertEqual(1, len(chassis))
|
||||
|
||||
def test_chassis_list_limit(self):
|
||||
self.api = utils.FakeAPI(fake_responses_pagination)
|
||||
self.mgr = ironicclient.v1.chassis.ChassisManager(self.api)
|
||||
chassis = self.mgr.list(limit=1)
|
||||
expect = [
|
||||
('GET', '/v1/chassis/?limit=1', {}, None),
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertThat(chassis, HasLength(1))
|
||||
|
||||
def test_chassis_list_marker(self):
|
||||
self.api = utils.FakeAPI(fake_responses_pagination)
|
||||
self.mgr = ironicclient.v1.chassis.ChassisManager(self.api)
|
||||
chassis = self.mgr.list(marker=CHASSIS['uuid'])
|
||||
expect = [
|
||||
('GET', '/v1/chassis/?marker=%s' % CHASSIS['uuid'], {}, None),
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertThat(chassis, HasLength(1))
|
||||
|
||||
def test_chassis_list_pagination_no_limit(self):
|
||||
self.api = utils.FakeAPI(fake_responses_pagination)
|
||||
self.mgr = ironicclient.v1.chassis.ChassisManager(self.api)
|
||||
chassis = self.mgr.list(limit=0)
|
||||
expect = [
|
||||
('GET', '/v1/chassis', {}, None),
|
||||
('GET', '/v1/chassis/?limit=1', {}, None)
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertThat(chassis, HasLength(2))
|
||||
|
||||
def test_chassis_show(self):
|
||||
chassis = self.mgr.get(CHASSIS['uuid'])
|
||||
expect = [
|
||||
@ -139,3 +216,28 @@ class ChassisManagerTest(testtools.TestCase):
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertEqual(1, len(nodes))
|
||||
self.assertEqual(NODE['uuid'], nodes[0].uuid)
|
||||
|
||||
def test_chassis_node_list_limit(self):
|
||||
self.api = utils.FakeAPI(fake_responses_pagination)
|
||||
self.mgr = ironicclient.v1.chassis.ChassisManager(self.api)
|
||||
nodes = self.mgr.list_nodes(CHASSIS['uuid'], limit=1)
|
||||
expect = [
|
||||
('GET',
|
||||
'/v1/chassis/%s/nodes?limit=1' % CHASSIS['uuid'], {}, None),
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertThat(nodes, HasLength(1))
|
||||
self.assertEqual(NODE['uuid'], nodes[0].uuid)
|
||||
|
||||
def test_chassis_node_list_marker(self):
|
||||
self.api = utils.FakeAPI(fake_responses_pagination)
|
||||
self.mgr = ironicclient.v1.chassis.ChassisManager(self.api)
|
||||
nodes = self.mgr.list_nodes(CHASSIS['uuid'], marker=NODE['uuid'])
|
||||
expect = [
|
||||
('GET',
|
||||
'/v1/chassis/%s/nodes?marker=%s' % (CHASSIS['uuid'],
|
||||
NODE['uuid']), {}, None),
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertThat(nodes, HasLength(1))
|
||||
self.assertEqual(NODE['uuid'], nodes[0].uuid)
|
||||
|
@ -17,10 +17,10 @@
|
||||
import copy
|
||||
|
||||
import testtools
|
||||
from testtools.matchers import HasLength
|
||||
|
||||
from ironicclient.tests import utils
|
||||
import ironicclient.v1.node
|
||||
from testtools.matchers import HasLength
|
||||
|
||||
NODE1 = {'id': 123,
|
||||
'uuid': '66666666-7777-8888-9999-000000000000',
|
||||
@ -77,7 +77,7 @@ fake_responses = {
|
||||
{
|
||||
'GET': (
|
||||
{},
|
||||
{"nodes": [NODE1, NODE2]},
|
||||
{"nodes": [NODE1, NODE2]}
|
||||
),
|
||||
'POST': (
|
||||
{},
|
||||
@ -203,6 +203,45 @@ fake_responses = {
|
||||
},
|
||||
}
|
||||
|
||||
fake_responses_pagination = {
|
||||
'/v1/nodes':
|
||||
{
|
||||
'GET': (
|
||||
{},
|
||||
{"nodes": [NODE1],
|
||||
"next": "http://127.0.0.1:6385/v1/nodes/?limit=1"}
|
||||
),
|
||||
},
|
||||
'/v1/nodes/?limit=1':
|
||||
{
|
||||
'GET': (
|
||||
{},
|
||||
{"nodes": [NODE2]}
|
||||
),
|
||||
},
|
||||
'/v1/nodes/?marker=%s' % NODE1['uuid']:
|
||||
{
|
||||
'GET': (
|
||||
{},
|
||||
{"nodes": [NODE2]}
|
||||
),
|
||||
},
|
||||
'/v1/nodes/%s/ports?limit=1' % NODE1['uuid']:
|
||||
{
|
||||
'GET': (
|
||||
{},
|
||||
{"ports": [PORT]},
|
||||
),
|
||||
},
|
||||
'/v1/nodes/%s/ports?marker=%s' % (NODE1['uuid'], PORT['uuid']):
|
||||
{
|
||||
'GET': (
|
||||
{},
|
||||
{"ports": [PORT]},
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class NodeManagerTest(testtools.TestCase):
|
||||
|
||||
@ -219,6 +258,37 @@ class NodeManagerTest(testtools.TestCase):
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertEqual(2, len(nodes))
|
||||
|
||||
def test_node_list_limit(self):
|
||||
self.api = utils.FakeAPI(fake_responses_pagination)
|
||||
self.mgr = ironicclient.v1.node.NodeManager(self.api)
|
||||
nodes = self.mgr.list(limit=1)
|
||||
expect = [
|
||||
('GET', '/v1/nodes/?limit=1', {}, None)
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertThat(nodes, HasLength(1))
|
||||
|
||||
def test_node_list_marker(self):
|
||||
self.api = utils.FakeAPI(fake_responses_pagination)
|
||||
self.mgr = ironicclient.v1.node.NodeManager(self.api)
|
||||
nodes = self.mgr.list(marker=NODE1['uuid'])
|
||||
expect = [
|
||||
('GET', '/v1/nodes/?marker=%s' % NODE1['uuid'], {}, None)
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertThat(nodes, HasLength(1))
|
||||
|
||||
def test_node_list_pagination_no_limit(self):
|
||||
self.api = utils.FakeAPI(fake_responses_pagination)
|
||||
self.mgr = ironicclient.v1.node.NodeManager(self.api)
|
||||
nodes = self.mgr.list(limit=0)
|
||||
expect = [
|
||||
('GET', '/v1/nodes', {}, None),
|
||||
('GET', '/v1/nodes/?limit=1', {}, None)
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertEqual(2, len(nodes))
|
||||
|
||||
def test_node_list_associated(self):
|
||||
nodes = self.mgr.list(associated=True)
|
||||
expect = [
|
||||
@ -319,6 +389,29 @@ class NodeManagerTest(testtools.TestCase):
|
||||
self.assertEqual(PORT['uuid'], ports[0].uuid)
|
||||
self.assertEqual(PORT['address'], ports[0].address)
|
||||
|
||||
def test_node_port_list_limit(self):
|
||||
self.api = utils.FakeAPI(fake_responses_pagination)
|
||||
self.mgr = ironicclient.v1.node.NodeManager(self.api)
|
||||
ports = self.mgr.list_ports(NODE1['uuid'], limit=1)
|
||||
expect = [
|
||||
('GET', '/v1/nodes/%s/ports?limit=1' % NODE1['uuid'], {}, None),
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertThat(ports, HasLength(1))
|
||||
self.assertEqual(PORT['uuid'], ports[0].uuid)
|
||||
self.assertEqual(PORT['address'], ports[0].address)
|
||||
|
||||
def test_node_port_list_marker(self):
|
||||
self.api = utils.FakeAPI(fake_responses_pagination)
|
||||
self.mgr = ironicclient.v1.node.NodeManager(self.api)
|
||||
ports = self.mgr.list_ports(NODE1['uuid'], marker=PORT['uuid'])
|
||||
expect = [
|
||||
('GET', '/v1/nodes/%s/ports?marker=%s' % (NODE1['uuid'],
|
||||
PORT['uuid']), {}, None),
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertThat(ports, HasLength(1))
|
||||
|
||||
def test_node_set_power_state(self):
|
||||
power_state = self.mgr.set_power_state(NODE1['uuid'], "on")
|
||||
body = {'target': 'power on'}
|
||||
|
@ -18,6 +18,7 @@
|
||||
import copy
|
||||
|
||||
import testtools
|
||||
from testtools.matchers import HasLength
|
||||
|
||||
from ironicclient.tests import utils
|
||||
import ironicclient.v1.port
|
||||
@ -28,6 +29,12 @@ PORT = {'id': 987,
|
||||
'address': 'AA:BB:CC:DD:EE:FF',
|
||||
'extra': {}}
|
||||
|
||||
PORT2 = {'id': 988,
|
||||
'uuid': '55555555-4444-3333-2222-111111111111',
|
||||
'node_uuid': '55555555-4444-3333-2222-111111111111',
|
||||
'address': 'AA:AA:AA:BB:BB:BB',
|
||||
'extra': {}}
|
||||
|
||||
CREATE_PORT = copy.deepcopy(PORT)
|
||||
del CREATE_PORT['id']
|
||||
del CREATE_PORT['uuid']
|
||||
@ -65,6 +72,31 @@ fake_responses = {
|
||||
},
|
||||
}
|
||||
|
||||
fake_responses_pagination = {
|
||||
'/v1/ports':
|
||||
{
|
||||
'GET': (
|
||||
{},
|
||||
{"ports": [PORT],
|
||||
"next": "http://127.0.0.1:6385/v1/ports/?limit=1"}
|
||||
),
|
||||
},
|
||||
'/v1/ports/?limit=1':
|
||||
{
|
||||
'GET': (
|
||||
{},
|
||||
{"ports": [PORT2]}
|
||||
),
|
||||
},
|
||||
'/v1/ports/?marker=%s' % PORT['uuid']:
|
||||
{
|
||||
'GET': (
|
||||
{},
|
||||
{"ports": [PORT2]}
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class PortManagerTest(testtools.TestCase):
|
||||
|
||||
@ -81,6 +113,37 @@ class PortManagerTest(testtools.TestCase):
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertEqual(1, len(ports))
|
||||
|
||||
def test_ports_list_limit(self):
|
||||
self.api = utils.FakeAPI(fake_responses_pagination)
|
||||
self.mgr = ironicclient.v1.port.PortManager(self.api)
|
||||
ports = self.mgr.list(limit=1)
|
||||
expect = [
|
||||
('GET', '/v1/ports/?limit=1', {}, None),
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertThat(ports, HasLength(1))
|
||||
|
||||
def test_ports_list_marker(self):
|
||||
self.api = utils.FakeAPI(fake_responses_pagination)
|
||||
self.mgr = ironicclient.v1.port.PortManager(self.api)
|
||||
ports = self.mgr.list(marker=PORT['uuid'])
|
||||
expect = [
|
||||
('GET', '/v1/ports/?marker=%s' % PORT['uuid'], {}, None),
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertThat(ports, HasLength(1))
|
||||
|
||||
def test_ports_list_pagination_no_limit(self):
|
||||
self.api = utils.FakeAPI(fake_responses_pagination)
|
||||
self.mgr = ironicclient.v1.port.PortManager(self.api)
|
||||
ports = self.mgr.list(limit=0)
|
||||
expect = [
|
||||
('GET', '/v1/ports', {}, None),
|
||||
('GET', '/v1/ports/?limit=1', {}, None)
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertThat(ports, HasLength(2))
|
||||
|
||||
def test_ports_show(self):
|
||||
port = self.mgr.get(PORT['uuid'])
|
||||
expect = [
|
||||
|
@ -33,12 +33,80 @@ class ChassisManager(base.Manager):
|
||||
def _path(id=None):
|
||||
return '/v1/chassis/%s' % id if id else '/v1/chassis'
|
||||
|
||||
def list(self):
|
||||
return self._list(self._path(), "chassis")
|
||||
def list(self, marker=None, limit=None):
|
||||
"""Retrieve a list of chassis.
|
||||
|
||||
:param marker: Optional, the UUID of a chassis, eg the last
|
||||
chassis from a previous result set. Return
|
||||
the next result set.
|
||||
:param limit: The maximum number of results to return per
|
||||
request, if:
|
||||
|
||||
1) limit > 0, the maximum number of chassis to return.
|
||||
2) limit == 0, return the entire list of chassis.
|
||||
3) limit param is NOT specified (None), the number of items
|
||||
returned respect the maximum imposed by the Ironic API
|
||||
(see Ironic's api.max_limit option).
|
||||
|
||||
:returns: A list of chassis.
|
||||
|
||||
"""
|
||||
if limit is not None:
|
||||
limit = int(limit)
|
||||
|
||||
filters = []
|
||||
if isinstance(limit, int) and limit > 0:
|
||||
filters.append('limit=%s' % limit)
|
||||
if marker is not None:
|
||||
filters.append('marker=%s' % marker)
|
||||
|
||||
path = None
|
||||
if filters:
|
||||
path = '?' + '&'.join(filters)
|
||||
|
||||
if limit is None:
|
||||
return self._list(self._path(path), "chassis")
|
||||
else:
|
||||
return self._list_pagination(self._path(path), "chassis",
|
||||
limit=limit)
|
||||
|
||||
def list_nodes(self, chassis_id, marker=None, limit=None):
|
||||
"""List all the nodes for a given chassis.
|
||||
|
||||
:param chassis_id: The UUID of the chassis.
|
||||
:param marker: Optional, the UUID of a node, eg the last
|
||||
node from a previous result set. Return
|
||||
the next result set.
|
||||
:param limit: The maximum number of results to return per
|
||||
request, if:
|
||||
|
||||
1) limit > 0, the maximum number of nodes to return.
|
||||
2) limit == 0, return the entire list of nodes.
|
||||
3) limit param is NOT specified (None), the number of items
|
||||
returned respect the maximum imposed by the Ironic API
|
||||
(see Ironic's api.max_limit option).
|
||||
|
||||
:returns: A list of nodes.
|
||||
|
||||
"""
|
||||
if limit is not None:
|
||||
limit = int(limit)
|
||||
|
||||
filters = []
|
||||
if isinstance(limit, int) and limit > 0:
|
||||
filters.append('limit=%s' % limit)
|
||||
if marker is not None:
|
||||
filters.append('marker=%s' % marker)
|
||||
|
||||
def list_nodes(self, chassis_id):
|
||||
path = "%s/nodes" % chassis_id
|
||||
return self._list(self._path(path), "nodes")
|
||||
if filters:
|
||||
path += '?' + '&'.join(filters)
|
||||
|
||||
if limit is None:
|
||||
return self._list(self._path(path), "nodes")
|
||||
else:
|
||||
return self._list_pagination(self._path(path), "nodes",
|
||||
limit=limit)
|
||||
|
||||
def get(self, chassis_id):
|
||||
try:
|
||||
|
@ -32,12 +32,31 @@ def do_chassis_show(cc, args):
|
||||
_print_chassis_show(chassis)
|
||||
|
||||
|
||||
@cliutils.arg(
|
||||
'--limit',
|
||||
metavar='<limit>',
|
||||
type=int,
|
||||
help='Maximum number of chassis to return per request, '
|
||||
'0 for no limit. Default is the maximum number used '
|
||||
'by the Ironic API Service.')
|
||||
@cliutils.arg(
|
||||
'--marker',
|
||||
metavar='<marker>',
|
||||
help='Chassis UUID (e.g of the last chassis in the list '
|
||||
'from a previous request). Returns the list of chassis '
|
||||
'after this UUID.')
|
||||
def do_chassis_list(cc, args):
|
||||
"""List chassis."""
|
||||
chassis = cc.chassis.list()
|
||||
params = {}
|
||||
if args.marker is not None:
|
||||
params['marker'] = args.marker
|
||||
if args.limit is not None:
|
||||
params['limit'] = args.limit
|
||||
|
||||
chassis = cc.chassis.list(**params)
|
||||
field_labels = ['UUID', 'Description']
|
||||
fields = ['uuid', 'description']
|
||||
cliutils.print_list(chassis, fields, field_labels, sortby_index=1)
|
||||
cliutils.print_list(chassis, fields, field_labels, sortby_index=None)
|
||||
|
||||
|
||||
@cliutils.arg(
|
||||
@ -96,11 +115,30 @@ def do_chassis_update(cc, args):
|
||||
_print_chassis_show(chassis)
|
||||
|
||||
|
||||
@cliutils.arg(
|
||||
'--limit',
|
||||
metavar='<limit>',
|
||||
type=int,
|
||||
help='Maximum number of nodes to return per request, '
|
||||
'0 for no limit. Default is the maximum number used '
|
||||
'by the Ironic API Service.')
|
||||
@cliutils.arg(
|
||||
'--marker',
|
||||
metavar='<marker>',
|
||||
help='Node UUID (e.g of the last node in the list from '
|
||||
'a previous request). Returns the list of nodes '
|
||||
'after this UUID.')
|
||||
@cliutils.arg('chassis', metavar='<chassis id>', help="UUID of chassis")
|
||||
def do_chassis_node_list(cc, args):
|
||||
"""List the nodes contained in the chassis."""
|
||||
nodes = cc.chassis.list_nodes(args.chassis)
|
||||
params = {}
|
||||
if args.marker is not None:
|
||||
params['marker'] = args.marker
|
||||
if args.limit is not None:
|
||||
params['limit'] = args.limit
|
||||
|
||||
nodes = cc.chassis.list_nodes(args.chassis, **params)
|
||||
field_labels = ['UUID', 'Instance UUID',
|
||||
'Power State', 'Provisioning State']
|
||||
fields = ['uuid', 'instance_uuid', 'power_state', 'provision_state']
|
||||
cliutils.print_list(nodes, fields, field_labels, sortby_index=1)
|
||||
cliutils.print_list(nodes, fields, field_labels, sortby_index=None)
|
||||
|
@ -33,22 +33,89 @@ class NodeManager(base.Manager):
|
||||
def _path(id=None):
|
||||
return '/v1/nodes/%s' % id if id else '/v1/nodes'
|
||||
|
||||
def list(self, associated=None, maintenance=None):
|
||||
def list(self, associated=None, maintenance=None, marker=None, limit=None):
|
||||
"""Retrieve a list of nodes.
|
||||
|
||||
:param associated: Optional, boolean whether to return a list of
|
||||
associated or unassociated nodes.
|
||||
:param maintenance: Optional, boolean value that indicates whether
|
||||
to get nodes in maintenance mode ("True"), or not
|
||||
in maintenance mode ("False").
|
||||
:param marker: Optional, the UUID of a node, eg the last
|
||||
node from a previous result set. Return
|
||||
the next result set.
|
||||
:param limit: The maximum number of results to return per
|
||||
request, if:
|
||||
|
||||
1) limit > 0, the maximum number of nodes to return.
|
||||
2) limit == 0, return the entire list of nodes.
|
||||
3) limit param is NOT specified (None), the number of items
|
||||
returned respect the maximum imposed by the Ironic API
|
||||
(see Ironic's api.max_limit option).
|
||||
|
||||
:returns: A list of nodes.
|
||||
|
||||
"""
|
||||
if limit is not None:
|
||||
limit = int(limit)
|
||||
|
||||
filters = []
|
||||
if isinstance(limit, int) and limit > 0:
|
||||
filters.append('limit=%s' % limit)
|
||||
if marker is not None:
|
||||
filters.append('marker=%s' % marker)
|
||||
if associated is not None:
|
||||
filters.append('associated=%s' % associated)
|
||||
if maintenance is not None:
|
||||
filters.append('maintenance=%s' % maintenance)
|
||||
|
||||
if not filters:
|
||||
return self._list(self._path(), "nodes")
|
||||
else:
|
||||
path = None
|
||||
if filters:
|
||||
path = '?' + '&'.join(filters)
|
||||
return self._list(self._path(path), "nodes")
|
||||
|
||||
def list_ports(self, node_id):
|
||||
if limit is None:
|
||||
return self._list(self._path(path), "nodes")
|
||||
else:
|
||||
return self._list_pagination(self._path(path), "nodes",
|
||||
limit=limit)
|
||||
|
||||
def list_ports(self, node_id, marker=None, limit=None):
|
||||
"""List all the ports for a given node.
|
||||
|
||||
:param node_id: The UUID of the node.
|
||||
:param marker: Optional, the UUID of a port, eg the last
|
||||
port from a previous result set. Return
|
||||
the next result set.
|
||||
:param limit: The maximum number of results to return per
|
||||
request, if:
|
||||
|
||||
1) limit > 0, the maximum number of ports to return.
|
||||
2) limit == 0, return the entire list of ports.
|
||||
3) limit param is NOT specified (None), the number of items
|
||||
returned respect the maximum imposed by the Ironic API
|
||||
(see Ironic's api.max_limit option).
|
||||
|
||||
:returns: A list of ports.
|
||||
|
||||
"""
|
||||
if limit is not None:
|
||||
limit = int(limit)
|
||||
|
||||
filters = []
|
||||
if isinstance(limit, int) and limit > 0:
|
||||
filters.append('limit=%s' % limit)
|
||||
if marker is not None:
|
||||
filters.append('marker=%s' % marker)
|
||||
|
||||
path = "%s/ports" % node_id
|
||||
return self._list(self._path(path), "ports")
|
||||
if filters:
|
||||
path += '?' + '&'.join(filters)
|
||||
|
||||
if limit is None:
|
||||
return self._list(self._path(path), "ports")
|
||||
else:
|
||||
return self._list_pagination(self._path(path), "ports",
|
||||
limit=limit)
|
||||
|
||||
def get(self, node_id):
|
||||
try:
|
||||
|
@ -47,6 +47,19 @@ def do_node_show(cc, args):
|
||||
_print_node_show(node)
|
||||
|
||||
|
||||
@cliutils.arg(
|
||||
'--limit',
|
||||
metavar='<limit>',
|
||||
type=int,
|
||||
help='Maximum number of nodes to return per request, '
|
||||
'0 for no limit. Default is the maximum number used '
|
||||
'by the Ironic API Service.')
|
||||
@cliutils.arg(
|
||||
'--marker',
|
||||
metavar='<marker>',
|
||||
help='Node UUID (e.g of the last node in the list from '
|
||||
'a previous request). Returns the list of nodes '
|
||||
'after this UUID.')
|
||||
@cliutils.arg(
|
||||
'--maintenance',
|
||||
metavar='<maintenance>',
|
||||
@ -64,13 +77,17 @@ def do_node_list(cc, args):
|
||||
params['associated'] = args.associated
|
||||
if args.maintenance is not None:
|
||||
params['maintenance'] = args.maintenance
|
||||
if args.marker is not None:
|
||||
params['marker'] = args.marker
|
||||
if args.limit is not None:
|
||||
params['limit'] = args.limit
|
||||
|
||||
nodes = cc.node.list(**params)
|
||||
field_labels = ['UUID', 'Instance UUID', 'Power State',
|
||||
'Provisioning State', 'Maintenance']
|
||||
fields = ['uuid', 'instance_uuid', 'power_state',
|
||||
'provision_state', 'maintenance']
|
||||
cliutils.print_list(nodes, fields, field_labels, sortby_index=1)
|
||||
cliutils.print_list(nodes, fields, field_labels, sortby_index=None)
|
||||
|
||||
|
||||
@cliutils.arg(
|
||||
@ -145,13 +162,32 @@ def do_node_update(cc, args):
|
||||
_print_node_show(node)
|
||||
|
||||
|
||||
@cliutils.arg(
|
||||
'--limit',
|
||||
metavar='<limit>',
|
||||
type=int,
|
||||
help='Maximum number of ports to return per request, '
|
||||
'0 for no limit. Default is the maximum number used '
|
||||
'by the Ironic API Service.')
|
||||
@cliutils.arg(
|
||||
'--marker',
|
||||
metavar='<marker>',
|
||||
help='Port UUID (e.g of the last port in the list from '
|
||||
'a previous request). Returns the list of ports '
|
||||
'after this UUID.')
|
||||
@cliutils.arg('node', metavar='<node id>', help="UUID of node")
|
||||
def do_node_port_list(cc, args):
|
||||
"""List the ports associated with the node."""
|
||||
ports = cc.node.list_ports(args.node)
|
||||
params = {}
|
||||
if args.marker is not None:
|
||||
params['marker'] = args.marker
|
||||
if args.limit is not None:
|
||||
params['limit'] = args.limit
|
||||
|
||||
ports = cc.node.list_ports(args.node, **params)
|
||||
field_labels = ['UUID', 'Address']
|
||||
fields = ['uuid', 'address']
|
||||
cliutils.print_list(ports, fields, field_labels, sortby_index=1)
|
||||
cliutils.print_list(ports, fields, field_labels, sortby_index=None)
|
||||
|
||||
|
||||
@cliutils.arg('node', metavar='<node id>', help="UUID of node")
|
||||
|
@ -32,8 +32,42 @@ class PortManager(base.Manager):
|
||||
def _path(id=None):
|
||||
return '/v1/ports/%s' % id if id else '/v1/ports'
|
||||
|
||||
def list(self):
|
||||
return self._list(self._path(), "ports")
|
||||
def list(self, limit=None, marker=None):
|
||||
"""Retrieve a list of port.
|
||||
|
||||
:param marker: Optional, the UUID of a port, eg the last
|
||||
port from a previous result set. Return
|
||||
the next result set.
|
||||
:param limit: The maximum number of results to return per
|
||||
request, if:
|
||||
|
||||
1) limit > 0, the maximum number of ports to return.
|
||||
2) limit == 0, return the entire list of ports.
|
||||
3) limit param is NOT specified (None), the number of items
|
||||
returned respect the maximum imposed by the Ironic API
|
||||
(see Ironic's api.max_limit option).
|
||||
|
||||
:returns: A list of ports.
|
||||
|
||||
"""
|
||||
if limit is not None:
|
||||
limit = int(limit)
|
||||
|
||||
filters = []
|
||||
if isinstance(limit, int) and limit > 0:
|
||||
filters.append('limit=%s' % limit)
|
||||
if marker is not None:
|
||||
filters.append('marker=%s' % marker)
|
||||
|
||||
path = None
|
||||
if filters:
|
||||
path = '?' + '&'.join(filters)
|
||||
|
||||
if limit is None:
|
||||
return self._list(self._path(path), "ports")
|
||||
else:
|
||||
return self._list_pagination(self._path(path), "ports",
|
||||
limit=limit)
|
||||
|
||||
def get(self, port_id):
|
||||
try:
|
||||
|
@ -33,12 +33,31 @@ def do_port_show(cc, args):
|
||||
_print_port_show(port)
|
||||
|
||||
|
||||
@cliutils.arg(
|
||||
'--limit',
|
||||
metavar='<limit>',
|
||||
type=int,
|
||||
help='Maximum number of ports to return per request, '
|
||||
'0 for no limit. Default is the maximum number used '
|
||||
'by the Ironic API Service.')
|
||||
@cliutils.arg(
|
||||
'--marker',
|
||||
metavar='<marker>',
|
||||
help='Port UUID (e.g of the last port in the list from '
|
||||
'a previous request). Returns the list of ports '
|
||||
'after this UUID.')
|
||||
def do_port_list(cc, args):
|
||||
"""List ports."""
|
||||
port = cc.port.list()
|
||||
params = {}
|
||||
if args.marker is not None:
|
||||
params['marker'] = args.marker
|
||||
if args.limit is not None:
|
||||
params['limit'] = args.limit
|
||||
|
||||
port = cc.port.list(**params)
|
||||
field_labels = ['UUID', 'Address']
|
||||
fields = ['uuid', 'address']
|
||||
cliutils.print_list(port, fields, field_labels, sortby_index=1)
|
||||
cliutils.print_list(port, fields, field_labels, sortby_index=None)
|
||||
|
||||
|
||||
@cliutils.arg(
|
||||
|
Loading…
x
Reference in New Issue
Block a user