diff --git a/tripleoclient/constants.py b/tripleoclient/constants.py index 89d7194f1..e3a129700 100644 --- a/tripleoclient/constants.py +++ b/tripleoclient/constants.py @@ -32,6 +32,7 @@ SERVICE_LIST = { TRIPLEO_HEAT_TEMPLATES = "/usr/share/openstack-tripleo-heat-templates/" OVERCLOUD_YAML_NAME = "overcloud.yaml" +OVERCLOUD_ROLES_FILE = "roles_data.yaml" RESOURCE_REGISTRY_NAME = "overcloud-resource-registry-puppet.yaml" RHEL_REGISTRATION_EXTRACONFIG_NAME = ( "extraconfig/pre_deploy/rhel-registration/") diff --git a/tripleoclient/tests/workflows/test_plan_management.py b/tripleoclient/tests/workflows/test_plan_management.py index 5f00e3b0a..83e026cde 100644 --- a/tripleoclient/tests/workflows/test_plan_management.py +++ b/tripleoclient/tests/workflows/test_plan_management.py @@ -24,7 +24,6 @@ class TestPlanCreationWorkflows(utils.TestCommand): def setUp(self): super(TestPlanCreationWorkflows, self).setUp() - self.app.client_manager.workflow_engine = self.workflow = mock.Mock() self.tripleoclient = mock.Mock() self.websocket = mock.Mock() @@ -78,3 +77,35 @@ class TestPlanCreationWorkflows(utils.TestCommand): {'container': 'test-overcloud'}) self.workflow.executions.create.assert_not_called() + + @mock.patch('tripleoclient.workflows.plan_management.tarball', + autospec=True) + def test_create_plan_from_templates_roles_data(self, mock_tarball): + output = mock.Mock(output='{"result": ""}') + self.workflow.action_executions.create.return_value = output + self.websocket.wait_for_message.return_value = { + "status": "SUCCESS", + } + + mock_open_context = mock.mock_open() + with mock.patch('six.moves.builtins.open', mock_open_context): + plan_management.create_plan_from_templates( + self.app.client_manager, + 'test-overcloud', + '/tht-root/', + 'the_roles_file.yaml') + + self.workflow.action_executions.create.assert_called_once_with( + 'tripleo.plan.create_container', + {'container': 'test-overcloud'}) + + self.workflow.executions.create.assert_called_once_with( + 'tripleo.plan_management.v1.create_deployment_plan', + workflow_input={'queue_name': 'UUID4', + 'container': 'test-overcloud'}) + + mock_open_context.assert_has_calls( + [mock.call('the_roles_file.yaml')]) + + self.tripleoclient.object_store.put_object.assert_called_once_with( + 'test-overcloud', 'roles_data.yaml', mock_open_context()) diff --git a/tripleoclient/v1/overcloud_deploy.py b/tripleoclient/v1/overcloud_deploy.py index 3cc7e3069..bbbcda705 100644 --- a/tripleoclient/v1/overcloud_deploy.py +++ b/tripleoclient/v1/overcloud_deploy.py @@ -400,10 +400,10 @@ class DeployOvercloud(command.Command): # Upload the new plan templates to swift to replace the existing # templates. plan_management.update_plan_from_templates( - clients, parsed_args.stack, tht_root) + clients, parsed_args.stack, tht_root, parsed_args.roles_file) else: plan_management.create_plan_from_templates( - clients, parsed_args.stack, tht_root) + clients, parsed_args.stack, tht_root, parsed_args.roles_file) print("Deploying templates in the directory {0}".format( os.path.abspath(tht_root))) @@ -943,6 +943,11 @@ class DeployOvercloud(command.Command): ' commands. Can be specified more than once. Files in' ' directories are loaded in ascending sort order.') ) + parser.add_argument( + '--roles-file', '-r', dest='roles_file', + help=_('Roles file, overrides the default %s in the --templates ' + 'directory') % constants.OVERCLOUD_ROLES_FILE + ) # TODO(bnemec): In Ocata or later, remove this group and just leave # --validation-errors-nonfatal error_group = parser.add_mutually_exclusive_group() diff --git a/tripleoclient/workflows/plan_management.py b/tripleoclient/workflows/plan_management.py index 42c64a5cd..a4ffb71f4 100644 --- a/tripleoclient/workflows/plan_management.py +++ b/tripleoclient/workflows/plan_management.py @@ -14,11 +14,12 @@ import uuid from tripleo_common.utils import tarball +from tripleoclient import constants from tripleoclient import exceptions from tripleoclient.workflows import base -def _upload_templates(swift_client, container_name, tht_root): +def _upload_templates(swift_client, container_name, tht_root, roles_file=None): """tarball up a given directory and upload it to Swift to be extracted""" with tempfile.NamedTemporaryFile() as tmp_tarball: @@ -26,6 +27,13 @@ def _upload_templates(swift_client, container_name, tht_root): tarball.tarball_extract_to_swift_container( swift_client, tmp_tarball.name, container_name) + # Allow optional override of the roles_data.yaml file + if roles_file: + with open(roles_file) as rf: + swift_client.put_object(container_name, + constants.OVERCLOUD_ROLES_FILE, + rf) + def create_default_plan(clients, **workflow_input): workflow_client = clients.workflow_engine @@ -95,7 +103,7 @@ def create_container(workflow_client, **input_): **input_) -def create_plan_from_templates(clients, name, tht_root): +def create_plan_from_templates(clients, name, tht_root, roles_file=None): workflow_client = clients.workflow_engine swift_client = clients.tripleoclient.object_store @@ -108,12 +116,12 @@ def create_plan_from_templates(clients, name, tht_root): "Unable to create plan. {}".format(result)) print("Creating plan from template files in: {}".format(tht_root)) - _upload_templates(swift_client, name, tht_root) + _upload_templates(swift_client, name, tht_root, roles_file) create_deployment_plan(clients, container=name, queue_name=str(uuid.uuid4())) -def update_plan_from_templates(clients, name, tht_root): +def update_plan_from_templates(clients, name, tht_root, roles_file=None): swift_client = clients.tripleoclient.object_store # TODO(dmatthews): Removing the existing plan files should probably be @@ -136,6 +144,6 @@ def update_plan_from_templates(clients, name, tht_root): ) print("Uploading new plan files") - _upload_templates(swift_client, name, tht_root) + _upload_templates(swift_client, name, tht_root, roles_file) update_deployment_plan(clients, container=name, queue_name=str(uuid.uuid4()))