Merge "Check for valid flavor on cluster create"
This commit is contained in:
commit
ade56aca89
1
AUTHORS
1
AUTHORS
|
@ -10,6 +10,7 @@ Matthew Farrellee <matt@redhat.com>
|
|||
Nadya Privalova <nprivalova@mirantis.com>
|
||||
Nikita Konovalov <nkonovalov@mirantis.com>
|
||||
Nikolay Mahotkin <nmakhotkin@mirantis.com>
|
||||
Nirmal Ranganathan <rnirmal@gmail.com>
|
||||
Ruslan Kamaldinov <rkamaldinov@mirantis.com>
|
||||
Sergey Lukjanov <slukjanov@mirantis.com>
|
||||
Sergey Reshetnyak <sreshetniak@mirantis.com>
|
||||
|
|
|
@ -91,7 +91,12 @@ def check_node_group_basic_fields(plugin_name, hadoop_version, ng,
|
|||
plugin_configs=None):
|
||||
|
||||
if ng.get('node_group_template_id'):
|
||||
check_node_group_template_exists(ng['node_group_template_id'])
|
||||
ng_tmpl_id = ng['node_group_template_id']
|
||||
check_node_group_template_exists(ng_tmpl_id)
|
||||
ng_tmpl = api.get_node_group_template(ng_tmpl_id).to_wrapped_dict()
|
||||
check_node_group_basic_fields(plugin_name, hadoop_version,
|
||||
ng_tmpl['node_group_template'],
|
||||
plugin_configs)
|
||||
|
||||
if ng.get('node_configs'):
|
||||
check_node_group_configs(plugin_name, hadoop_version,
|
||||
|
@ -167,8 +172,16 @@ def check_cluster_template_exists(cluster_template_id):
|
|||
" doesn't exist" % cluster_template_id)
|
||||
|
||||
|
||||
def check_node_groups_in_cluster_templates(plugin_name, hadoop_version,
|
||||
cluster_template_id):
|
||||
c_t = api.get_cluster_template(id=cluster_template_id)
|
||||
n_groups = c_t.to_wrapped_dict()['cluster_template']['node_groups']
|
||||
for node_group in n_groups:
|
||||
check_node_group_basic_fields(plugin_name, hadoop_version, node_group)
|
||||
|
||||
## NodeGroup templates related checks
|
||||
|
||||
|
||||
def check_node_group_template_unique_name(name):
|
||||
if name in [t.name for t in api.get_node_group_templates()]:
|
||||
raise ex.NameAlreadyExistsException("NodeGroup template with name '%s'"
|
||||
|
|
|
@ -42,7 +42,12 @@ def check_cluster_create(data, **kwargs):
|
|||
b.check_plugin_supports_version(data['plugin_name'],
|
||||
data['hadoop_version'])
|
||||
if data.get('cluster_template_id'):
|
||||
b.check_cluster_template_exists(data['cluster_template_id'])
|
||||
ct_id = data['cluster_template_id']
|
||||
b.check_cluster_template_exists(ct_id)
|
||||
if not data.get('node_groups'):
|
||||
b.check_node_groups_in_cluster_templates(data['plugin_name'],
|
||||
data['hadoop_version'],
|
||||
ct_id)
|
||||
|
||||
if data.get('user_keypair_id'):
|
||||
b.check_keypair_exists(data['user_keypair_id'])
|
||||
|
|
|
@ -13,8 +13,13 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import mock
|
||||
|
||||
from savanna import context
|
||||
from savanna import exceptions
|
||||
from savanna.service import api
|
||||
from savanna.service.validations import clusters as c
|
||||
from savanna.tests.unit import base
|
||||
from savanna.tests.unit.service.validation import utils as u
|
||||
|
||||
|
||||
|
@ -165,3 +170,186 @@ class TestClusterCreateValidation(u.ValidationTestCase):
|
|||
|
||||
def test_cluster_create_v_default_image_required_tags(self):
|
||||
self._assert_cluster_default_image_tags_validation()
|
||||
|
||||
|
||||
class TestClusterCreateFlavorValidation(base.DbTestCase):
|
||||
"""Tests for valid flavor on cluster create.
|
||||
|
||||
The following use cases for flavors during cluster create are validated:
|
||||
* Flavor id defined in a node group template and used in a cluster
|
||||
template.
|
||||
* Flavor id defined in node groups on cluster create.
|
||||
* Both node groups and cluster template defined on cluster create.
|
||||
* Node groups with node group template defined on cluster create.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestClusterCreateFlavorValidation, self).setUp()
|
||||
context.current().tenant_id = '1234'
|
||||
modules = [
|
||||
"savanna.service.validations.base.check_plugin_name_exists",
|
||||
"savanna.service.validations.base.check_plugin_supports_version",
|
||||
"savanna.service.validations.base._get_plugin_configs",
|
||||
"savanna.service.validations.base.check_node_processes",
|
||||
"savanna.utils.openstack.nova.client",
|
||||
]
|
||||
self.patchers = []
|
||||
for module in modules:
|
||||
patch = mock.patch(module)
|
||||
patch.start()
|
||||
self.patchers.append(patch)
|
||||
|
||||
nova_p = mock.patch("savanna.utils.openstack.nova.client")
|
||||
nova = nova_p.start()
|
||||
self.patchers.append(nova_p)
|
||||
nova().flavors.get.side_effect = u._get_flavor
|
||||
|
||||
def tearDown(self):
|
||||
u.stop_patch(self.patchers)
|
||||
super(TestClusterCreateFlavorValidation, self).tearDown()
|
||||
|
||||
def _create_node_group_template(self, flavor='42'):
|
||||
ng_tmpl = {
|
||||
"plugin_name": "vanilla",
|
||||
"hadoop_version": "1.1.2",
|
||||
"node_processes": ["namenode"],
|
||||
"name": "master",
|
||||
"flavor_id": flavor
|
||||
}
|
||||
return api.create_node_group_template(ng_tmpl).id
|
||||
|
||||
def _create_cluster_template(self, ng_id):
|
||||
cl_tmpl = {
|
||||
"plugin_name": "vanilla",
|
||||
"hadoop_version": "1.1.2",
|
||||
"node_groups": [
|
||||
{"name": "master",
|
||||
"count": 1,
|
||||
"node_group_template_id": "%s" % ng_id}
|
||||
],
|
||||
"name": "test-template"
|
||||
}
|
||||
return api.create_cluster_template(cl_tmpl).id
|
||||
|
||||
def test_cluster_create_v_correct_flavor(self):
|
||||
ng_id = self._create_node_group_template(flavor='42')
|
||||
ctmpl_id = self._create_cluster_template(ng_id)
|
||||
|
||||
data = {
|
||||
"name": "testname",
|
||||
"plugin_name": "vanilla",
|
||||
"hadoop_version": "1.1.2",
|
||||
"cluster_template_id": '%s' % ctmpl_id
|
||||
}
|
||||
c.check_cluster_create(data)
|
||||
|
||||
data1 = {
|
||||
"name": "testwithnodegroups",
|
||||
"plugin_name": "vanilla",
|
||||
"hadoop_version": "1.1.2",
|
||||
"node_groups": [
|
||||
{
|
||||
"name": "allinone",
|
||||
"count": 1,
|
||||
"flavor_id": "42",
|
||||
"node_processes": [
|
||||
"namenode",
|
||||
"jobtracker",
|
||||
"datanode",
|
||||
"tasktracker"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
c.check_cluster_create(data1)
|
||||
|
||||
def test_cluster_create_v_invalid_flavor(self):
|
||||
ng_id = self._create_node_group_template(flavor='10')
|
||||
ctmpl_id = self._create_cluster_template(ng_id)
|
||||
|
||||
data = {
|
||||
"name": "testname",
|
||||
"plugin_name": "vanilla",
|
||||
"hadoop_version": "1.1.2",
|
||||
"cluster_template_id": '%s' % ctmpl_id
|
||||
}
|
||||
data1 = {
|
||||
"name": "testwithnodegroups",
|
||||
"plugin_name": "vanilla",
|
||||
"hadoop_version": "1.1.2",
|
||||
"node_groups": [
|
||||
{
|
||||
"name": "allinone",
|
||||
"count": 1,
|
||||
"flavor_id": "10",
|
||||
"node_processes": [
|
||||
"namenode",
|
||||
"jobtracker",
|
||||
"datanode",
|
||||
"tasktracker"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
for values in [data, data1]:
|
||||
with self.assertRaises(exceptions.InvalidException):
|
||||
try:
|
||||
c.check_cluster_create(values)
|
||||
except exceptions.InvalidException as e:
|
||||
self.assertEqual("Requested flavor '10' not found",
|
||||
e.message)
|
||||
raise e
|
||||
|
||||
def test_cluster_create_cluster_tmpl_node_group_mixin(self):
|
||||
ng_id = self._create_node_group_template(flavor='10')
|
||||
ctmpl_id = self._create_cluster_template(ng_id)
|
||||
|
||||
data = {
|
||||
"name": "testtmplnodegroups",
|
||||
"plugin_name": "vanilla",
|
||||
"hadoop_version": "1.1.2",
|
||||
"cluster_template_id": '%s' % ctmpl_id,
|
||||
"node_groups": [
|
||||
{
|
||||
"name": "allinone",
|
||||
"count": 1,
|
||||
"flavor_id": "42",
|
||||
"node_processes": [
|
||||
"namenode",
|
||||
"jobtracker",
|
||||
"datanode",
|
||||
"tasktracker"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
c.check_cluster_create(data)
|
||||
|
||||
def test_cluster_create_node_group_tmpl_mixin(self):
|
||||
ng_id = self._create_node_group_template(flavor='23')
|
||||
data = {
|
||||
"name": "testtmplnodegroups",
|
||||
"plugin_name": "vanilla",
|
||||
"hadoop_version": "1.1.2",
|
||||
"node_groups": [
|
||||
{
|
||||
"node_group_template_id": '%s' % ng_id,
|
||||
"name": "allinone",
|
||||
"count": 1,
|
||||
"flavor_id": "42",
|
||||
"node_processes": [
|
||||
"namenode",
|
||||
"jobtracker",
|
||||
"datanode",
|
||||
"tasktracker"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
with self.assertRaises(exceptions.InvalidException):
|
||||
try:
|
||||
c.check_cluster_create(data)
|
||||
except exceptions.InvalidException as e:
|
||||
self.assertEqual("Requested flavor '23' not found",
|
||||
e.message)
|
||||
raise e
|
||||
|
|
|
@ -53,12 +53,12 @@ def _get_plugin(name):
|
|||
|
||||
|
||||
def _get_keypair(name):
|
||||
if name is not "test_keypair":
|
||||
if name != "test_keypair":
|
||||
raise nova_ex.NotFound("")
|
||||
|
||||
|
||||
def _get_flavor(flavor_id):
|
||||
if flavor_id is not "42":
|
||||
if flavor_id != "42":
|
||||
raise nova_ex.NotFound("")
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue