Add allocation owner

Add support to create an allocation with an owner, and to display
an allocation owner.

Change-Id: I85d5c324b177a1e016e93e011f9ad22144ca9340
Story: #2006506
Task: #37540
This commit is contained in:
Tzu-Mainn Chen 2020-01-15 19:01:57 +00:00
parent 7d58049841
commit a64370701e
8 changed files with 101 additions and 6 deletions

View File

@ -40,7 +40,7 @@ from ironicclient import exc
# http://specs.openstack.org/openstack/ironic-specs/specs/kilo/api-microversions.html # noqa
# for full details.
DEFAULT_VER = '1.9'
LAST_KNOWN_API_VERSION = 58
LAST_KNOWN_API_VERSION = 60
LATEST_VERSION = '1.{}'.format(LAST_KNOWN_API_VERSION)
LOG = logging.getLogger(__name__)

View File

@ -56,6 +56,10 @@ class CreateBaremetalAllocation(command.ShowOne):
'--uuid',
dest='uuid',
help=_('UUID of the allocation.'))
parser.add_argument(
'--owner',
dest='owner',
help=_('Owner of the allocation.'))
parser.add_argument(
'--extra',
metavar="<key=value>",
@ -91,7 +95,7 @@ class CreateBaremetalAllocation(command.ShowOne):
_('--resource-class is required except when --node is used'))
field_list = ['name', 'uuid', 'extra', 'resource_class', 'traits',
'candidate_nodes', 'node']
'candidate_nodes', 'node', 'owner']
fields = dict((k, v) for (k, v) in vars(parsed_args).items()
if k in field_list and v is not None)
@ -182,6 +186,10 @@ class ListBaremetalAllocation(command.Lister):
'--state',
metavar='<state>',
help=_("Only list allocations in this state."))
parser.add_argument(
'--owner',
metavar='<owner>',
help=_("Only list allocations with this owner."))
# NOTE(dtantsur): the allocation API does not expose the 'detail' flag,
# but some fields are inconvenient to display in a table, so we emulate
@ -216,7 +224,7 @@ class ListBaremetalAllocation(command.Lister):
parsed_args.limit)
params['limit'] = parsed_args.limit
params['marker'] = parsed_args.marker
for field in ('node', 'resource_class', 'state'):
for field in ('node', 'resource_class', 'state', 'owner'):
value = getattr(parsed_args, field)
if value is not None:
params[field] = value

View File

