Add Validation for Node Manage/Action API's
Partially-Implements blueprint validation Change-Id: If10e37e0036c88a4bd0b183793e4344d8c257b67
This commit is contained in:
parent
a42b5a688f
commit
542f3ced2f
@ -332,7 +332,7 @@ Response
|
||||
Manage Node
|
||||
===========
|
||||
|
||||
.. rest_method:: POST /v1/nodes/managed
|
||||
.. rest_method:: POST /v1/nodes/manage
|
||||
|
||||
Manage a composed node already existing in the RSD rack by creating a
|
||||
Valence database entry for it, allowing Valence to perform all operations
|
||||
|
@ -48,14 +48,16 @@ class Node(Resource):
|
||||
|
||||
class NodeAction(Resource):
|
||||
|
||||
@validator.check_input('node_action_schema')
|
||||
def post(self, node_uuid):
|
||||
return utils.make_response(
|
||||
http_client.OK,
|
||||
http_client.NO_CONTENT,
|
||||
nodes.Node.node_action(node_uuid, request.get_json()))
|
||||
|
||||
|
||||
class NodeManage(Resource):
|
||||
|
||||
@validator.check_input('node_manage_schema')
|
||||
def post(self):
|
||||
return utils.make_response(
|
||||
http_client.OK, nodes.Node.manage_node(request.get_json()))
|
||||
|
@ -191,19 +191,6 @@ class Node(object):
|
||||
param request_body: parameter of node action
|
||||
return: message of this deletion
|
||||
"""
|
||||
|
||||
# Get node detail from db, and map node uuid to index
|
||||
index = db_api.Connection.get_composed_node_by_uuid(node_uuid).index
|
||||
|
||||
# TODO(lin.yang): should validate request body whether follow specifc
|
||||
# format, like
|
||||
# {
|
||||
# "Reset": {
|
||||
# "Type": "On"
|
||||
# }
|
||||
# }
|
||||
# Should rework this part after basic validation framework for api
|
||||
# input is done.
|
||||
# https://review.openstack.org/#/c/422547/
|
||||
|
||||
return redfish.node_action(index, request_body)
|
||||
|
@ -3,6 +3,7 @@ import json
|
||||
|
||||
import mock
|
||||
from oslotest import base
|
||||
from six.moves import http_client
|
||||
|
||||
from valence.api import app as flask_app
|
||||
from valence.common import constants
|
||||
@ -32,7 +33,7 @@ class TestFlavorApi(TestApiValidation):
|
||||
response = self.app.post('/v1/flavors',
|
||||
content_type='application/json',
|
||||
data=json.dumps(flavor))
|
||||
self.assertEqual(200, response.status_code)
|
||||
self.assertEqual(http_client.OK, response.status_code)
|
||||
mock_create.assert_called_once_with(flavor)
|
||||
|
||||
def test_flavor_create_incorrect_param(self):
|
||||
@ -44,7 +45,7 @@ class TestFlavorApi(TestApiValidation):
|
||||
content_type='application/json',
|
||||
data=json.dumps(self.flavor))
|
||||
response = json.loads(response.data.decode())
|
||||
self.assertEqual(400, response['status'])
|
||||
self.assertEqual(http_client.BAD_REQUEST, response['status'])
|
||||
self.assertEqual('ValidationError', response['code'])
|
||||
|
||||
# Test invalid key
|
||||
@ -53,7 +54,7 @@ class TestFlavorApi(TestApiValidation):
|
||||
content_type='application/json',
|
||||
data=json.dumps(self.flavor))
|
||||
response = json.loads(response.data.decode())
|
||||
self.assertEqual(400, response['status'])
|
||||
self.assertEqual(http_client.BAD_REQUEST, response['status'])
|
||||
self.assertEqual('ValidationError', response['code'])
|
||||
|
||||
|
||||
@ -84,7 +85,7 @@ class TestPodmanagerApi(TestApiValidation):
|
||||
response = self.app.post('/v1/pod_managers',
|
||||
content_type='application/json',
|
||||
data=json.dumps(values))
|
||||
self.assertEqual(200, response.status_code)
|
||||
self.assertEqual(http_client.OK, response.status_code)
|
||||
|
||||
def test_check_creation_incomplete_parameters(self):
|
||||
incomplete_values = {
|
||||
@ -95,7 +96,7 @@ class TestPodmanagerApi(TestApiValidation):
|
||||
content_type='application/json',
|
||||
data=json.dumps(incomplete_values))
|
||||
response = json.loads(response.data.decode())
|
||||
self.assertEqual(400, response['status'])
|
||||
self.assertEqual(http_client.BAD_REQUEST, response['status'])
|
||||
self.assertEqual('ValidationError', response['code'])
|
||||
|
||||
def test_check_creation_invalid_authentication(self):
|
||||
@ -111,7 +112,7 @@ class TestPodmanagerApi(TestApiValidation):
|
||||
content_type='application/json',
|
||||
data=json.dumps(invalid_auth_values))
|
||||
response = json.loads(response.data.decode())
|
||||
self.assertEqual(400, response['status'])
|
||||
self.assertEqual(http_client.BAD_REQUEST, response['status'])
|
||||
self.assertEqual('ValidationError', response['code'])
|
||||
|
||||
|
||||
@ -136,7 +137,7 @@ class TestNodeApi(TestApiValidation):
|
||||
resp = self.app.post('/v1/nodes',
|
||||
content_type='application/json',
|
||||
data=json.dumps(req))
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(http_client.OK, resp.status_code)
|
||||
|
||||
@mock.patch('valence.controller.nodes.Node.compose_node')
|
||||
def test_compose_request_using_flavor(self, mock_compose):
|
||||
@ -148,7 +149,7 @@ class TestNodeApi(TestApiValidation):
|
||||
resp = self.app.post('/v1/nodes',
|
||||
content_type='application/json',
|
||||
data=json.dumps(req))
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(http_client.OK, resp.status_code)
|
||||
|
||||
def test_compose_request_invalid_params(self):
|
||||
req = {
|
||||
@ -158,5 +159,54 @@ class TestNodeApi(TestApiValidation):
|
||||
content_type='application/json',
|
||||
data=json.dumps(req))
|
||||
response = json.loads(resp.data.decode())
|
||||
self.assertEqual(400, response['status'])
|
||||
self.assertEqual(http_client.BAD_REQUEST, response['status'])
|
||||
self.assertEqual('ValidationError', response['code'])
|
||||
|
||||
@mock.patch('valence.controller.nodes.Node.manage_node')
|
||||
def test_node_manage_request(self, mock_manage):
|
||||
req = {"node_index": "fake-index"}
|
||||
mock_manage.return_value = {"uuid": "ea8e2a25-2901-438d-8157-de7ffd",
|
||||
"links": "fake-links",
|
||||
"name": "fake-node",
|
||||
"index": "fake-index"}
|
||||
resp = self.app.post('/v1/nodes/manage',
|
||||
content_type='application/json',
|
||||
data=json.dumps(req))
|
||||
mock_manage.assert_called_once_with(req)
|
||||
self.assertEqual(http_client.OK, resp.status_code)
|
||||
|
||||
def test_node_manage_request_invalid(self):
|
||||
req = {"node_id": "fake-index"}
|
||||
resp = self.app.post('/v1/nodes/manage',
|
||||
content_type='application/json',
|
||||
data=json.dumps(req))
|
||||
response = json.loads(resp.data.decode())
|
||||
self.assertEqual(http_client.BAD_REQUEST, response['status'])
|
||||
self.assertEqual('ValidationError', response['code'])
|
||||
|
||||
@mock.patch('valence.controller.nodes.Node.node_action')
|
||||
def test_node_action_request(self, mock_action):
|
||||
req = {
|
||||
"Reset": {
|
||||
"Type": "On"
|
||||
}
|
||||
}
|
||||
mock_action.return_value = None
|
||||
resp = self.app.post('/v1/nodes/fake-node/action',
|
||||
content_type='application/json',
|
||||
data=json.dumps(req))
|
||||
mock_action.assert_called_once_with('fake-node', req)
|
||||
self.assertEqual(http_client.NO_CONTENT, resp.status_code)
|
||||
|
||||
def test_node_action_request_invalid(self):
|
||||
req = {
|
||||
"Boot": {
|
||||
"Type": "On"
|
||||
}
|
||||
}
|
||||
resp = self.app.post('/v1/nodes/fake-node/action',
|
||||
content_type='application/json',
|
||||
data=json.dumps(req))
|
||||
response = json.loads(resp.data.decode())
|
||||
self.assertEqual(http_client.BAD_REQUEST, response['status'])
|
||||
self.assertEqual('ValidationError', response['code'])
|
||||
|
@ -68,7 +68,6 @@ podmanager_schema = {
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
|
||||
jsonschema.Draft4Validator.check_schema(podmanager_schema)
|
||||
|
||||
compose_node_with_flavor = {
|
||||
@ -91,6 +90,54 @@ compose_node_schema = {
|
||||
|
||||
jsonschema.Draft4Validator.check_schema(compose_node_schema)
|
||||
|
||||
node_manage_schema = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'node_index': {'type': 'string'},
|
||||
},
|
||||
'required': ['node_index'],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
jsonschema.Draft4Validator.check_schema(node_manage_schema)
|
||||
|
||||
node_action_schema = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'Boot': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'Enabled': {
|
||||
'enum': ['Once', 'Continuous']
|
||||
},
|
||||
'Target': {
|
||||
'enum': ['Pxe', 'Hdd', 'None']
|
||||
},
|
||||
},
|
||||
'required': ['Enabled', 'Target'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
'Reset': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'Type': {
|
||||
'enum': ['On', 'ForceOn', 'ForceOff', 'GracefulRestart']
|
||||
},
|
||||
},
|
||||
'required': ['Type'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
'oneOf': [
|
||||
{'required': ['Boot']},
|
||||
{'required': ['Reset']}],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
jsonschema.Draft4Validator.check_schema(node_action_schema)
|
||||
|
||||
SCHEMAS = {'flavor_schema': flavor_schema,
|
||||
'podmanager_schema': podmanager_schema,
|
||||
'compose_node_schema': compose_node_schema, }
|
||||
'compose_node_schema': compose_node_schema,
|
||||
'node_manage_schema': node_manage_schema,
|
||||
'node_action_schema': node_action_schema, }
|
||||
|
Loading…
Reference in New Issue
Block a user