def _download_ansible_playbooks(self, client, stack_name, output_dir): stack_config = config.Config(client) print('** Downloading undercloud ansible.. **') # python output buffering is making this seem to take forever.. sys.stdout.flush() stack_config.download_config('undercloud', output_dir) # Sadly the above writes the ansible config to a new directory each # time. This finds the newest new entry. # The use of tmpdirs is going away, but we need to remain # backwards compatible for now to pass the gate. lp:17252118 def find_ansible_dir(): tmpdirs = glob.glob('%s/tripleo-*-config' % output_dir) if not tmpdirs: return output_dir else: return max(tmpdirs, key=os.path.getctime) ansible_dir = find_ansible_dir() inventory = TripleoInventory(hclient=client, plan_name=stack_name, ansible_ssh_user='******') inv_path = os.path.join(ansible_dir, 'inventory.yaml') extra_vars = {'Undercloud': {'ansible_connection': 'local'}} inventory.write_static_inventory(inv_path, extra_vars) print('** Downloaded undercloud ansible to %s **' % ansible_dir) sys.stdout.flush() return ansible_dir
def test_config_download(self, mock_server_data, mock_deployment_data, mock_server_id_data, mock_config_dict): heat = mock.MagicMock() self.config = ooo_config.Config(heat) stack = 'overcloud' server_data, server_id_data, deployment_data, configs = \ self._get_config_data('config_data.yaml') self.configs = configs mock_server_data.return_value = server_data mock_server_id_data.return_value = server_id_data mock_deployment_data.return_value = deployment_data mock_config_dict.side_effect = self._get_config_dict tmp_path = self.config.download_config(stack, '/tmp') print("config at %s" % tmp_path) for f in ['overcloud-controller-0', 'overcloud-novacompute-0', 'overcloud-novacompute-1', 'overcloud-novacompute-2', 'Controller', 'Compute', ]: self.assertEqual( yaml.safe_load( open(os.path.join(tmp_path, 'group_vars', f)).read()), self._get_yaml_file(f))
def _download_ansible_playbooks(self, client, stack_id): stack_config = config.Config(client) output_dir = os.environ.get('HOME') stack = client.stacks.get(stack_id) print('** Downloading undercloud ansible.. **') # python output buffering is making this seem to take forever.. sys.stdout.flush() stack_config.download_config('undercloud', output_dir) # Sadly the above writes the ansible config to a new directory each # time. This finds the newest new entry. ansible_dir = max(glob.iglob('%s/tripleo-*-config' % output_dir), key=os.path.getctime) inventory = ANSIBLE_INVENTORY outputs = {i['output_key']: i['output_value'] for i in stack.outputs} for service in outputs['EnabledServices']['Undercloud']: inventory += ANSIBLE_SERVICE_INVENTORY.format(service=service) # Write out the inventory file. with open('%s/inventory' % ansible_dir, 'w') as f: f.write(inventory.format(hostname=self._get_hostname())) print('** Downloaded undercloud ansible to %s **' % ansible_dir) sys.stdout.flush() return ansible_dir
def test_get_server_data(self): heat = mock.MagicMock() self.config = ooo_config.Config(heat) stack = 'overcloud' role_names = ['Controller', 'Compute', 'Custom'] heat.resources.list.return_value = ['fakeserver'] server_data = self.config.get_server_data(stack, role_names) self.assertEqual(heat.resources.list.call_count, 3) self.assertEqual( heat.resources.list.call_args_list[0], mock.call(stack, filters=dict(type='OS::TripleO::ControllerServer'), nested_depth=constants.NESTED_DEPTH, with_detail=True)) self.assertEqual( heat.resources.list.call_args_list[1], mock.call(stack, filters=dict(type='OS::TripleO::ComputeServer'), nested_depth=constants.NESTED_DEPTH, with_detail=True)) self.assertEqual( heat.resources.list.call_args_list[2], mock.call(stack, filters=dict(type='OS::TripleO::CustomServer'), nested_depth=constants.NESTED_DEPTH, with_detail=True)) self.assertEqual(server_data, ['fakeserver', 'fakeserver', 'fakeserver'])
def _download_ansible_playbooks(self, client, stack_name, tripleo_role_name='Standalone'): stack_config = config.Config(client) self._create_working_dirs() self.log.warning( _('** Downloading {0} ansible.. **').format(stack_name)) # python output buffering is making this seem to take forever.. sys.stdout.flush() stack_config.write_config(stack_config.fetch_config(stack_name), stack_name, self.tmp_ansible_dir) inventory = TripleoInventory(hclient=client, plan_name=stack_name, ansible_ssh_user='******') inv_path = os.path.join(self.tmp_ansible_dir, 'inventory.yaml') extra_vars = {tripleo_role_name: {'ansible_connection': 'local'}} inventory.write_static_inventory(inv_path, extra_vars) self.log.info( _('** Downloaded {0} ansible to {1} **').format( stack_name, self.tmp_ansible_dir)) sys.stdout.flush() return self.tmp_ansible_dir
def test_initialize_git_repo(self): heat = mock.MagicMock() heat.stacks.get.return_value = fakes.create_tht_stack() self.config = ooo_config.Config(heat) self.tmp_dir = self.useFixture(fixtures.TempDir()).path repo = self.config.initialize_git_repo(self.tmp_dir) self.assertIsInstance(repo, git.Repo)
def test_config_download_warn_grandparent_resource_name( self, mock_deployment_data, mock_deployment_resource_id, mock_git_init): heat = mock.MagicMock() self.config = ooo_config.Config(heat) stack = mock.MagicMock() heat.stacks.get.return_value = stack heat.resources.get.return_value = mock.MagicMock() deployment_data, _ = self._get_config_data('config_data.yaml') # Set the name of the deployment to an integer to trigger looking up # the grandparent resource name deployment_data[0].attributes['value']['name'] = 1 self.deployments = deployment_data mock_deployment_data.return_value = deployment_data mock_deployment_resource_id.side_effect = self._get_deployment_id self.tmp_dir = self.useFixture(fixtures.TempDir()).path with warnings.catch_warnings(record=True) as w: self.assertRaises(ValueError, self.config.download_config, stack, self.tmp_dir) self.assertGreaterEqual(len(w), 1) self.assertGreaterEqual(len([x for x in w if "grandparent" in str(x.message)]), 1) mock_git_init.assert_called_once_with(self.tmp_dir)
def test_overcloud_config_generate_config(self, mock_rmtree, mock_open, mock_mkdir, mock_copyfile): config_type_list = [ 'config_settings', 'global_config_settings', 'logging_sources', 'monitoring_subscriptions', 'service_config_settings', 'service_metadata_settings', 'service_names', 'upgrade_batch_tasks', 'upgrade_tasks', 'external_deploy_tasks' ] fake_role = [ role for role in fakes.FAKE_STACK['outputs'][1]['output_value'] ] heat = mock.MagicMock() heat.stacks.get.return_value = fakes.create_tht_stack() self.config = ooo_config.Config(heat) self.config.download_config('overcloud', '/tmp/tht', config_type_list) expected_mkdir_calls = [call('/tmp/tht/%s' % r) for r in fake_role] mock_mkdir.assert_has_calls(expected_mkdir_calls, any_order=True) expected_calls = [] for config in config_type_list: for role in fake_role: if 'external' in config: continue elif config == 'step_config': expected_calls += [ call('/tmp/tht/%s/%s.pp' % (role, config)) ] else: expected_calls += [ call('/tmp/tht/%s/%s.yaml' % (role, config)) ] mock_open.assert_has_calls(expected_calls, any_order=True)
def test_create_config_dir(self, mock_os_path_exists, mock_rmtree): mock_os_path_exists.get.return_value = True heat = mock.MagicMock() heat.stacks.get.return_value = fakes.create_tht_stack() self.config = ooo_config.Config(heat) self.config.create_config_dir('/tmp/tht', False) expected_rmtree_calls = [call('/tmp/tht')] mock_rmtree.assert_has_calls(expected_rmtree_calls)
def test_config_download(self, mock_deployment_data, mock_config_dict): heat = mock.MagicMock() self.config = ooo_config.Config(heat) stack = mock.MagicMock() heat.stacks.get.return_value = stack stack.outputs = [{ 'output_key': 'RoleNetHostnameMap', 'output_value': { 'Controller': { 'ctlplane': ['overcloud-controller-0.ctlplane.localdomain'] }, 'Compute': { 'ctlplane': [ 'overcloud-novacompute-0.ctlplane.localdomain', 'overcloud-novacompute-1.ctlplane.localdomain', 'overcloud-novacompute-2.ctlplane.localdomain' ] } } }, { 'output_key': 'ServerIdData', 'output_value': { 'server_ids': { 'Controller': ['00b3a5e1-5e8e-4b55-878b-2fa2271f15ad'], 'Compute': [ 'a7db3010-a51f-4ae0-a791-2364d629d20d', '8b07cd31-3083-4b88-a433-955f72039e2c', '169b46f8-1965-4d90-a7de-f36fb4a830fe' ] } } }] deployment_data, configs = \ self._get_config_data('config_data.yaml') self.configs = configs mock_deployment_data.return_value = deployment_data mock_config_dict.side_effect = self._get_config_dict self.tmp_dir = self.useFixture(fixtures.TempDir()).path tmp_path = self.config.download_config(stack, self.tmp_dir) for f in [ 'overcloud-controller-0', 'overcloud-novacompute-0', 'overcloud-novacompute-1', 'overcloud-novacompute-2', 'Controller', 'Compute', ]: self.assertEqual( yaml.safe_load( open(os.path.join(tmp_path, 'group_vars', f)).read()), self._get_yaml_file(f))
def test_overcloud_config_wrong_config_type(self, mock_rmtree, mock_open, mock_mkdir, mock_repo): args = {'name': 'overcloud', 'config_dir': '/tmp/tht', 'config_type': ['bad_config']} heat = mock.MagicMock() heat.stacks.get.return_value = fakes.create_tht_stack() self.config = ooo_config.Config(heat) self.assertRaises( KeyError, self.config.download_config, *args)
def test_render_role_network_config_empty_dict( self, mock_get_role_net_config_data): heat = mock.MagicMock() heat.stacks.get.return_value = fakes.create_tht_stack() config_mock = mock.MagicMock() config_mock.config = {} heat.software_configs.get.return_value = config_mock self.config = ooo_config.Config(heat) mock_get_role_net_config_data.return_value = dict(Controller='config') config_dir = '/tmp/tht' self.config.render_network_config(config_dir)
def take_action(self, parsed_args): self.log.debug("take_action(%s)" % parsed_args) # Get clients clients = self.app.client_manager name = parsed_args.name config_dir = parsed_args.config_dir config_type = parsed_args.config_type # Get config config = ooo_config.Config(clients.orchestration) config_path = config.download_config(name, config_dir, config_type) print("The TripleO configuration has been successfully generated " "into: {0}".format(config_path))
def test_render_role_network_config(self, mock_get_role_net_config_data, mock_open): heat = mock.MagicMock() heat.stacks.get.return_value = fakes.create_tht_stack() config_mock = mock.MagicMock() config_mock.config = 'some config' heat.software_configs.get.return_value = config_mock self.config = ooo_config.Config(heat) mock_get_role_net_config_data.return_value = dict(Controller='config') config_dir = '/tmp/tht' self.config.render_network_config(config_dir) self.assertEqual(1, mock_open.call_count) self.assertEqual('/tmp/tht/Controller/NetworkConfig', mock_open.call_args_list[0][0][0])
def test_overcloud_config_upgrade_tasks(self): heat = mock.MagicMock() heat.stacks.get.return_value = fakes.create_tht_stack() self.config = ooo_config.Config(heat) self.config.fetch_config('overcloud') self.tmp_dir = self.useFixture(fixtures.TempDir()).path fake_role = list(self.config.stack_outputs.get('RoleData')) expected_tasks = {'FakeController': {0: [], 1: [{'name': 'Stop fake service', 'service': 'name=fake ' 'state=stopped', 'when': 'step|int == 1'}], 2: [], 3: [], 4: [], 5: []}, 'FakeCompute': {0: [], 1: [{'name': 'Stop fake service', 'service': 'name=fake ' 'state=stopped', 'when': ['nova_api_enabled.rc' ' == 0', 'httpd_enabled.rc' ' != 0', 'step|int == 1']}], 2: [{'name': 'Stop nova-compute ' 'service', 'service': 'name=openstack-' 'nova-compute state=stopped', 'when': ['nova_compute_' 'enabled.rc == 0', 'step|int == 2', 'existing', 'list']}], 3: [], 4: [], 5: []}} for role in fake_role: filedir = os.path.join(self.tmp_dir, role) os.makedirs(filedir) for step in range(constants.DEFAULT_STEPS_MAX): filepath = os.path.join(filedir, "upgrade_tasks_step%s.yaml" % step) playbook_tasks = self.config._write_tasks_per_step( self.config.stack_outputs.get('RoleData')[role] ['upgrade_tasks'], role, filepath, step) self.assertTrue(os.path.isfile(filepath)) self.assertEqual(expected_tasks[role][step], playbook_tasks)
def run(self, context): heat = self.get_orchestration_client(context) swift = self.get_object_client(context) # Since the config-download directory is now a git repo, first download # the existing config container if it exists so we can reuse the # existing git repo. try: swiftutils.download_container(swift, self.container_config, self.config_dir) # Delete the existing container before we re-upload, otherwise # files may not be fully overwritten. swiftutils.delete_container(swift, self.container_config) except swiftexceptions.ClientException as err: if err.http_status != 404: raise # Delete downloaded tarball as it will be recreated later and we don't # want to include the old tarball in the new tarball. old_tarball_path = os.path.join(self.config_dir, '%s.tar.gz' % self.container_config) if os.path.exists(old_tarball_path): os.unlink(old_tarball_path) config = ooo_config.Config(heat) message = ('Automatic commit by Mistral GetOvercloudConfig action.\n\n' 'User: {user}\n' 'Project: {project}'.format(user=context.user_name, project=context.project_name)) config_path = config.download_config(self.container, self.config_dir, self.config_type, preserve_config_dir=True, commit_message=message) with tempfile.NamedTemporaryFile() as tmp_tarball: tarball.create_tarball(config_path, tmp_tarball.name, excludes=['.tox', '*.pyc', '*.pyo']) tarball.tarball_extract_to_swift_container( self.get_object_client(context), tmp_tarball.name, self.container_config) # Also upload the tarball to the container for use by export later with open(tmp_tarball.name, 'rb') as t: swift.put_object(self.container_config, '%s.tar.gz' % self.container_config, t) if os.path.exists(config_path): shutil.rmtree(config_path)
def test_overcloud_config_dont_preserve_config(self, mock_os_path_exists, mock_rmtree, mock_open, mock_mkdir, mock_copyfile, mock_repo, mock_git_init): config_type_list = ['config_settings', 'global_config_settings', 'logging_sources', 'monitoring_subscriptions', 'service_config_settings', 'service_metadata_settings', 'service_names', 'upgrade_batch_tasks', 'upgrade_tasks', 'external_deploy_tasks'] mock_os_path_exists.get.return_value = True heat = mock.MagicMock() heat.stacks.get.return_value = fakes.create_tht_stack() self.config = ooo_config.Config(heat) self.config.fetch_config('overcloud') fake_role = list(self.config.stack_outputs.get('RoleData')) self.config.download_config('overcloud', '/tmp/tht', config_type_list, False) mock_git_init.assert_called_once_with('/tmp/tht') expected_rmtree_calls = [call('/tmp/tht')] mock_rmtree.assert_has_calls(expected_rmtree_calls) expected_mkdir_calls = [call('/tmp/tht/%s' % r) for r in fake_role] mock_mkdir.assert_has_calls(expected_mkdir_calls, any_order=True) mock_mkdir.assert_called() expected_calls = [] for config in config_type_list: for role in fake_role: if 'external' in config: continue elif config == 'step_config': expected_calls += [call('/tmp/tht/%s/%s.pp' % (role, config))] elif config == 'param_config': expected_calls += [call('/tmp/tht/%s/%s.json' % (role, config))] else: expected_calls += [call('/tmp/tht/%s/%s.yaml' % (role, config))] mock_open.assert_has_calls(expected_calls, any_order=True)
def test_overcloud_config_upgrade_tasks(self): heat = mock.MagicMock() heat.stacks.get.return_value = fakes.create_tht_stack() self.config = ooo_config.Config(heat) self.tmp_dir = self.useFixture(fixtures.TempDir()).path fake_role = [ role for role in fakes.FAKE_STACK['outputs'][1]['output_value'] ] expected_tasks = { 'FakeController': [{ 'name': 'Stop fake service', 'service': 'name=fake ' 'state=stopped', 'when': 'step|int == 1' }], 'FakeCompute': [{ 'name': 'Stop fake service', 'service': 'name=fake state=stopped', 'when': [ 'nova_api_enabled.rc == 0', 'httpd_enabled.rc != 0', 'step|int == 1' ] }, { 'name': 'Stop nova-' 'compute service', 'service': 'name=openstack-nova-' 'compute state=stopped', 'when': [ 'nova_compute_enabled.rc == 0', 'step|int == 2', 'existing', 'list' ] }] } for role in fake_role: filedir = os.path.join(self.tmp_dir, role) os.makedirs(filedir) filepath = os.path.join(filedir, "upgrade_tasks_playbook.yaml") playbook_tasks = self.config._write_playbook_get_tasks( fakes.FAKE_STACK['outputs'][1]['output_value'][role] ['upgrade_tasks'], role, filepath) self.assertTrue(os.path.isfile(filepath)) self.assertEqual(expected_tasks[role], playbook_tasks)
def test_config_download_no_deployment_name(self, mock_deployment_data): heat = mock.MagicMock() self.config = ooo_config.Config(heat) stack = mock.MagicMock() heat.stacks.get.return_value = stack deployment_data, _ = self._get_config_data('config_data.yaml') # Delete the name of the first deployment and his parent. del deployment_data[0].attributes['value']['name'] deployment_data[0].parent_resource = None mock_deployment_data.return_value = deployment_data self.tmp_dir = self.useFixture(fixtures.TempDir()).path self.assertRaises(ValueError, self.config.download_config, stack, self.tmp_dir)
def test_get_server_names(self): heat = mock.MagicMock() self.config = ooo_config.Config(heat) self.config.stack_outputs = { 'RoleNetHostnameMap': { 'Controller': { 'ctlplane': [ 'c0.ctlplane.localdomain', 'c1.ctlplane.localdomain', 'c2.ctlplane.localdomain']}}, 'ServerIdData': { 'server_ids': { 'Controller': [ '8269f736', '2af0a373', 'c8479674']}}} server_names = self.config.get_server_names() expected = {'2af0a373': 'c1', '8269f736': 'c0', 'c8479674': 'c2'} self.assertEqual(expected, server_names)
def test_create_config_dir(self, mock_os_path_exists, mock_rmtree, mock_makedirs): mock_os_path_exists.get.return_value = True heat = mock.MagicMock() heat.stacks.get.return_value = fakes.create_tht_stack() self.config = ooo_config.Config(heat) self.config.create_config_dir('/tmp/tht', False) expected_rmtree_calls = [call('/tmp/tht')] mock_rmtree.assert_has_calls(expected_rmtree_calls) expected_makedirs_calls = [ call('/tmp/tht', mode=0o700, exist_ok=True), call('/tmp/tht/artifacts', mode=0o700, exist_ok=True), call('/tmp/tht/env', mode=0o700, exist_ok=True), call('/tmp/tht/inventory', mode=0o700, exist_ok=True), call('/tmp/tht/profiling_data', mode=0o700, exist_ok=True), call('/tmp/tht/project', mode=0o700, exist_ok=True), call('/tmp/tht/roles', mode=0o700, exist_ok=True), ] mock_makedirs.assert_has_calls(expected_makedirs_calls)
def test_validate_config_invalid_yaml(self, mock_deployment_data, mock_config_dict): # Use invalid YAML to assert that we properly handle the exception stack_config = """ Controller: ctlplane: overcloud-controller-0.ctlplane.localdomain Compute: ctlplane: overcloud-novacompute-0.ctlplane.localdomain overcloud-novacompute-1.ctlplane.localdomain overcloud-novacompute-2.ctlplane.localdomain """ yaml_file = '/tmp/testfile.yaml' heat = mock.MagicMock() heat.stacks.get.return_value = fakes.create_tht_stack() self.config = ooo_config.Config(heat) self.assertRaises(yaml.scanner.ScannerError, self.config.validate_config, stack_config, yaml_file)
def test_validate_config(self, mock_yaml, mock_deployment_data, mock_config_dict): stack_config = """ Controller: ctlplane: overcloud-controller-0.ctlplane.localdomain Compute: ctlplane: overcloud-novacompute-0.ctlplane.localdomain overcloud-novacompute-1.ctlplane.localdomain overcloud-novacompute-2.ctlplane.localdomain """ yaml_file = '/tmp/testfile.yaml' heat = mock.MagicMock() heat.stacks.get.return_value = fakes.create_tht_stack() self.config = ooo_config.Config(heat) self.config.validate_config(stack_config, yaml_file) expected_yaml_safe_load_calls = [call(stack_config)] mock_yaml.assert_has_calls(expected_yaml_safe_load_calls)
def test_overcloud_config_one_config_type(self, mock_rmtree, mock_open, mock_mkdir, mock_copyfile): expected_config_type = 'config_settings' fake_role = [ role for role in fakes.FAKE_STACK['outputs'][1]['output_value'] ] heat = mock.MagicMock() heat.stacks.get.return_value = fakes.create_tht_stack() self.config = ooo_config.Config(heat) self.config.download_config('overcloud', '/tmp/tht', ['config_settings']) expected_mkdir_calls = [call('/tmp/tht/%s' % r) for r in fake_role] expected_calls = [ call('/tmp/tht/%s/%s.yaml' % (r, expected_config_type)) for r in fake_role ] mock_mkdir.assert_has_calls(expected_mkdir_calls, any_order=True) mock_open.assert_has_calls(expected_calls, any_order=True)
def test_overcloud_config_one_config_type(self, mock_rmtree, mock_open, mock_mkdir, mock_copyfile, mock_git_init): expected_config_type = 'config_settings' heat = mock.MagicMock() heat.stacks.get.return_value = fakes.create_tht_stack() self.config = ooo_config.Config(heat) self.config.fetch_config('overcloud') fake_role = list(self.config.stack_outputs.get('RoleData')) self.config.download_config('overcloud', '/tmp/tht', ['config_settings']) expected_mkdir_calls = [call('/tmp/tht/%s' % r) for r in fake_role] expected_calls = [ call('/tmp/tht/%s/%s.yaml' % (r, expected_config_type)) for r in fake_role ] mock_mkdir.assert_has_calls(expected_mkdir_calls, any_order=True) mock_mkdir.assert_called() mock_open.assert_has_calls(expected_calls, any_order=True) mock_git_init.assert_called_once_with('/tmp/tht')
def test_get_deployment_data(self): heat = mock.MagicMock() self.config = ooo_config.Config(heat) stack = 'overcloud' first = mock.MagicMock() first.creation_time = datetime.datetime.now() - datetime.timedelta(2) second = mock.MagicMock() second.creation_time = datetime.datetime.now() - datetime.timedelta(1) third = mock.MagicMock() third.creation_time = datetime.datetime.now() # Set return_value in a nonsorted order, as we expect the function to # sort, so that's what we want to test heat.resources.list.return_value = [second, third, first] deployment_data = self.config.get_deployment_data(stack) self.assertTrue(heat.resources.list.called) self.assertEqual( heat.resources.list.call_args, mock.call(stack, filters=dict(name=constants.TRIPLEO_DEPLOYMENT_RESOURCE), nested_depth=constants.NESTED_DEPTH, with_detail=True)) self.assertEqual(deployment_data, [first, second, third])
def run(self, context): heat = self.get_orchestration_client(context) swift = self.get_object_client(context) # Since the config-download directory is now a git repo, first download # the existing config container if it exists so we can reuse the # existing git repo. try: swiftutils.download_container(swift, self.container_config, self.config_dir) # Delete the existing container before we re-upload, otherwise # files may not be fully overwritten. swiftutils.delete_container(swift, self.container_config) except swiftexceptions.ClientException as err: if err.http_status != 404: raise config = ooo_config.Config(heat) message = ('Automatic commit by Mistral GetOvercloudConfig action.\n\n' 'User: {user}\n' 'Project: {project}'.format(user=context.user_name, project=context.project_name)) config_path = config.download_config(self.container, self.config_dir, preserve_config_dir=True, commit_message=message) with tempfile.NamedTemporaryFile() as tmp_tarball: tarball.create_tarball(config_path, tmp_tarball.name, excludes=['.tox', '*.pyc', '*.pyo']) tarball.tarball_extract_to_swift_container( self.get_object_client(context), tmp_tarball.name, self.container_config) if os.path.exists(config_path): shutil.rmtree(config_path)
def test_write_config(self, mock_deployment_data, mock_config_dict): heat = mock.MagicMock() self.config = ooo_config.Config(heat) stack = mock.MagicMock() heat.stacks.get.return_value = stack stack.outputs = [ {'output_key': 'RoleNetHostnameMap', 'output_value': { 'Controller': { 'ctlplane': [ 'overcloud-controller-0.ctlplane.localdomain']}, 'Compute': { 'ctlplane': [ 'overcloud-novacompute-0.ctlplane.localdomain', 'overcloud-novacompute-1.ctlplane.localdomain', 'overcloud-novacompute-2.ctlplane.localdomain']}}}, {'output_key': 'ServerIdData', 'output_value': { 'server_ids': { 'Controller': [ '00b3a5e1-5e8e-4b55-878b-2fa2271f15ad'], 'Compute': [ 'a7db3010-a51f-4ae0-a791-2364d629d20d', '8b07cd31-3083-4b88-a433-955f72039e2c', '169b46f8-1965-4d90-a7de-f36fb4a830fe']}}}, {'output_key': 'RoleGroupVars', 'output_value': { 'Controller': { 'any_errors_fatal': True, 'max_fail_percentage': 15}, 'Compute': { 'any_errors_fatal': True, 'max_fail_percentage': 15}}}, {'output_key': 'HostnameNetworkConfigMap', 'output_value': {}} ] deployment_data, configs = \ self._get_config_data('config_data.yaml') self.configs = configs self.deployments = deployment_data stack_data = self.config.fetch_config('overcloud') mock_deployment_data.return_value = deployment_data mock_config_dict.side_effect = self._get_config_dict config_dir = self.useFixture(fixtures.TempDir()).path self.config.write_config(stack_data, 'overcloud', config_dir) for f in ['Controller', 'Compute', ]: with open(os.path.join(config_dir, 'group_vars', f)) as fin: self.assertEqual( yaml.safe_load(fin.read()), self._get_yaml_file(f)) for d in ['ControllerHostEntryDeployment', 'NetworkDeployment', 'MyExtraConfigPost', 'MyPostConfig']: with open(os.path.join(config_dir, 'Controller', 'overcloud-controller-0', d)) as fin: self.assertEqual( yaml.safe_load(fin.read()), self._get_yaml_file(os.path.join( 'overcloud-controller-0', d))) for d in ['ComputeHostEntryDeployment', 'NetworkDeployment', 'MyExtraConfigPost']: with open(os.path.join(config_dir, 'Compute', 'overcloud-novacompute-0', d)) as fin: self.assertEqual( yaml.safe_load(fin.read()), self._get_yaml_file(os.path.join( 'overcloud-novacompute-0', d))) for d in ['ComputeHostEntryDeployment', 'NetworkDeployment', 'MyExtraConfigPost']: with open(os.path.join(config_dir, 'Compute', 'overcloud-novacompute-1', d)) as fin: self.assertEqual( yaml.safe_load(fin.read()), self._get_yaml_file(os.path.join( 'overcloud-novacompute-1', d))) for d in ['ComputeHostEntryDeployment', 'NetworkDeployment', 'MyExtraConfigPost', 'AnsibleDeployment']: with open(os.path.join(config_dir, 'Compute', 'overcloud-novacompute-2', d)) as fin: self.assertEqual( yaml.safe_load(fin.read()), self._get_yaml_file(os.path.join( 'overcloud-novacompute-2', d)))
def test_config_download_no_deployment_uuid(self, mock_deployment_data, mock_config_dict, mock_deployment_resource_id, mock_git_init): heat = mock.MagicMock() self.config = ooo_config.Config(heat) stack = mock.MagicMock() heat.stacks.get.return_value = stack heat.resources.get.return_value = mock.MagicMock() stack.outputs = [ {'output_key': 'RoleNetHostnameMap', 'output_value': { 'Controller': { 'ctlplane': [ 'overcloud-controller-0.ctlplane.localdomain']}, 'Compute': { 'ctlplane': [ 'overcloud-novacompute-0.ctlplane.localdomain', 'overcloud-novacompute-1.ctlplane.localdomain', 'overcloud-novacompute-2.ctlplane.localdomain']}}}, {'output_key': 'ServerIdData', 'output_value': { 'server_ids': { 'Controller': [ '00b3a5e1-5e8e-4b55-878b-2fa2271f15ad'], 'Compute': [ 'a7db3010-a51f-4ae0-a791-2364d629d20d', '8b07cd31-3083-4b88-a433-955f72039e2c', '169b46f8-1965-4d90-a7de-f36fb4a830fe']}}}, {'output_key': 'HostnameNetworkConfigMap', 'output_value': {}}, {'output_key': 'RoleGroupVars', 'output_value': { 'Controller': { 'any_errors_fatal': 'yes', 'max_fail_percentage': 15}, 'Compute': { 'any_errors_fatal': 'yes', 'max_fail_percentage': 15}, }}] deployment_data, configs = self._get_config_data('config_data.yaml') # Set the deployment to TripleOSoftwareDeployment for the first # deployment deployment_data[0].attributes['value']['deployment'] = \ 'TripleOSoftwareDeployment' # Set the physical_resource_id as '' for the second deployment deployment_data[1].attributes['value']['deployment'] = '' self.configs = configs self.deployments = deployment_data mock_deployment_data.return_value = deployment_data mock_config_dict.side_effect = self._get_config_dict mock_deployment_resource_id.side_effect = self._get_deployment_id self.tmp_dir = self.useFixture(fixtures.TempDir()).path with warnings.catch_warnings(record=True) as w: self.config.download_config(stack, self.tmp_dir) assert "Skipping deployment" in str(w[-1].message) assert "Skipping deployment" in str(w[-2].message)
def test_config_download_os_apply_config( self, mock_deployment_data, mock_config_dict, mock_deployment_resource_id, mock_git_init): heat = mock.MagicMock() self.config = ooo_config.Config(heat) stack = mock.MagicMock() heat.stacks.get.return_value = stack heat.resources.get.return_value = mock.MagicMock() stack.outputs = [ {'output_key': 'RoleNetHostnameMap', 'output_value': { 'Controller': { 'ctlplane': [ 'overcloud-controller-0.ctlplane.localdomain']}, 'Compute': { 'ctlplane': [ 'overcloud-novacompute-0.ctlplane.localdomain', 'overcloud-novacompute-1.ctlplane.localdomain', 'overcloud-novacompute-2.ctlplane.localdomain']}}}, {'output_key': 'ServerIdData', 'output_value': { 'server_ids': { 'Controller': [ '00b3a5e1-5e8e-4b55-878b-2fa2271f15ad'], 'Compute': [ 'a7db3010-a51f-4ae0-a791-2364d629d20d', '8b07cd31-3083-4b88-a433-955f72039e2c', '169b46f8-1965-4d90-a7de-f36fb4a830fe']}}}, {'output_key': 'HostnameNetworkConfigMap', 'output_value': {}}, {'output_key': 'RoleGroupVars', 'output_value': { 'Controller': { 'any_errors_fatal': 'yes', 'max_fail_percentage': 15}, 'Compute': { 'any_errors_fatal': 'yes', 'max_fail_percentage': 15}, }}] deployment_data, configs = \ self._get_config_data('config_data.yaml') # Add a group:os-apply-config config and deployment config_uuid = str(uuid.uuid4()) configs[config_uuid] = dict( id=config_uuid, config=dict(a='a'), group='os-apply-config', outputs=[]) deployment_uuid = str(uuid.uuid4()) deployment_mock = mock.MagicMock() deployment_mock.id = deployment_uuid deployment_mock.attributes = dict( value=dict(server='00b3a5e1-5e8e-4b55-878b-2fa2271f15ad', deployment=deployment_uuid, config=config_uuid, name='OsApplyConfigDeployment')) deployment_data.append(deployment_mock) self.configs = configs self.deployments = deployment_data mock_deployment_data.return_value = deployment_data mock_config_dict.side_effect = self._get_config_dict mock_deployment_resource_id.side_effect = self._get_deployment_id self.tmp_dir = self.useFixture(fixtures.TempDir()).path with warnings.catch_warnings(record=True) as w: self.config.download_config(stack, self.tmp_dir) mock_git_init.assert_called_once_with(self.tmp_dir) # check that we got at least one of the warnings that we expected # to throw self.assertGreaterEqual(len(w), 1) self.assertGreaterEqual(len([x for x in w if issubclass(x.category, DeprecationWarning)]), 1) self.assertGreaterEqual(len([x for x in w if "group:os-apply-config" in str(x.message)]), 1)