Merge "Getting correct count and attributes from database"
This commit is contained in:
commit
13faf8b889
@ -25,29 +25,80 @@ import tuskar.heat.template_tools as template_tools
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# FIXME(lsmola) mocked params for POC, remove later by real ones
|
||||
# FIXME(lsmola) this is for debugging purposes only, remove before I3
|
||||
POC_PARAMS = {'controller': 1, 'compute': 1}
|
||||
POC_PARAMS_UPDATE = {'controller': 1, 'compute': 2}
|
||||
|
||||
|
||||
def process_stack(params, create=False):
|
||||
"""Helper function for processing the stack. Given a params dict containing
|
||||
the Overcloud Roles and initialization parameters create or update the
|
||||
stack.
|
||||
def parse_counts(counts):
|
||||
"""Helper for parsing the OvercloudRoleCount object
|
||||
|
||||
:param params: Dictionary of initialization params and overcloud roles for
|
||||
heat template and initialization of stack/
|
||||
:type params: dict
|
||||
Given a list of OvercloudRoleCount objects return a dict of
|
||||
(image_name, count) in a format used for building a template.
|
||||
|
||||
:param counts: List of tuskar.api.controllers.v1.models.OvercloudRoleCount
|
||||
:type counts: list
|
||||
|
||||
:return: Dict of (image_name, count)
|
||||
:rtype: dict
|
||||
"""
|
||||
parsed_counts = {}
|
||||
for count_obj in counts:
|
||||
image_name = count_obj.overcloud_role.image_name
|
||||
count = count_obj.num_nodes
|
||||
parsed_counts[image_name] = count
|
||||
|
||||
return parsed_counts
|
||||
|
||||
|
||||
def filter_template_attributes(allowed_data, attributes):
|
||||
"""Helper filtering attributes for template
|
||||
|
||||
Given a list of allowed data and attributes, filter the attributes
|
||||
only with keys of allowed data and return filtered data.
|
||||
|
||||
:param allowed_data: Dict of allowed attributes for template returned by
|
||||
validating of template.
|
||||
:type allowed_data: dict
|
||||
|
||||
:param attributes: Dict of attributes sent from user in deploying stack
|
||||
operation
|
||||
:type attributes: Dict
|
||||
|
||||
:return: Dict of filtered attributes
|
||||
:rtype: dict
|
||||
"""
|
||||
allowed_keys = allowed_data.get("Parameters", {}).keys()
|
||||
|
||||
filtered_data = dict([(key, value) for key, value in attributes.items()
|
||||
if key in allowed_keys])
|
||||
|
||||
return filtered_data
|
||||
|
||||
|
||||
def process_stack(attributes, counts, create=False):
|
||||
"""Helper function for processing the stack.
|
||||
|
||||
Given a params dict containing the Overcloud Roles and initialization
|
||||
parameters create or update the stack.
|
||||
|
||||
:param attributes: Dictionary of initialization params and overcloud roles
|
||||
for heat template and initialization of stack
|
||||
:type attributes: dict
|
||||
|
||||
:param counts: Dictionary of counts of roles to be deployed
|
||||
:type counts: dict
|
||||
|
||||
:param create: A flag to designate if we are creating or updating the stack
|
||||
:type create: bool
|
||||
"""
|
||||
|
||||
overcloud = template_tools.merge_templates(params)
|
||||
overcloud = template_tools.merge_templates(parse_counts(counts))
|
||||
heat_client = HeatClient()
|
||||
|
||||
stack_exists = heat_client.exists_stack()
|
||||
if not heat_client.validate_template(overcloud):
|
||||
valid, allowed_data = heat_client.validate_template(overcloud)
|
||||
|
||||
if not valid:
|
||||
raise exception.InvalidHeatTemplate()
|
||||
|
||||
if stack_exists and create:
|
||||
@ -56,7 +107,13 @@ def process_stack(params, create=False):
|
||||
elif not stack_exists and not create:
|
||||
raise exception.StackNotFound()
|
||||
|
||||
res = heat_client.create_stack(overcloud, params)
|
||||
if create:
|
||||
operation = heat_client.create_stack
|
||||
else:
|
||||
operation = heat_client.update_stack
|
||||
|
||||
res = operation(overcloud,
|
||||
filter_template_attributes(allowed_data, attributes))
|
||||
|
||||
if not res:
|
||||
if create:
|
||||
@ -93,7 +150,6 @@ class OvercloudsController(rest.RestController):
|
||||
:raises: tuskar.common.exception.OvercloudExists: if an overcloud
|
||||
with the given name exists
|
||||
"""
|
||||
|
||||
LOG.debug('Creating overcloud: %s' % transfer_overcloud)
|
||||
|
||||
# Persist to the database
|
||||
@ -110,7 +166,8 @@ class OvercloudsController(rest.RestController):
|
||||
# step 2- put the right stack_id to the overcloud
|
||||
# step 3- initialize the stack
|
||||
# step 4- set the correct overcloud status
|
||||
process_stack(POC_PARAMS, create=True)
|
||||
process_stack(saved_overcloud.attributes, result.counts,
|
||||
create=True)
|
||||
|
||||
return saved_overcloud
|
||||
|
||||
@ -145,15 +202,16 @@ class OvercloudsController(rest.RestController):
|
||||
# Will raise a not found if there is no overcloud with the ID
|
||||
result = pecan.request.dbapi.update_overcloud(db_delta)
|
||||
|
||||
updated = models.Overcloud.from_db_model(result)
|
||||
updated_overcloud = models.Overcloud.from_db_model(result)
|
||||
|
||||
# FIXME(lsmola) This is just POC of updating a stack
|
||||
# this probably should also have workflow
|
||||
# step one- build template and stack-update
|
||||
# step 2- set the correct overcloud status
|
||||
process_stack(POC_PARAMS_UPDATE)
|
||||
process_stack(updated_overcloud.attributes, updated_overcloud.counts,
|
||||
create=True)
|
||||
|
||||
return updated
|
||||
return updated_overcloud
|
||||
|
||||
@wsme_pecan.wsexpose(None, int, status_code=204)
|
||||
def delete(self, overcloud_id):
|
||||
@ -168,6 +226,10 @@ class OvercloudsController(rest.RestController):
|
||||
|
||||
# FIXME(lsmola) this should always try to delete both overcloud
|
||||
# and stack. So it requires some exception catch over below.
|
||||
# FIXME(lsmola) there is also a workflow needed
|
||||
# step one- delete stack and set status deleting in progress to
|
||||
# overcloud
|
||||
# step 2 - once stack is deleted, delete the overcloud
|
||||
LOG.debug('Deleting overcloud with ID: %s' % overcloud_id)
|
||||
pecan.request.dbapi.delete_overcloud_by_id(overcloud_id)
|
||||
|
||||
|
@ -95,11 +95,12 @@ class HeatClient(object):
|
||||
def validate_template(self, template_body):
|
||||
"""Validate given Heat template."""
|
||||
try:
|
||||
self.connection.stacks.validate(template=template_body)
|
||||
return True
|
||||
allowed_data = self.connection.stacks.validate(
|
||||
template=template_body)
|
||||
return True, allowed_data
|
||||
except Exception:
|
||||
LOG.exception("Validation of the Heat template failed.")
|
||||
return False
|
||||
return False, None
|
||||
|
||||
def get_stack(self, name=None):
|
||||
"""Get overcloud Heat template."""
|
||||
|
@ -23,7 +23,7 @@ from tripleo_heat_merge import merge
|
||||
|
||||
|
||||
# The name of the compute Overcloud role - defined for special case handling
|
||||
OVERCLOUD_COMPUTE_ROLE = 'compute'
|
||||
OVERCLOUD_COMPUTE_ROLE = 'overcloud-compute'
|
||||
|
||||
|
||||
def generate_scaling_params(overcloud_roles):
|
||||
|
@ -71,10 +71,55 @@ class OvercloudTests(base.TestCase):
|
||||
|
||||
mock_db_get.assert_called_once_with(12345)
|
||||
|
||||
def test_parse_counts(self):
|
||||
# Setup
|
||||
overcloud_role_1 = db_models.OvercloudRole(
|
||||
image_name='overcloud-compute')
|
||||
|
||||
overcloud_role_2 = db_models.OvercloudRole(
|
||||
image_name='overcloud-block-storage')
|
||||
|
||||
overcloud_role_count_1 = db_models.OvercloudRoleCount(
|
||||
overcloud_role_id=2, num_nodes=5, overcloud_role=overcloud_role_1)
|
||||
|
||||
overcloud_role_count_2 = db_models.OvercloudRoleCount(
|
||||
overcloud_role_id=2, num_nodes=9, overcloud_role=overcloud_role_2)
|
||||
|
||||
mock_counts = [overcloud_role_count_1, overcloud_role_count_2]
|
||||
|
||||
# Test
|
||||
result = overcloud.parse_counts(mock_counts)
|
||||
|
||||
# Verify
|
||||
self.assertEqual(result, {'overcloud-compute': 5,
|
||||
'overcloud-block-storage': 9})
|
||||
|
||||
def test_filter_template_attributes(self):
|
||||
# Setup
|
||||
allowed_data = {'Parameters': {
|
||||
'Allowed_1': 42,
|
||||
'Allowed_2': 21,
|
||||
}}
|
||||
|
||||
attributes = {
|
||||
'NotAllowed_1': "Infinity",
|
||||
'Allowed_1': 42,
|
||||
'NotAllowed_2': "SubZero",
|
||||
'Allowed_2': 21,
|
||||
'NotAllowed_3': "Goro",
|
||||
}
|
||||
|
||||
# Test
|
||||
result = overcloud.filter_template_attributes(allowed_data, attributes)
|
||||
|
||||
# Verify
|
||||
self.assertEqual(result, {'Allowed_1': 42,
|
||||
'Allowed_2': 21})
|
||||
|
||||
@mock.patch('tuskar.heat.template_tools.merge_templates')
|
||||
@mock.patch(
|
||||
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
||||
'validate_template.return_value': True,
|
||||
'validate_template.return_value': (True, {}),
|
||||
'exists_stack.return_value': False,
|
||||
'create_stack.return_value': True,
|
||||
})
|
||||
@ -84,7 +129,7 @@ class OvercloudTests(base.TestCase):
|
||||
mock_heat_merge_templates.return_value = None
|
||||
|
||||
# Test
|
||||
response = overcloud.process_stack({}, create=True)
|
||||
response = overcloud.process_stack({}, {}, create=True)
|
||||
|
||||
# Verify
|
||||
self.assertEqual(response, None)
|
||||
@ -92,7 +137,7 @@ class OvercloudTests(base.TestCase):
|
||||
@mock.patch('tuskar.heat.template_tools.merge_templates')
|
||||
@mock.patch(
|
||||
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
||||
'validate_template.return_value': True,
|
||||
'validate_template.return_value': (True, {}),
|
||||
'exists_stack.return_value': False,
|
||||
'create_stack.return_value': False,
|
||||
})
|
||||
@ -105,12 +150,12 @@ class OvercloudTests(base.TestCase):
|
||||
# Test and Verify
|
||||
self.assertRaises(
|
||||
exception.HeatTemplateCreateFailed,
|
||||
overcloud.process_stack, {}, True)
|
||||
overcloud.process_stack, {}, {}, True)
|
||||
|
||||
@mock.patch('tuskar.heat.template_tools.merge_templates')
|
||||
@mock.patch(
|
||||
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
||||
'validate_template.return_value': True,
|
||||
'validate_template.return_value': (True, {}),
|
||||
'exists_stack.return_value': True,
|
||||
'create_stack.return_value': True,
|
||||
})
|
||||
@ -122,12 +167,13 @@ class OvercloudTests(base.TestCase):
|
||||
|
||||
# Test and Verify
|
||||
self.assertRaises(
|
||||
exception.StackAlreadyCreated, overcloud.process_stack, {}, True)
|
||||
exception.StackAlreadyCreated, overcloud.process_stack, {}, {},
|
||||
True)
|
||||
|
||||
@mock.patch('tuskar.heat.template_tools.merge_templates')
|
||||
@mock.patch(
|
||||
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
||||
'validate_template.return_value': False,
|
||||
'validate_template.return_value': (False, {}),
|
||||
'exists_stack.return_value': False,
|
||||
'create_stack.return_value': True,
|
||||
})
|
||||
@ -139,7 +185,8 @@ class OvercloudTests(base.TestCase):
|
||||
|
||||
# Test and Verify
|
||||
self.assertRaises(
|
||||
exception.InvalidHeatTemplate, overcloud.process_stack, {}, True)
|
||||
exception.InvalidHeatTemplate, overcloud.process_stack, {}, {},
|
||||
True)
|
||||
|
||||
@mock.patch('tuskar.api.controllers.v1.overcloud.process_stack')
|
||||
@mock.patch('tuskar.db.sqlalchemy.api.Connection.create_overcloud')
|
||||
@ -168,7 +215,7 @@ class OvercloudTests(base.TestCase):
|
||||
@mock.patch('tuskar.heat.template_tools.merge_templates')
|
||||
@mock.patch(
|
||||
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
||||
'validate_template.return_value': True,
|
||||
'validate_template.return_value': (True, {}),
|
||||
'exists_stack.return_value': True,
|
||||
'create_stack.return_value': True,
|
||||
})
|
||||
@ -178,7 +225,7 @@ class OvercloudTests(base.TestCase):
|
||||
mock_heat_merge_templates.return_value = None
|
||||
|
||||
# Test
|
||||
response = overcloud.process_stack({})
|
||||
response = overcloud.process_stack({}, {})
|
||||
|
||||
# Verify
|
||||
self.assertEqual(response, None)
|
||||
@ -186,9 +233,9 @@ class OvercloudTests(base.TestCase):
|
||||
@mock.patch('tuskar.heat.template_tools.merge_templates')
|
||||
@mock.patch(
|
||||
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
||||
'validate_template.return_value': True,
|
||||
'validate_template.return_value': (True, {}),
|
||||
'exists_stack.return_value': True,
|
||||
'create_stack.return_value': False,
|
||||
'update_stack.return_value': False,
|
||||
})
|
||||
)
|
||||
def test_update_stack_heat_exception(self, mock_heat_client,
|
||||
@ -198,12 +245,13 @@ class OvercloudTests(base.TestCase):
|
||||
|
||||
# Test and Verify
|
||||
self.assertRaises(
|
||||
exception.HeatTemplateUpdateFailed, overcloud.process_stack, {})
|
||||
exception.HeatTemplateUpdateFailed, overcloud.process_stack, {},
|
||||
{})
|
||||
|
||||
@mock.patch('tuskar.heat.template_tools.merge_templates')
|
||||
@mock.patch(
|
||||
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
||||
'validate_template.return_value': True,
|
||||
'validate_template.return_value': (True, {}),
|
||||
'exists_stack.return_value': False,
|
||||
'create_stack.return_value': True,
|
||||
})
|
||||
@ -215,12 +263,12 @@ class OvercloudTests(base.TestCase):
|
||||
|
||||
# Test and Verify
|
||||
self.assertRaises(
|
||||
exception.StackNotFound, overcloud.process_stack, {})
|
||||
exception.StackNotFound, overcloud.process_stack, {}, {})
|
||||
|
||||
@mock.patch('tuskar.heat.template_tools.merge_templates')
|
||||
@mock.patch(
|
||||
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
||||
'validate_template.return_value': False,
|
||||
'validate_template.return_value': (False, {}),
|
||||
'exists_stack.return_value': True,
|
||||
'create_stack.return_value': True,
|
||||
})
|
||||
@ -232,7 +280,7 @@ class OvercloudTests(base.TestCase):
|
||||
|
||||
# Test and Verify
|
||||
self.assertRaises(
|
||||
exception.InvalidHeatTemplate, overcloud.process_stack, {})
|
||||
exception.InvalidHeatTemplate, overcloud.process_stack, {}, {})
|
||||
|
||||
@mock.patch('tuskar.api.controllers.v1.overcloud.process_stack')
|
||||
@mock.patch('tuskar.db.sqlalchemy.api.Connection.update_overcloud')
|
||||
|
@ -23,7 +23,7 @@ class TemplateToolsTests(unittest.TestCase):
|
||||
@mock.patch('tripleo_heat_merge.merge.parse_scaling')
|
||||
def test_generate_scaling_params(self, mock_parse_scaling):
|
||||
# Setup
|
||||
overcloud_roles = {'controller': 1, 'compute': 12}
|
||||
overcloud_roles = {'controller': 1, 'overcloud-compute': 12}
|
||||
|
||||
# Test
|
||||
template_tools.generate_scaling_params(overcloud_roles)
|
||||
@ -34,7 +34,7 @@ class TemplateToolsTests(unittest.TestCase):
|
||||
@mock.patch('tripleo_heat_merge.merge.merge')
|
||||
def test_merge_templates(self, mock_merge):
|
||||
# Setup
|
||||
overcloud_roles = {'controller': 1, 'compute': 12}
|
||||
overcloud_roles = {'controller': 1, 'overcloud-compute': 12}
|
||||
|
||||
# Test
|
||||
template_tools.merge_templates(overcloud_roles)
|
||||
|
Loading…
x
Reference in New Issue
Block a user