@ -34,6 +34,7 @@ BAREMETAL_CHASSIS = {
baremetal_uuid = 'xxx-xxxxxx-xxxx'
baremetal_name = 'fake name'
baremetal_owner = 'fake-owner'
baremetal_instance_uuid = 'yyy-yyyyyy-yyyy'
baremetal_power_state = None
baremetal_provision_state = None

View File

@ -174,6 +174,28 @@ class TestCreateBaremetalAllocation(TestBaremetalAllocation):
self.baremetal_mock.allocation.create.assert_called_once_with(**args)
def test_baremetal_allocation_create_owner(self):
arglist = [
'--resource-class', baremetal_fakes.baremetal_resource_class,
'--owner', baremetal_fakes.baremetal_owner,
]
verifylist = [
('resource_class', baremetal_fakes.baremetal_resource_class),
('owner', baremetal_fakes.baremetal_owner),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
args = {
'resource_class': baremetal_fakes.baremetal_resource_class,
'owner': baremetal_fakes.baremetal_owner,
}
self.baremetal_mock.allocation.create.assert_called_once_with(**args)
def test_baremetal_allocation_create_no_options(self):
arglist = []
verifylist = []
@ -344,6 +366,36 @@ class TestBaremetalAllocationList(TestBaremetalAllocation):
baremetal_fakes.baremetal_uuid),)
self.assertEqual(datalist, tuple(data))
def test_baremetal_allocation_list_owner(self):
arglist = ['--owner',
baremetal_fakes.baremetal_owner]
verifylist = [('owner',
baremetal_fakes.baremetal_owner)]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
kwargs = {
'owner': baremetal_fakes.baremetal_owner,
'marker': None,
'limit': None}
self.baremetal_mock.allocation.list.assert_called_once_with(**kwargs)
collist = (
"UUID",
"Name",
"Resource Class",
"State",
"Node UUID")
self.assertEqual(collist, columns)
datalist = ((baremetal_fakes.baremetal_uuid,
baremetal_fakes.baremetal_name,
baremetal_fakes.baremetal_resource_class,
baremetal_fakes.baremetal_allocation_state,
baremetal_fakes.baremetal_uuid),)
self.assertEqual(datalist, tuple(data))
def test_baremetal_allocation_list_state(self):
arglist = ['--state', baremetal_fakes.baremetal_allocation_state]
verifylist = [('state', baremetal_fakes.baremetal_allocation_state)]
@ -388,6 +440,7 @@ class TestBaremetalAllocationList(TestBaremetalAllocation):
collist = ('UUID',
'Name',
'State',
'Owner',
'Node UUID',
'Last Error',
'Resource Class',
@ -401,6 +454,7 @@ class TestBaremetalAllocationList(TestBaremetalAllocation):
datalist = ((baremetal_fakes.baremetal_uuid,
baremetal_fakes.baremetal_name,
baremetal_fakes.baremetal_allocation_state,
'',
baremetal_fakes.baremetal_uuid,
'',
baremetal_fakes.baremetal_resource_class,

View File

@ -21,6 +21,7 @@ import ironicclient.v1.allocation
ALLOCATION = {'uuid': '11111111-2222-3333-4444-555555555555',
'name': 'Allocation-name',
'owner': None,
'state': 'active',
'node_uuid': '66666666-7777-8888-9999-000000000000',
'last_error': None,
@ -31,6 +32,7 @@ ALLOCATION = {'uuid': '11111111-2222-3333-4444-555555555555',
ALLOCATION2 = {'uuid': '55555555-4444-3333-2222-111111111111',
'name': 'Allocation2-name',
'owner': 'fake-owner',
'state': 'allocating',
'node_uuid': None,
'last_error': None,
@ -73,6 +75,13 @@ fake_responses = {
{"allocations": [ALLOCATION]},
),
},
'/v1/allocations/?owner=%s' % ALLOCATION2['owner']:
{
'GET': (
{},
{"allocations": [ALLOCATION2]},
),
},
}
fake_responses_pagination = {
@ -150,6 +159,19 @@ class AllocationManagerTest(testtools.TestCase):
self.assertEqual(expected_resp,
self.api.responses['/v1/allocations']['GET'])
def test_allocations_list_by_owner(self):
allocations = self.mgr.list(owner=ALLOCATION2['owner'])
expect = [
('GET', '/v1/allocations/?owner=%s' % ALLOCATION2['owner'], {},
None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(allocations))
expected_resp = ({}, {"allocations": [ALLOCATION, ALLOCATION2]},)
self.assertEqual(expected_resp,
self.api.responses['/v1/allocations']['GET'])
def test_allocations_show(self):
allocation = self.mgr.get(ALLOCATION['uuid'])
expect = [
@ -158,6 +180,7 @@ class AllocationManagerTest(testtools.TestCase):
self.assertEqual(expect, self.api.calls)
self.assertEqual(ALLOCATION['uuid'], allocation.uuid)
self.assertEqual(ALLOCATION['name'], allocation.name)
self.assertEqual(ALLOCATION['owner'], allocation.owner)
self.assertEqual(ALLOCATION['node_uuid'], allocation.node_uuid)
self.assertEqual(ALLOCATION['state'], allocation.state)
self.assertEqual(ALLOCATION['resource_class'],

View File

@ -30,10 +30,11 @@ class AllocationManager(base.CreateManager):
resource_class = Allocation
_resource_name = 'allocations'
_creation_attributes = ['extra', 'name', 'resource_class', 'uuid',
'traits', 'candidate_nodes', 'node']
'traits', 'candidate_nodes', 'node', 'owner']
def list(self, resource_class=None, state=None, node=None, limit=None,
marker=None, sort_key=None, sort_dir=None, fields=None):
marker=None, sort_key=None, sort_dir=None, fields=None,
owner=None):
"""Retrieve a list of allocations.
:param resource_class: Optional, get allocations with this resource
@ -60,6 +61,7 @@ class AllocationManager(base.CreateManager):
:param fields: Optional, a list with a specified set of fields
of the resource to be returned.
:param owner: Optional, project that owns the allocation.
:returns: A list of allocations.
:raises: InvalidAttribute if a subset of fields is requested with
@ -72,7 +74,8 @@ class AllocationManager(base.CreateManager):
filters = utils.common_filters(marker, limit, sort_key, sort_dir,
fields)
for name, value in [('resource_class', resource_class),
('state', state), ('node', node)]:
('state', state), ('node', node),
('owner', owner)]:
if value is not None:
filters.append('%s=%s' % (name, value))

View File

@ -493,6 +493,7 @@ ALLOCATION_DETAILED_RESOURCE = Resource(
['uuid',
'name',
'state',
'owner',
'node_uuid',
'last_error',
'resource_class',

View File

@ -0,0 +1,5 @@
---
features:
- |
Adds support to create an allocation with an ``owner``,
as well as display it. Introduced in API 1.60.