Merge "Use jsonschema to validate efficacy indicators"
This commit is contained in:
commit
595cd1d435
@ -126,7 +126,7 @@ class BaseAction(loadable.Loadable):
|
||||
|
||||
:returns: A schema declaring the input parameters this action should be
|
||||
provided along with their respective constraints
|
||||
:rtype: :py:class:`voluptuous.Schema` instance
|
||||
:rtype: :py:class:`jsonschema.Schema` instance
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
@ -24,10 +24,10 @@ calculating its :ref:`global efficacy <efficacy_definition>`.
|
||||
"""
|
||||
|
||||
import abc
|
||||
import jsonschema
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
import six
|
||||
import voluptuous
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
@ -65,17 +65,21 @@ class EfficacySpecification(object):
|
||||
@property
|
||||
def schema(self):
|
||||
"""Combined schema from the schema of the indicators"""
|
||||
schema = voluptuous.Schema({}, required=True)
|
||||
schema = {
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
"required": []
|
||||
}
|
||||
for indicator in self.indicators_specs:
|
||||
key_constraint = (voluptuous.Required
|
||||
if indicator.required else voluptuous.Optional)
|
||||
schema = schema.extend(
|
||||
{key_constraint(indicator.name): indicator.schema.schema})
|
||||
|
||||
schema["properties"][indicator.name] = indicator.schema
|
||||
schema["required"].append(indicator.name)
|
||||
return schema
|
||||
|
||||
def validate_efficacy_indicators(self, indicators_map):
|
||||
return self.schema(indicators_map)
|
||||
if indicators_map:
|
||||
jsonschema.validate(indicators_map, self.schema)
|
||||
else:
|
||||
True
|
||||
|
||||
def get_indicators_specs_dicts(self):
|
||||
return [indicator.to_dict()
|
||||
|
@ -15,10 +15,13 @@
|
||||
# limitations under the License.
|
||||
|
||||
import abc
|
||||
import jsonschema
|
||||
from jsonschema import SchemaError
|
||||
from jsonschema import ValidationError
|
||||
import six
|
||||
|
||||
from oslo_log import log
|
||||
import voluptuous
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from watcher._i18n import _
|
||||
from watcher.common import exception
|
||||
@ -37,10 +40,9 @@ class IndicatorSpecification(object):
|
||||
|
||||
@abc.abstractproperty
|
||||
def schema(self):
|
||||
"""Schema used to validate the indicator value
|
||||
"""JsonSchema used to validate the indicator value
|
||||
|
||||
:return: A Voplutuous Schema
|
||||
:rtype: :py:class:`.voluptuous.Schema` instance
|
||||
:return: A Schema
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
@ -54,7 +56,10 @@ class IndicatorSpecification(object):
|
||||
value = None
|
||||
try:
|
||||
value = getattr(solution, indicator.name)
|
||||
indicator.schema(value)
|
||||
jsonschema.validate(value, cls.schema)
|
||||
except (SchemaError, ValidationError) as exc:
|
||||
LOG.exception(exc)
|
||||
raise exc
|
||||
except Exception as exc:
|
||||
LOG.exception(exc)
|
||||
raise exception.InvalidIndicatorValue(
|
||||
@ -65,7 +70,7 @@ class IndicatorSpecification(object):
|
||||
"name": self.name,
|
||||
"description": self.description,
|
||||
"unit": self.unit,
|
||||
"schema": str(self.schema.schema) if self.schema else None,
|
||||
"schema": jsonutils.dumps(self.schema) if self.schema else None,
|
||||
}
|
||||
|
||||
def __str__(self):
|
||||
@ -82,8 +87,10 @@ class ComputeNodesCount(IndicatorSpecification):
|
||||
|
||||
@property
|
||||
def schema(self):
|
||||
return voluptuous.Schema(
|
||||
voluptuous.Range(min=0), required=True)
|
||||
return {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
|
||||
|
||||
class ReleasedComputeNodesCount(IndicatorSpecification):
|
||||
@ -96,8 +103,10 @@ class ReleasedComputeNodesCount(IndicatorSpecification):
|
||||
|
||||
@property
|
||||
def schema(self):
|
||||
return voluptuous.Schema(
|
||||
voluptuous.Range(min=0), required=True)
|
||||
return {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
|
||||
|
||||
class InstanceMigrationsCount(IndicatorSpecification):
|
||||
@ -110,8 +119,10 @@ class InstanceMigrationsCount(IndicatorSpecification):
|
||||
|
||||
@property
|
||||
def schema(self):
|
||||
return voluptuous.Schema(
|
||||
voluptuous.Range(min=0), required=True)
|
||||
return {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
|
||||
|
||||
class LiveInstanceMigrateCount(IndicatorSpecification):
|
||||
@ -124,8 +135,10 @@ class LiveInstanceMigrateCount(IndicatorSpecification):
|
||||
|
||||
@property
|
||||
def schema(self):
|
||||
return voluptuous.Schema(
|
||||
voluptuous.Range(min=0), required=True)
|
||||
return {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
|
||||
|
||||
class PlannedLiveInstanceMigrateCount(IndicatorSpecification):
|
||||
@ -138,8 +151,10 @@ class PlannedLiveInstanceMigrateCount(IndicatorSpecification):
|
||||
|
||||
@property
|
||||
def schema(self):
|
||||
return voluptuous.Schema(
|
||||
voluptuous.Range(min=0), required=True)
|
||||
return {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
|
||||
|
||||
class ColdInstanceMigrateCount(IndicatorSpecification):
|
||||
@ -152,8 +167,10 @@ class ColdInstanceMigrateCount(IndicatorSpecification):
|
||||
|
||||
@property
|
||||
def schema(self):
|
||||
return voluptuous.Schema(
|
||||
voluptuous.Range(min=0), required=True)
|
||||
return {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
|
||||
|
||||
class PlannedColdInstanceMigrateCount(IndicatorSpecification):
|
||||
@ -166,8 +183,10 @@ class PlannedColdInstanceMigrateCount(IndicatorSpecification):
|
||||
|
||||
@property
|
||||
def schema(self):
|
||||
return voluptuous.Schema(
|
||||
voluptuous.Range(min=0), required=True)
|
||||
return {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
|
||||
|
||||
class VolumeMigrateCount(IndicatorSpecification):
|
||||
@ -180,8 +199,10 @@ class VolumeMigrateCount(IndicatorSpecification):
|
||||
|
||||
@property
|
||||
def schema(self):
|
||||
return voluptuous.Schema(
|
||||
voluptuous.Range(min=0), required=True)
|
||||
return {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
|
||||
|
||||
class PlannedVolumeMigrateCount(IndicatorSpecification):
|
||||
@ -195,8 +216,10 @@ class PlannedVolumeMigrateCount(IndicatorSpecification):
|
||||
|
||||
@property
|
||||
def schema(self):
|
||||
return voluptuous.Schema(
|
||||
voluptuous.Range(min=0), required=True)
|
||||
return {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
|
||||
|
||||
class VolumeUpdateCount(IndicatorSpecification):
|
||||
@ -210,8 +233,10 @@ class VolumeUpdateCount(IndicatorSpecification):
|
||||
|
||||
@property
|
||||
def schema(self):
|
||||
return voluptuous.Schema(
|
||||
voluptuous.Range(min=0), required=True)
|
||||
return {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
|
||||
|
||||
class PlannedVolumeUpdateCount(IndicatorSpecification):
|
||||
@ -225,5 +250,7 @@ class PlannedVolumeUpdateCount(IndicatorSpecification):
|
||||
|
||||
@property
|
||||
def schema(self):
|
||||
return voluptuous.Schema(
|
||||
voluptuous.Range(min=0), required=True)
|
||||
return {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
|
@ -14,8 +14,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import voluptuous
|
||||
|
||||
from watcher.decision_engine.goal import base as base_goal
|
||||
from watcher.decision_engine.goal.efficacy import base as efficacy_base
|
||||
from watcher.decision_engine.goal.efficacy import indicators
|
||||
@ -55,8 +53,10 @@ class DummyIndicator(indicators.IndicatorSpecification):
|
||||
|
||||
@property
|
||||
def schema(self):
|
||||
return voluptuous.Schema(
|
||||
voluptuous.Range(min=0, max=100), required=True)
|
||||
return {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
|
||||
|
||||
class DummySpec1(efficacy_base.EfficacySpecification):
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
import mock
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from watcher.common import context
|
||||
from watcher.common import utils
|
||||
from watcher.decision_engine.loading import default
|
||||
@ -451,8 +453,7 @@ class TestSyncer(base.DbTestCase):
|
||||
|
||||
dummy_1_spec = [
|
||||
{'description': 'Dummy indicator', 'name': 'dummy',
|
||||
'schema': 'Range(min=0, max=100, min_included=True, '
|
||||
'max_included=True, msg=None)',
|
||||
'schema': jsonutils.dumps({'minimum': 0, 'type': 'integer'}),
|
||||
'unit': '%'}]
|
||||
dummy_2_spec = []
|
||||
self.assertEqual(
|
||||
|
Loading…
Reference in New Issue
Block a user