Merge "Replace voluptuous with JSONSchema to validate migration action"
This commit is contained in:
commit
986ba9872f
@ -6,6 +6,7 @@ apscheduler # MIT License
|
|||||||
enum34;python_version=='2.7' or python_version=='2.6' or python_version=='3.3' # BSD
|
enum34;python_version=='2.7' or python_version=='2.6' or python_version=='3.3' # BSD
|
||||||
jsonpatch>=1.1 # BSD
|
jsonpatch>=1.1 # BSD
|
||||||
keystoneauth1>=2.21.0 # Apache-2.0
|
keystoneauth1>=2.21.0 # Apache-2.0
|
||||||
|
jsonschema!=2.5.0,<3.0.0,>=2.0.0 # MIT
|
||||||
keystonemiddleware>=4.12.0 # Apache-2.0
|
keystonemiddleware>=4.12.0 # Apache-2.0
|
||||||
lxml!=3.7.0,>=2.3 # BSD
|
lxml!=3.7.0,>=2.3 # BSD
|
||||||
oslo.concurrency>=3.8.0 # Apache-2.0
|
oslo.concurrency>=3.8.0 # Apache-2.0
|
||||||
|
@ -17,15 +17,13 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
from oslo_log import log
|
|
||||||
import six
|
|
||||||
import voluptuous
|
|
||||||
|
|
||||||
|
import jsonschema
|
||||||
|
from oslo_log import log
|
||||||
from watcher._i18n import _
|
from watcher._i18n import _
|
||||||
from watcher.applier.actions import base
|
from watcher.applier.actions import base
|
||||||
from watcher.common import exception
|
from watcher.common import exception
|
||||||
from watcher.common import nova_helper
|
from watcher.common import nova_helper
|
||||||
from watcher.common import utils
|
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
@ -62,28 +60,42 @@ class Migrate(base.BaseAction):
|
|||||||
DESTINATION_NODE = 'destination_node'
|
DESTINATION_NODE = 'destination_node'
|
||||||
SOURCE_NODE = 'source_node'
|
SOURCE_NODE = 'source_node'
|
||||||
|
|
||||||
def check_resource_id(self, value):
|
|
||||||
if (value is not None and
|
|
||||||
len(value) > 0 and not
|
|
||||||
utils.is_uuid_like(value)):
|
|
||||||
raise voluptuous.Invalid(_("The parameter "
|
|
||||||
"resource_id is invalid."))
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def schema(self):
|
def schema(self):
|
||||||
return voluptuous.Schema({
|
return {
|
||||||
voluptuous.Required(self.RESOURCE_ID): self.check_resource_id,
|
'type': 'object',
|
||||||
voluptuous.Required(
|
'properties': {
|
||||||
self.MIGRATION_TYPE, default=self.LIVE_MIGRATION):
|
'destination_node': {
|
||||||
voluptuous.Any(
|
'type': 'string',
|
||||||
*[self.LIVE_MIGRATION, self.COLD_MIGRATION]),
|
"minLength": 1
|
||||||
voluptuous.Required(self.DESTINATION_NODE):
|
},
|
||||||
voluptuous.All(voluptuous.Any(*six.string_types),
|
'migration_type': {
|
||||||
voluptuous.Length(min=1)),
|
'type': 'string',
|
||||||
voluptuous.Required(self.SOURCE_NODE):
|
"enum": ["live", "cold"]
|
||||||
voluptuous.All(voluptuous.Any(*six.string_types),
|
},
|
||||||
voluptuous.Length(min=1)),
|
'resource_id': {
|
||||||
})
|
'type': 'string',
|
||||||
|
"minlength": 1,
|
||||||
|
"pattern": ("^([a-fA-F0-9]){8}-([a-fA-F0-9]){4}-"
|
||||||
|
"([a-fA-F0-9]){4}-([a-fA-F0-9]){4}-"
|
||||||
|
"([a-fA-F0-9]){12}$")
|
||||||
|
},
|
||||||
|
'source_node': {
|
||||||
|
'type': 'string',
|
||||||
|
"minLength": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'required': ['destination_node', 'migration_type',
|
||||||
|
'resource_id', 'source_node'],
|
||||||
|
'additionalProperties': False,
|
||||||
|
}
|
||||||
|
|
||||||
|
def validate_parameters(self):
|
||||||
|
try:
|
||||||
|
jsonschema.validate(self.input_parameters, self.schema)
|
||||||
|
return True
|
||||||
|
except jsonschema.ValidationError as e:
|
||||||
|
raise e
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def instance_uuid(self):
|
def instance_uuid(self):
|
||||||
@ -137,7 +149,6 @@ class Migrate(base.BaseAction):
|
|||||||
LOG.critical("Unexpected error occurred. Migration failed for "
|
LOG.critical("Unexpected error occurred. Migration failed for "
|
||||||
"instance %s. Leaving instance on previous "
|
"instance %s. Leaving instance on previous "
|
||||||
"host.", self.instance_uuid)
|
"host.", self.instance_uuid)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def migrate(self, destination):
|
def migrate(self, destination):
|
||||||
|
@ -15,8 +15,9 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
|
||||||
|
import jsonschema
|
||||||
import mock
|
import mock
|
||||||
import voluptuous
|
|
||||||
|
|
||||||
from watcher.applier.actions import base as baction
|
from watcher.applier.actions import base as baction
|
||||||
from watcher.applier.actions import migration
|
from watcher.applier.actions import migration
|
||||||
@ -93,13 +94,8 @@ class TestMigration(base.TestCase):
|
|||||||
'source_node': None,
|
'source_node': None,
|
||||||
'destination_node': None}
|
'destination_node': None}
|
||||||
self.action.input_parameters = parameters
|
self.action.input_parameters = parameters
|
||||||
exc = self.assertRaises(
|
self.assertRaises(jsonschema.ValidationError,
|
||||||
voluptuous.MultipleInvalid, self.action.validate_parameters)
|
self.action.validate_parameters)
|
||||||
self.assertEqual(
|
|
||||||
sorted([(['migration_type'], voluptuous.ScalarInvalid),
|
|
||||||
(['source_node'], voluptuous.TypeInvalid),
|
|
||||||
(['destination_node'], voluptuous.TypeInvalid)]),
|
|
||||||
sorted([(e.path, type(e)) for e in exc.errors]))
|
|
||||||
|
|
||||||
def test_parameters_exception_migration_type(self):
|
def test_parameters_exception_migration_type(self):
|
||||||
parameters = {baction.BaseAction.RESOURCE_ID:
|
parameters = {baction.BaseAction.RESOURCE_ID:
|
||||||
@ -108,11 +104,8 @@ class TestMigration(base.TestCase):
|
|||||||
'source_node': 'compute-2',
|
'source_node': 'compute-2',
|
||||||
'destination_node': 'compute-3'}
|
'destination_node': 'compute-3'}
|
||||||
self.action.input_parameters = parameters
|
self.action.input_parameters = parameters
|
||||||
exc = self.assertRaises(
|
self.assertRaises(jsonschema.ValidationError,
|
||||||
voluptuous.Invalid, self.action.validate_parameters)
|
self.action.validate_parameters)
|
||||||
self.assertEqual(
|
|
||||||
[(['migration_type'], voluptuous.ScalarInvalid)],
|
|
||||||
[(e.path, type(e)) for e in exc.errors])
|
|
||||||
|
|
||||||
def test_parameters_exception_source_node(self):
|
def test_parameters_exception_source_node(self):
|
||||||
parameters = {baction.BaseAction.RESOURCE_ID:
|
parameters = {baction.BaseAction.RESOURCE_ID:
|
||||||
@ -121,11 +114,8 @@ class TestMigration(base.TestCase):
|
|||||||
'source_node': None,
|
'source_node': None,
|
||||||
'destination_node': 'compute-3'}
|
'destination_node': 'compute-3'}
|
||||||
self.action.input_parameters = parameters
|
self.action.input_parameters = parameters
|
||||||
exc = self.assertRaises(
|
self.assertRaises(jsonschema.ValidationError,
|
||||||
voluptuous.MultipleInvalid, self.action.validate_parameters)
|
self.action.validate_parameters)
|
||||||
self.assertEqual(
|
|
||||||
[(['source_node'], voluptuous.TypeInvalid)],
|
|
||||||
[(e.path, type(e)) for e in exc.errors])
|
|
||||||
|
|
||||||
def test_parameters_exception_destination_node(self):
|
def test_parameters_exception_destination_node(self):
|
||||||
parameters = {baction.BaseAction.RESOURCE_ID:
|
parameters = {baction.BaseAction.RESOURCE_ID:
|
||||||
@ -134,11 +124,8 @@ class TestMigration(base.TestCase):
|
|||||||
'source_node': 'compute-1',
|
'source_node': 'compute-1',
|
||||||
'destination_node': None}
|
'destination_node': None}
|
||||||
self.action.input_parameters = parameters
|
self.action.input_parameters = parameters
|
||||||
exc = self.assertRaises(
|
self.assertRaises(jsonschema.ValidationError,
|
||||||
voluptuous.MultipleInvalid, self.action.validate_parameters)
|
self.action.validate_parameters)
|
||||||
self.assertEqual(
|
|
||||||
[(['destination_node'], voluptuous.TypeInvalid)],
|
|
||||||
[(e.path, type(e)) for e in exc.errors])
|
|
||||||
|
|
||||||
def test_parameters_exception_resource_id(self):
|
def test_parameters_exception_resource_id(self):
|
||||||
parameters = {baction.BaseAction.RESOURCE_ID: "EFEF",
|
parameters = {baction.BaseAction.RESOURCE_ID: "EFEF",
|
||||||
@ -146,11 +133,8 @@ class TestMigration(base.TestCase):
|
|||||||
'source_node': 'compute-2',
|
'source_node': 'compute-2',
|
||||||
'destination_node': 'compute-3'}
|
'destination_node': 'compute-3'}
|
||||||
self.action.input_parameters = parameters
|
self.action.input_parameters = parameters
|
||||||
exc = self.assertRaises(
|
self.assertRaises(jsonschema.ValidationError,
|
||||||
voluptuous.MultipleInvalid, self.action.validate_parameters)
|
self.action.validate_parameters)
|
||||||
self.assertEqual(
|
|
||||||
[(['resource_id'], voluptuous.Invalid)],
|
|
||||||
[(e.path, type(e)) for e in exc.errors])
|
|
||||||
|
|
||||||
def test_migration_pre_condition(self):
|
def test_migration_pre_condition(self):
|
||||||
try:
|
try:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user