Add validation for 'sriov_numvfs' value

Nailgun should accept only integer positive values for
this parameter.

Closes-Bug: #1556115
Change-Id: I198079bfa15dd6020dfad063cf48b612bb68e539
This commit is contained in:
slava 2016-03-14 18:49:06 +03:00 committed by Valyavskiy Viacheslav
parent 715e2e9ca6
commit 7744d16dff
7 changed files with 134 additions and 5 deletions

View File

@ -16,3 +16,5 @@ from nailgun.api.v1.validators.json_schema \
import cluster as cluster_schema
from nailgun.api.v1.validators.json_schema \
import node as node_schema
from nailgun.api.v1.validators.json_schema \
import interface as iface_schema

View File

@ -26,9 +26,13 @@ NULLABLE_STRING = {
'type': ['string', 'null']
}
NULLABLE_BOOL = {
'type': ['boolean', 'null']
}
POSITIVE_INTEGER = {
'type': 'integer',
'minValue': 1
'minimum': 1
}
POSITIVE_NUMBER = {
@ -47,7 +51,7 @@ NULLABLE_ENUM = lambda e: {
NON_NEGATIVE_INTEGER = {
'type': 'integer',
'minValue': 0
'minimum': 0
}
NULLABLE_NON_NEGATIVE_INTEGER = {

View File

@ -0,0 +1,68 @@
# -*- coding: utf-8 -*-
# Copyright 2016 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from nailgun.api.v1.validators.json_schema import base_types
INTERFACES = {
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Interface",
"description": "Serialized Interface object",
"type": "array",
"items": {
"type": "object",
"properties": {
"ip": base_types.NULLABLE_IP_ADDRESS,
"netmask": base_types.NET_ADDRESS,
"mac": base_types.NULLABLE_MAC_ADDRESS,
"state": base_types.NULLABLE_STRING,
"name": {"type": "string"},
"driver": base_types.NULLABLE_STRING,
"bus_info": base_types.NULLABLE_STRING,
"offloading_modes": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"state": base_types.NULLABLE_BOOL,
"sub": {
"$ref": "#/items/properties/offloading_modes"
}
}
}
},
"pxe": {"type": "boolean"},
"interface_properties": {
"type": "object",
"properties": {
"sriov": {
"type": "object",
"properties": {
"enabled": base_types.NULLABLE_BOOL,
"available": {"type": "boolean"},
"sriov_numvfs":
base_types.NULLABLE_NON_NEGATIVE_INTEGER,
"sriov_totalvfs": base_types.NON_NEGATIVE_INTEGER,
"pci_id": {"type": "string"},
"physnet": {"type": "string"}
}
}
}
}
}
}
}

View File

@ -65,7 +65,6 @@ single_schema = {
}
}
}
},
"pxe": {"type": "boolean"}

View File

@ -18,6 +18,7 @@ from oslo_serialization import jsonutils
import six
from nailgun.api.v1.validators.base import BasicValidator
from nailgun.api.v1.validators.json_schema import iface_schema
from nailgun.api.v1.validators.json_schema.network_template import \
NETWORK_TEMPLATE
from nailgun.api.v1.validators.json_schema import networks
@ -281,6 +282,8 @@ class NeutronNetworkConfigurationValidator(NetworkConfigurationValidator):
class NetAssignmentValidator(BasicValidator):
single_schema = iface_schema.INTERFACES
@classmethod
def validate(cls, node):
if not isinstance(node, dict):
@ -300,7 +303,6 @@ class NetAssignmentValidator(BasicValidator):
node['id']),
log_message=True
)
net_ids = set()
for iface in node['interfaces']:
if not isinstance(iface, dict):

View File

@ -869,3 +869,57 @@ class TestHandlers(BaseIntegrationTest):
"Node '{0}' interface '{1}': '8' virtual functions was"
"requested but just '0' are available".format(
self.env.nodes[0].id, nics[0]['name']))
def test_set_sriov_numvfs_failed_negative_value(self):
self.env.create(
nodes_kwargs=[{"api": True}]
)
resp = self.app.get(
reverse('NodeNICsHandler',
kwargs={'node_id': self.env.nodes[0].id}),
headers=self.default_headers)
self.assertEqual(resp.status_code, 200)
nics = resp.json_body
sriov = nics[0]['interface_properties']['sriov']
sriov['sriov_numvfs'] = -40
resp = self.app.put(
reverse("NodeNICsHandler",
kwargs={"node_id": self.env.nodes[0].id}),
jsonutils.dumps(nics),
expect_errors=True,
headers=self.default_headers)
self.assertEqual(resp.status_code, 400)
self.assertIn(
"-40 is not valid under any of the given schemas",
resp.json_body['message']
)
def test_set_sriov_numvfs_failed_float_value(self):
self.env.create(
nodes_kwargs=[{"api": True}]
)
resp = self.app.get(
reverse('NodeNICsHandler',
kwargs={'node_id': self.env.nodes[0].id}),
headers=self.default_headers)
self.assertEqual(resp.status_code, 200)
nics = resp.json_body
sriov = nics[0]['interface_properties']['sriov']
sriov['sriov_numvfs'] = 2.5
resp = self.app.put(
reverse("NodeNICsHandler",
kwargs={"node_id": self.env.nodes[0].id}),
jsonutils.dumps(nics),
expect_errors=True,
headers=self.default_headers)
self.assertEqual(resp.status_code, 400)
self.assertIn(
"2.5 is not valid under any of the given schemas",
resp.json_body['message']
)

View File

@ -29,7 +29,7 @@ class TestIpAddrValidator(base.BaseUnitTest):
self.create_data = {
'ip_addr': "192.168.0.15",
'network': -1,
'network': 1,
'vip_name': 'test',
'is_user_defined': True
}