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__)
|
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 = {'controller': 1, 'compute': 1}
|
||||||
POC_PARAMS_UPDATE = {'controller': 1, 'compute': 2}
|
|
||||||
|
|
||||||
|
|
||||||
def process_stack(params, create=False):
|
def parse_counts(counts):
|
||||||
"""Helper function for processing the stack. Given a params dict containing
|
"""Helper for parsing the OvercloudRoleCount object
|
||||||
the Overcloud Roles and initialization parameters create or update the
|
|
||||||
stack.
|
|
||||||
|
|
||||||
:param params: Dictionary of initialization params and overcloud roles for
|
Given a list of OvercloudRoleCount objects return a dict of
|
||||||
heat template and initialization of stack/
|
(image_name, count) in a format used for building a template.
|
||||||
:type params: dict
|
|
||||||
|
: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
|
:param create: A flag to designate if we are creating or updating the stack
|
||||||
:type create: bool
|
:type create: bool
|
||||||
"""
|
"""
|
||||||
|
|
||||||
overcloud = template_tools.merge_templates(params)
|
overcloud = template_tools.merge_templates(parse_counts(counts))
|
||||||
heat_client = HeatClient()
|
heat_client = HeatClient()
|
||||||
|
|
||||||
stack_exists = heat_client.exists_stack()
|
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()
|
raise exception.InvalidHeatTemplate()
|
||||||
|
|
||||||
if stack_exists and create:
|
if stack_exists and create:
|
||||||
@ -56,7 +107,13 @@ def process_stack(params, create=False):
|
|||||||
elif not stack_exists and not create:
|
elif not stack_exists and not create:
|
||||||
raise exception.StackNotFound()
|
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 not res:
|
||||||
if create:
|
if create:
|
||||||
@ -93,7 +150,6 @@ class OvercloudsController(rest.RestController):
|
|||||||
:raises: tuskar.common.exception.OvercloudExists: if an overcloud
|
:raises: tuskar.common.exception.OvercloudExists: if an overcloud
|
||||||
with the given name exists
|
with the given name exists
|
||||||
"""
|
"""
|
||||||
|
|
||||||
LOG.debug('Creating overcloud: %s' % transfer_overcloud)
|
LOG.debug('Creating overcloud: %s' % transfer_overcloud)
|
||||||
|
|
||||||
# Persist to the database
|
# Persist to the database
|
||||||
@ -110,7 +166,8 @@ class OvercloudsController(rest.RestController):
|
|||||||
# step 2- put the right stack_id to the overcloud
|
# step 2- put the right stack_id to the overcloud
|
||||||
# step 3- initialize the stack
|
# step 3- initialize the stack
|
||||||
# step 4- set the correct overcloud status
|
# 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
|
return saved_overcloud
|
||||||
|
|
||||||
@ -145,15 +202,16 @@ class OvercloudsController(rest.RestController):
|
|||||||
# Will raise a not found if there is no overcloud with the ID
|
# Will raise a not found if there is no overcloud with the ID
|
||||||
result = pecan.request.dbapi.update_overcloud(db_delta)
|
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
|
# FIXME(lsmola) This is just POC of updating a stack
|
||||||
# this probably should also have workflow
|
# this probably should also have workflow
|
||||||
# step one- build template and stack-update
|
# step one- build template and stack-update
|
||||||
# step 2- set the correct overcloud status
|
# 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)
|
@wsme_pecan.wsexpose(None, int, status_code=204)
|
||||||
def delete(self, overcloud_id):
|
def delete(self, overcloud_id):
|
||||||
@ -168,6 +226,10 @@ class OvercloudsController(rest.RestController):
|
|||||||
|
|
||||||
# FIXME(lsmola) this should always try to delete both overcloud
|
# FIXME(lsmola) this should always try to delete both overcloud
|
||||||
# and stack. So it requires some exception catch over below.
|
# 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)
|
LOG.debug('Deleting overcloud with ID: %s' % overcloud_id)
|
||||||
pecan.request.dbapi.delete_overcloud_by_id(overcloud_id)
|
pecan.request.dbapi.delete_overcloud_by_id(overcloud_id)
|
||||||
|
|
||||||
|
@ -95,11 +95,12 @@ class HeatClient(object):
|
|||||||
def validate_template(self, template_body):
|
def validate_template(self, template_body):
|
||||||
"""Validate given Heat template."""
|
"""Validate given Heat template."""
|
||||||
try:
|
try:
|
||||||
self.connection.stacks.validate(template=template_body)
|
allowed_data = self.connection.stacks.validate(
|
||||||
return True
|
template=template_body)
|
||||||
|
return True, allowed_data
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.exception("Validation of the Heat template failed.")
|
LOG.exception("Validation of the Heat template failed.")
|
||||||
return False
|
return False, None
|
||||||
|
|
||||||
def get_stack(self, name=None):
|
def get_stack(self, name=None):
|
||||||
"""Get overcloud Heat template."""
|
"""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
|
# 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):
|
def generate_scaling_params(overcloud_roles):
|
||||||
|
@ -71,10 +71,55 @@ class OvercloudTests(base.TestCase):
|
|||||||
|
|
||||||
mock_db_get.assert_called_once_with(12345)
|
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.template_tools.merge_templates')
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
||||||
'validate_template.return_value': True,
|
'validate_template.return_value': (True, {}),
|
||||||
'exists_stack.return_value': False,
|
'exists_stack.return_value': False,
|
||||||
'create_stack.return_value': True,
|
'create_stack.return_value': True,
|
||||||
})
|
})
|
||||||
@ -84,7 +129,7 @@ class OvercloudTests(base.TestCase):
|
|||||||
mock_heat_merge_templates.return_value = None
|
mock_heat_merge_templates.return_value = None
|
||||||
|
|
||||||
# Test
|
# Test
|
||||||
response = overcloud.process_stack({}, create=True)
|
response = overcloud.process_stack({}, {}, create=True)
|
||||||
|
|
||||||
# Verify
|
# Verify
|
||||||
self.assertEqual(response, None)
|
self.assertEqual(response, None)
|
||||||
@ -92,7 +137,7 @@ class OvercloudTests(base.TestCase):
|
|||||||
@mock.patch('tuskar.heat.template_tools.merge_templates')
|
@mock.patch('tuskar.heat.template_tools.merge_templates')
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
||||||
'validate_template.return_value': True,
|
'validate_template.return_value': (True, {}),
|
||||||
'exists_stack.return_value': False,
|
'exists_stack.return_value': False,
|
||||||
'create_stack.return_value': False,
|
'create_stack.return_value': False,
|
||||||
})
|
})
|
||||||
@ -105,12 +150,12 @@ class OvercloudTests(base.TestCase):
|
|||||||
# Test and Verify
|
# Test and Verify
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.HeatTemplateCreateFailed,
|
exception.HeatTemplateCreateFailed,
|
||||||
overcloud.process_stack, {}, True)
|
overcloud.process_stack, {}, {}, True)
|
||||||
|
|
||||||
@mock.patch('tuskar.heat.template_tools.merge_templates')
|
@mock.patch('tuskar.heat.template_tools.merge_templates')
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
||||||
'validate_template.return_value': True,
|
'validate_template.return_value': (True, {}),
|
||||||
'exists_stack.return_value': True,
|
'exists_stack.return_value': True,
|
||||||
'create_stack.return_value': True,
|
'create_stack.return_value': True,
|
||||||
})
|
})
|
||||||
@ -122,12 +167,13 @@ class OvercloudTests(base.TestCase):
|
|||||||
|
|
||||||
# Test and Verify
|
# Test and Verify
|
||||||
self.assertRaises(
|
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.template_tools.merge_templates')
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
||||||
'validate_template.return_value': False,
|
'validate_template.return_value': (False, {}),
|
||||||
'exists_stack.return_value': False,
|
'exists_stack.return_value': False,
|
||||||
'create_stack.return_value': True,
|
'create_stack.return_value': True,
|
||||||
})
|
})
|
||||||
@ -139,7 +185,8 @@ class OvercloudTests(base.TestCase):
|
|||||||
|
|
||||||
# Test and Verify
|
# Test and Verify
|
||||||
self.assertRaises(
|
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.api.controllers.v1.overcloud.process_stack')
|
||||||
@mock.patch('tuskar.db.sqlalchemy.api.Connection.create_overcloud')
|
@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.template_tools.merge_templates')
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
||||||
'validate_template.return_value': True,
|
'validate_template.return_value': (True, {}),
|
||||||
'exists_stack.return_value': True,
|
'exists_stack.return_value': True,
|
||||||
'create_stack.return_value': True,
|
'create_stack.return_value': True,
|
||||||
})
|
})
|
||||||
@ -178,7 +225,7 @@ class OvercloudTests(base.TestCase):
|
|||||||
mock_heat_merge_templates.return_value = None
|
mock_heat_merge_templates.return_value = None
|
||||||
|
|
||||||
# Test
|
# Test
|
||||||
response = overcloud.process_stack({})
|
response = overcloud.process_stack({}, {})
|
||||||
|
|
||||||
# Verify
|
# Verify
|
||||||
self.assertEqual(response, None)
|
self.assertEqual(response, None)
|
||||||
@ -186,9 +233,9 @@ class OvercloudTests(base.TestCase):
|
|||||||
@mock.patch('tuskar.heat.template_tools.merge_templates')
|
@mock.patch('tuskar.heat.template_tools.merge_templates')
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
||||||
'validate_template.return_value': True,
|
'validate_template.return_value': (True, {}),
|
||||||
'exists_stack.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,
|
def test_update_stack_heat_exception(self, mock_heat_client,
|
||||||
@ -198,12 +245,13 @@ class OvercloudTests(base.TestCase):
|
|||||||
|
|
||||||
# Test and Verify
|
# Test and Verify
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.HeatTemplateUpdateFailed, overcloud.process_stack, {})
|
exception.HeatTemplateUpdateFailed, overcloud.process_stack, {},
|
||||||
|
{})
|
||||||
|
|
||||||
@mock.patch('tuskar.heat.template_tools.merge_templates')
|
@mock.patch('tuskar.heat.template_tools.merge_templates')
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
||||||
'validate_template.return_value': True,
|
'validate_template.return_value': (True, {}),
|
||||||
'exists_stack.return_value': False,
|
'exists_stack.return_value': False,
|
||||||
'create_stack.return_value': True,
|
'create_stack.return_value': True,
|
||||||
})
|
})
|
||||||
@ -215,12 +263,12 @@ class OvercloudTests(base.TestCase):
|
|||||||
|
|
||||||
# Test and Verify
|
# Test and Verify
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.StackNotFound, overcloud.process_stack, {})
|
exception.StackNotFound, overcloud.process_stack, {}, {})
|
||||||
|
|
||||||
@mock.patch('tuskar.heat.template_tools.merge_templates')
|
@mock.patch('tuskar.heat.template_tools.merge_templates')
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
'tuskar.heat.client.HeatClient.__new__', return_value=mock.Mock(**{
|
||||||
'validate_template.return_value': False,
|
'validate_template.return_value': (False, {}),
|
||||||
'exists_stack.return_value': True,
|
'exists_stack.return_value': True,
|
||||||
'create_stack.return_value': True,
|
'create_stack.return_value': True,
|
||||||
})
|
})
|
||||||
@ -232,7 +280,7 @@ class OvercloudTests(base.TestCase):
|
|||||||
|
|
||||||
# Test and Verify
|
# Test and Verify
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.InvalidHeatTemplate, overcloud.process_stack, {})
|
exception.InvalidHeatTemplate, overcloud.process_stack, {}, {})
|
||||||
|
|
||||||
@mock.patch('tuskar.api.controllers.v1.overcloud.process_stack')
|
@mock.patch('tuskar.api.controllers.v1.overcloud.process_stack')
|
||||||
@mock.patch('tuskar.db.sqlalchemy.api.Connection.update_overcloud')
|
@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')
|
@mock.patch('tripleo_heat_merge.merge.parse_scaling')
|
||||||
def test_generate_scaling_params(self, mock_parse_scaling):
|
def test_generate_scaling_params(self, mock_parse_scaling):
|
||||||
# Setup
|
# Setup
|
||||||
overcloud_roles = {'controller': 1, 'compute': 12}
|
overcloud_roles = {'controller': 1, 'overcloud-compute': 12}
|
||||||
|
|
||||||
# Test
|
# Test
|
||||||
template_tools.generate_scaling_params(overcloud_roles)
|
template_tools.generate_scaling_params(overcloud_roles)
|
||||||
@ -34,7 +34,7 @@ class TemplateToolsTests(unittest.TestCase):
|
|||||||
@mock.patch('tripleo_heat_merge.merge.merge')
|
@mock.patch('tripleo_heat_merge.merge.merge')
|
||||||
def test_merge_templates(self, mock_merge):
|
def test_merge_templates(self, mock_merge):
|
||||||
# Setup
|
# Setup
|
||||||
overcloud_roles = {'controller': 1, 'compute': 12}
|
overcloud_roles = {'controller': 1, 'overcloud-compute': 12}
|
||||||
|
|
||||||
# Test
|
# Test
|
||||||
template_tools.merge_templates(overcloud_roles)
|
template_tools.merge_templates(overcloud_roles)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user