diff --git a/magnum/api/controllers/v1/baymodel.py b/magnum/api/controllers/v1/baymodel.py index 41d3b2bb28..a6068a34ba 100644 --- a/magnum/api/controllers/v1/baymodel.py +++ b/magnum/api/controllers/v1/baymodel.py @@ -120,8 +120,7 @@ class BayModel(base.APIBase): public = wsme.wsattr(types.boolean, default=False) """Indicates whether the Baymodel is public or not.""" - server_type = wsme.wsattr(wtypes.StringType(min_length=1, - max_length=255), + server_type = wsme.wsattr(wtypes.Enum(str, *fields.ServerType.ALL), default='vm') """Server type for this bay model""" @@ -319,6 +318,7 @@ class BayModelsController(base.Controller): return BayModel.convert_with_links(baymodel) @expose.expose(BayModel, body=BayModel, status_code=201) + @validation.enforce_server_type() @validation.enforce_network_driver_types_create() @validation.enforce_volume_driver_types_create() @validation.enforce_volume_storage_size_create() diff --git a/magnum/api/controllers/v1/cluster_template.py b/magnum/api/controllers/v1/cluster_template.py index bd0325d310..37d760a08d 100644 --- a/magnum/api/controllers/v1/cluster_template.py +++ b/magnum/api/controllers/v1/cluster_template.py @@ -121,8 +121,7 @@ class ClusterTemplate(base.APIBase): public = wsme.wsattr(types.boolean, default=False) """Indicates whether the ClusterTemplate is public or not.""" - server_type = wsme.wsattr(wtypes.StringType(min_length=1, - max_length=255), + server_type = wsme.wsattr(wtypes.Enum(str, *fields.ServerType.ALL), default='vm') """Server type for this ClusterTemplate """ @@ -327,6 +326,7 @@ class ClusterTemplatesController(base.Controller): return ClusterTemplate.convert_with_links(cluster_template) @expose.expose(ClusterTemplate, body=ClusterTemplate, status_code=201) + @validation.enforce_server_type() @validation.enforce_network_driver_types_create() @validation.enforce_volume_driver_types_create() @validation.enforce_volume_storage_size_create() diff --git a/magnum/api/validation.py b/magnum/api/validation.py index 8296a3e5eb..abc1496c5e 100644 --- a/magnum/api/validation.py +++ b/magnum/api/validation.py @@ -137,6 +137,21 @@ def _enforce_network_driver_types(cluster_template): validator.validate_network_driver(cluster_template.network_driver) +def enforce_server_type(): + @decorator.decorator + def wrapper(func, *args, **kwargs): + cluster_template = args[1] + _enforce_server_type(cluster_template) + return func(*args, **kwargs) + + return wrapper + + +def _enforce_server_type(cluster_template): + validator = Validator.get_coe_validator(cluster_template.coe) + validator.validate_server_type(cluster_template.server_type) + + def enforce_volume_driver_types_create(): @decorator.decorator def wrapper(func, *args, **kwargs): @@ -261,10 +276,26 @@ class Validator(object): 'supported_volume_driver': '/'.join( cls.supported_volume_driver + ['unspecified'])}) + @classmethod + def validate_server_type(cls, server_type): + cls._validate_server_type(server_type) + + @classmethod + def _validate_server_type(cls, server_type): + """Confirm that server type is supported by Magnum for this COE.""" + if server_type not in cls.supported_server_types: + raise exception.InvalidParameterValue(_( + 'Server type %(server_type)s is not supported, ' + 'expecting a %(supported_server_types)s server type.') % { + 'server_type': server_type, + 'supported_server_types': '/'.join( + cls.supported_server_types + ['unspecified'])}) + class K8sValidator(Validator): supported_network_drivers = ['flannel'] + supported_server_types = ['vm', 'bm'] allowed_network_drivers = ( cfg.CONF.cluster_template.kubernetes_allowed_network_drivers) default_network_driver = ( @@ -276,6 +307,7 @@ class K8sValidator(Validator): class SwarmValidator(Validator): supported_network_drivers = ['docker', 'flannel'] + supported_server_types = ['vm', 'bm'] allowed_network_drivers = (cfg.CONF.cluster_template. swarm_allowed_network_drivers) default_network_driver = (cfg.CONF.cluster_template. @@ -287,6 +319,7 @@ class SwarmValidator(Validator): class MesosValidator(Validator): supported_network_drivers = ['docker'] + supported_server_types = ['vm', 'bm'] allowed_network_drivers = (cfg.CONF.cluster_template. mesos_allowed_network_drivers) default_network_driver = (cfg.CONF.cluster_template. diff --git a/magnum/objects/fields.py b/magnum/objects/fields.py index ed48a9d45f..92dd30e2f4 100644 --- a/magnum/objects/fields.py +++ b/magnum/objects/fields.py @@ -83,6 +83,18 @@ class DockerStorageDriver(fields.Enum): valid_values=DockerStorageDriver.ALL) +class ServerType(fields.Enum): + ALL = ( + VM, BM, + ) = ( + 'vm', 'bm', + ) + + def __init__(self): + super(ServerType, self).__init__( + valid_values=ServerType.ALL) + + class MagnumServiceState(fields.Enum): ALL = ( up, down @@ -133,3 +145,7 @@ class ClusterTypeField(fields.BaseEnumField): class DockerStorageDriverField(fields.BaseEnumField): AUTO_TYPE = DockerStorageDriver() + + +class ServerTypeField(fields.BaseEnumField): + AUTO_TYPE = ServerType() diff --git a/magnum/tests/unit/api/test_validation.py b/magnum/tests/unit/api/test_validation.py index da170065e1..428c4d9ba0 100644 --- a/magnum/tests/unit/api/test_validation.py +++ b/magnum/tests/unit/api/test_validation.py @@ -350,6 +350,39 @@ class TestValidation(base.BaseTestCase): volume_driver_type='type', assert_raised=True) + def _test_enforce_server_type( + self, + server_type, + coe='kubernetes', + assert_raised=False): + + @v.enforce_server_type() + def test(self, cluster_template): + pass + + cluster_template = obj_utils.get_test_cluster_template( + {}, name='test_cluster_template', coe=coe, + server_type=server_type) + + if assert_raised: + self.assertRaises(exception.InvalidParameterValue, + test, self, cluster_template) + else: + test(self, cluster_template) + + def test_enforce_server_type_valid_vm(self): + self._test_enforce_server_type( + server_type='vm') + + def test_enforce_server_type_valid_bm(self): + self._test_enforce_server_type( + server_type='bm') + + def test_enforce_server_type_invalid(self): + self._test_enforce_server_type( + server_type='invalid', + assert_raised=True) + @mock.patch('pecan.request') @mock.patch('magnum.api.utils.get_resource') def _test_enforce_volume_driver_types_update( diff --git a/magnum/tests/unit/objects/test_fields.py b/magnum/tests/unit/objects/test_fields.py index ebc0b34068..89b7f1ec13 100644 --- a/magnum/tests/unit/objects/test_fields.py +++ b/magnum/tests/unit/objects/test_fields.py @@ -107,3 +107,22 @@ class TestMagnumServiceBinary(test_fields.TestField): def test_stringify_invalid(self): self.assertRaises(ValueError, self.field.stringify, 'invalid') + + +class TestServerType(test_fields.TestField): + def setUp(self): + super(TestServerType, self).setUp() + self.field = fields.ServerTypeField() + self.coerce_good_values = [('vm', 'vm'), + ('bm', 'bm'), ] + self.coerce_bad_values = ['invalid'] + + self.to_primitive_values = self.coerce_good_values[0:1] + self.from_primitive_values = self.coerce_good_values[0:1] + + def test_stringify(self): + self.assertEqual("'vm'", + self.field.stringify('vm')) + + def test_stringify_invalid(self): + self.assertRaises(ValueError, self.field.stringify, 'invalid')