Merge "Expose the vendor_passthru resource"
This commit is contained in:
commit
d5d42ad655
@ -1013,6 +1013,35 @@ JSON structure of a meta_data::
|
|||||||
"bar": "foo"
|
"bar": "foo"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VendorPassthru
|
||||||
|
---------
|
||||||
|
|
||||||
|
VendorPassthru allow vendors to expose a custom functionality in
|
||||||
|
the Ironic API. Ironic will merely relay the message from here to the
|
||||||
|
appropriate driver (see: Driver_), no introspection will be made in the
|
||||||
|
message body.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
======= ================================== ==========================
|
||||||
|
Verb Path Response
|
||||||
|
======= ================================== ==========================
|
||||||
|
POST /nodes/1/vendor_passthru/<method> Invoke a specific <method>
|
||||||
|
======= ================================== ==========================
|
||||||
|
|
||||||
|
Example
|
||||||
|
^^^^^^^^
|
||||||
|
|
||||||
|
Invoking "custom_method"::
|
||||||
|
|
||||||
|
POST /nodes/1/vendor_passthru/custom_method
|
||||||
|
{
|
||||||
|
...
|
||||||
|
"foo": "bar",
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
Areas To Be Defined
|
Areas To Be Defined
|
||||||
####################
|
####################
|
||||||
|
|
||||||
|
@ -257,12 +257,39 @@ class NodeCollection(collection.Collection):
|
|||||||
return collection
|
return collection
|
||||||
|
|
||||||
|
|
||||||
|
class NodeVendorPassthruController(rest.RestController):
|
||||||
|
"""REST controller for VendorPassthru.
|
||||||
|
|
||||||
|
This controller allow vendors to expose a custom functionality in
|
||||||
|
the Ironic API. Ironic will merely relay the message from here to the
|
||||||
|
appropriate driver, no introspection will be made in the message body.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@wsme_pecan.wsexpose(None, unicode, unicode, body=unicode, status=202)
|
||||||
|
def _default(self, node_id, method, data):
|
||||||
|
# Only allow POST requests
|
||||||
|
if pecan.request.method.upper() != "POST":
|
||||||
|
raise exception.NotFound
|
||||||
|
|
||||||
|
# Raise an exception if node is not found
|
||||||
|
objects.Node.get_by_uuid(pecan.request.context, node_id)
|
||||||
|
|
||||||
|
# Raise an exception if method is not specified
|
||||||
|
if not method:
|
||||||
|
raise wsme.exc.ClientSideError(_("Method not specified"))
|
||||||
|
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
class NodesController(rest.RestController):
|
class NodesController(rest.RestController):
|
||||||
"""REST controller for Nodes."""
|
"""REST controller for Nodes."""
|
||||||
|
|
||||||
state = NodeStatesController()
|
state = NodeStatesController()
|
||||||
"Expose the state controller action as a sub-element of nodes"
|
"Expose the state controller action as a sub-element of nodes"
|
||||||
|
|
||||||
|
vendor_passthru = NodeVendorPassthruController()
|
||||||
|
"A resource used for vendors to expose a custom functionality in the API"
|
||||||
|
|
||||||
_custom_actions = {
|
_custom_actions = {
|
||||||
'ports': ['GET'],
|
'ports': ['GET'],
|
||||||
}
|
}
|
||||||
|
@ -243,6 +243,29 @@ class TestPost(base.FunctionalTest):
|
|||||||
result = self.get_json('/nodes/%s' % ndict['uuid'])
|
result = self.get_json('/nodes/%s' % ndict['uuid'])
|
||||||
self.assertEqual(ndict['uuid'], result['uuid'])
|
self.assertEqual(ndict['uuid'], result['uuid'])
|
||||||
|
|
||||||
|
def test_vendor_passthru(self):
|
||||||
|
ndict = dbutils.get_test_node()
|
||||||
|
self.post_json('/nodes', ndict)
|
||||||
|
uuid = ndict['uuid']
|
||||||
|
# TODO(lucasagomes): When vendor_passthru gets implemented
|
||||||
|
# remove the expect_errors parameter
|
||||||
|
response = self.post_json('/nodes/%s/vendor_passthru/method' % uuid,
|
||||||
|
{'foo': 'bar'},
|
||||||
|
expect_errors=True)
|
||||||
|
# TODO(lucasagomes): it's expected to return 202, but because we are
|
||||||
|
# passing expect_errors=True to the post_json
|
||||||
|
# function the return code will be 500. So change
|
||||||
|
# the return code when vendor_passthru gets
|
||||||
|
# implemented
|
||||||
|
self.assertEqual(response.status_code, 500)
|
||||||
|
|
||||||
|
def test_vendor_passthru_without_method(self):
|
||||||
|
ndict = dbutils.get_test_node()
|
||||||
|
self.post_json('/nodes', ndict)
|
||||||
|
self.assertRaises(webtest.app.AppError, self.post_json,
|
||||||
|
'/nodes/%s/vendor_passthru' % ndict['uuid'],
|
||||||
|
{'foo': 'bar'})
|
||||||
|
|
||||||
|
|
||||||
class TestDelete(base.FunctionalTest):
|
class TestDelete(base.FunctionalTest):
|
||||||
|
|
||||||
@ -251,7 +274,7 @@ class TestDelete(base.FunctionalTest):
|
|||||||
self.post_json('/nodes', ndict)
|
self.post_json('/nodes', ndict)
|
||||||
self.delete('/nodes/%s' % ndict['uuid'])
|
self.delete('/nodes/%s' % ndict['uuid'])
|
||||||
response = self.get_json('/nodes/%s' % ndict['uuid'],
|
response = self.get_json('/nodes/%s' % ndict['uuid'],
|
||||||
expect_errors=True)
|
expect_errors=True)
|
||||||
self.assertEqual(response.status_int, 500)
|
self.assertEqual(response.status_int, 500)
|
||||||
self.assertEqual(response.content_type, 'application/json')
|
self.assertEqual(response.content_type, 'application/json')
|
||||||
self.assertTrue(response.json['error_message'])
|
self.assertTrue(response.json['error_message'])
|
||||||
|
Loading…
Reference in New Issue
Block a user