Use parameter_defaults instead of parameters

This patch updates the overcloud deployment so that it
writes out a custom Heat environment to use parameter_defaults
instead of parameters for the stack creation. The parameter
defaults environment is placed first in the environments files
array so that end users can easily override any values with
settings in external Heat environments.

The motiviation here is to allow oscplugin to work in a wider
variety of environments instead of just forcing all users
to use the hard coded defaults for things. Ultimately
it would be nice if the defaults would actually live
outside of this project thus making the provisioning tool
more generically within the upstream TripleO community.
This is a step in that direction.

Functionally this works with --templates.

Change-Id: I2722e118abde1cea6210148b16ac1ed3d9f235d8
This commit is contained in:
Dan Prince 2015-08-19 11:07:18 -04:00 committed by Brad P. Crochet
parent 6a2082df05
commit 1e82d0e696
2 changed files with 70 additions and 30 deletions

View File

@ -13,7 +13,10 @@
# under the License.
#
import json
import os
import sys
import tempfile
import mock
import six
@ -44,6 +47,15 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
self._get_passwords = generate_overcloud_passwords_mock
self.parameter_defaults_env_file = (
tempfile.NamedTemporaryFile(mode='w', delete=False).name)
def tearDown(self):
super(TestDeployOvercloud, self).tearDown()
os.unlink(self.parameter_defaults_env_file)
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'_create_parameters_env')
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'_deploy_postconfig')
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
@ -81,7 +93,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
mock_create_overcloudrc,
mock_generate_overcloud_passwords,
mock_create_tempest_deployer_input,
mock_deploy_postconfig):
mock_deploy_postconfig,
mock_create_parameters_env):
arglist = ['--templates', '--ceph-storage-scale', '3']
verifylist = [
@ -116,13 +129,6 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
baremetal = clients.tripleoclient.baremetal()
baremetal.node.list.return_value = range(10)
result = self.cmd.take_action(parsed_args)
self.assertTrue(result)
args, kwargs = orchestration_client.stacks.update.call_args
self.assertEqual(args, (orchestration_client.stacks.get().id, ))
expected_parameters = {
'AdminPassword': 'password',
'AdminToken': 'password',
@ -165,9 +171,23 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
'SwiftPassword': 'password',
'SwiftStorageImage': 'overcloud-full',
}
self.assertEqual(set(kwargs['parameters'].keys())
^ set(expected_parameters.keys()), set())
self.assertEqual(kwargs['parameters'], expected_parameters)
def _custom_create_params_env(parameters):
for key, value in six.iteritems(parameters):
self.assertEqual(value, expected_parameters[key])
parameter_defaults = {"parameter_defaults": parameters}
with open(self.parameter_defaults_env_file, 'w') as temp_file:
temp_file.write(json.dumps(parameter_defaults))
return [self.parameter_defaults_env_file]
mock_create_parameters_env.side_effect = _custom_create_params_env
result = self.cmd.take_action(parsed_args)
self.assertTrue(result)
args, kwargs = orchestration_client.stacks.update.call_args
self.assertEqual(args, (orchestration_client.stacks.get().id, ))
self.assertEqual(kwargs['files'], {})
self.assertEqual(kwargs['template'], 'template')
@ -180,6 +200,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
mock_create_tempest_deployer_input.assert_called_with(self.cmd)
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'_create_parameters_env')
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
'_deploy_postconfig')
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
@ -217,7 +239,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
mock_create_overcloudrc,
mock_generate_overcloud_passwords,
mock_create_tempest_deployer_input,
mock_deploy_postconfig):
mock_deploy_postconfig,
mock_create_parameters_env):
arglist = ['--templates', '--ceph-storage-scale', '3']
verifylist = [
@ -258,11 +281,6 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
baremetal = clients.tripleoclient.baremetal()
baremetal.node.list.return_value = range(10)
result = self.cmd.take_action(parsed_args)
self.assertTrue(result)
args, kwargs = orchestration_client.stacks.create.call_args
expected_parameters = {
'AdminPassword': 'password',
'AdminToken': 'password',
@ -297,9 +315,9 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
'NeutronNetworkVLANRanges': 'datacentre:1:1000',
'NeutronPassword': 'password',
'NeutronPublicInterface': 'nic1',
'NeutronTunnelIdRanges': '1:1000',
'NeutronTunnelIdRanges': ['1:1000'],
'NeutronTunnelTypes': 'gre',
'NeutronVniRanges': '1:1000',
'NeutronVniRanges': ['1:1000'],
'NovaComputeLibvirtType': 'kvm',
'NovaImage': 'overcloud-full',
'NovaPassword': 'password',
@ -315,9 +333,20 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
'SwiftStorageImage': 'overcloud-full',
}
self.assertEqual(set(kwargs['parameters'].keys())
^ set(expected_parameters.keys()), set())
self.assertEqual(kwargs['parameters'], expected_parameters)
def _custom_create_params_env(parameters):
for key, value in six.iteritems(parameters):
self.assertEqual(value, expected_parameters[key])
parameter_defaults = {"parameter_defaults": parameters}
with open(self.parameter_defaults_env_file, 'w') as temp_file:
temp_file.write(json.dumps(parameter_defaults))
return [self.parameter_defaults_env_file]
mock_create_parameters_env.side_effect = _custom_create_params_env
result = self.cmd.take_action(parsed_args)
self.assertTrue(result)
args, kwargs = orchestration_client.stacks.create.call_args
self.assertEqual(kwargs['files'], {})
self.assertEqual(kwargs['template'], 'template')
@ -405,10 +434,6 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
self.assertEqual(args, (orchestration_client.stacks.get().id, ))
# The parameters output contains lots of output and some is random.
# So lets just check that it is present
self.assertTrue('parameters' in kwargs)
self.assertEqual(kwargs['files'], {})
self.assertEqual(kwargs['template'], 'template')
self.assertEqual(kwargs['environment'], 'env')

View File

@ -16,6 +16,7 @@ from __future__ import print_function
import argparse
import collections
import json
import logging
import os
import re
@ -86,8 +87,8 @@ PARAMETERS = {
NEW_STACK_PARAMETERS = {
'NovaComputeLibvirtType': 'kvm',
'NeutronTunnelIdRanges': '1:1000',
'NeutronVniRanges': '1:1000',
'NeutronTunnelIdRanges': ['1:1000'],
'NeutronVniRanges': ['1:1000'],
'NeutronEnableTunnelling': 'True',
'NeutronNetworkType': 'gre',
'NeutronTunnelTypes': 'gre',
@ -305,7 +306,12 @@ class DeployOvercloud(command.Command):
# Update parameters from commandline
for param, arg in param_args:
if getattr(args, arg, None) is not None:
parameters[param] = getattr(args, arg)
# these must be converted to [] which is what Heat expects
if param.endswith(('NeutronTunnelIdRanges',
'NeutronVniRanges')):
parameters[param] = [getattr(args, arg)]
else:
parameters[param] = getattr(args, arg)
# Scaling needs extra parameters
number_controllers = max((
@ -396,8 +402,17 @@ class DeployOvercloud(command.Command):
handle, user_env_file = tempfile.mkstemp()
with open(user_env_file, 'w') as temp_file:
temp_file.write(user_env)
os.close(handle)
return [registry, environment, user_env_file]
def _create_parameters_env(self, parameters):
parameter_defaults = {"parameter_defaults": parameters}
handle, parameter_defaults_env_file = tempfile.mkstemp()
with open(parameter_defaults_env_file, 'w') as temp_file:
temp_file.write(json.dumps(parameter_defaults))
os.close(handle)
return [parameter_defaults_env_file]
def _heat_deploy(self, stack, stack_name, template_path, parameters,
environments, timeout):
"""Verify the Baremetal nodes are available and do a stack update"""
@ -425,7 +440,6 @@ class DeployOvercloud(command.Command):
stack_args = {
'stack_name': stack_name,
'template': template,
'parameters': parameters,
'environment': env,
'files': files
}
@ -508,6 +522,7 @@ class DeployOvercloud(command.Command):
resource_registry_path = os.path.join(tht_root, RESOURCE_REGISTRY_NAME)
environments = [resource_registry_path, env_path]
environments.extend(self._create_parameters_env(parameters))
if parsed_args.rhel_reg:
reg_env = self._create_registration_env(parsed_args)
environments.extend(reg_env)