def play_scenario(scenario): deployment = None output = dict(scenario=scenario, records=[], agents={}) output['tests'] = dict((_make_test_title(test), test) for test in scenario['execution']['tests']) try: deployment = deploy.Deployment(cfg.CONF.server_endpoint) if (cfg.CONF.os_username and cfg.CONF.os_password and cfg.CONF.os_tenant_name and cfg.CONF.os_auth_url): deployment.connect_to_openstack( cfg.CONF.os_username, cfg.CONF.os_password, cfg.CONF.os_tenant_name, cfg.CONF.os_auth_url, cfg.CONF.os_region_name, cfg.CONF.external_net, cfg.CONF.flavor_name, cfg.CONF.image_name) agents = deployment.deploy(scenario['deployment'], base_dir=os.path.dirname(cfg.CONF.scenario)) agents = _extend_agents(agents) output['agents'] = agents LOG.debug('Deployed agents: %s', agents) if not agents: LOG.warning('No agents deployed.') else: message_queue = messaging.MessageQueue(cfg.CONF.server_endpoint) heartbeat = multiprocessing.Process( target=agent_process.work, kwargs=dict(agent_id='heartbeat', endpoint=cfg.CONF.server_endpoint, polling_interval=cfg.CONF.polling_interval)) heartbeat.daemon = True heartbeat.start() quorum = quorum_pkg.Quorum(message_queue, cfg.CONF.polling_interval, cfg.CONF.agent_loss_timeout, cfg.CONF.agent_join_timeout) quorum.join(set(agents.keys())) execution_result = execute(quorum, scenario['execution'], agents) for record in execution_result: record['scenario'] = (scenario.get('title') or scenario.get('file_name')) output['records'] = execution_result except BaseException as e: if isinstance(e, KeyboardInterrupt): LOG.info('Caught SIGINT. Terminating') else: error_msg = 'Error while executing scenario: %s' % e LOG.error(error_msg) LOG.exception(e) output['scenario']['error'] = error_msg finally: if deployment: deployment.cleanup() return output
def test_get_compute_nodes_non_admin_zones(self, nova_nodes_mock): deployment = deploy.Deployment() deployment.openstack_client = mock.Mock() def raise_error(arg): raise nova.ForbiddenException('err') nova_nodes_mock.side_effect = raise_error accommodation = {'compute_nodes': 4, 'zones': ['nova', 'nsx']} expected = [ { 'host': None, 'zone': 'nova' }, { 'host': None, 'zone': 'nsx' }, { 'host': None, 'zone': 'nova' }, { 'host': None, 'zone': 'nsx' }, ] observed = deployment._get_compute_nodes(accommodation) self.assertEqual(expected, observed)
def test_get_compute_nodes_flavor_no_extra_specs(self, nova_client_mock): # setup fake nova api service list response compute_host_1 = fakes.FakeNovaServiceList(host='host-1') compute_host_2 = fakes.FakeNovaServiceList(host='host-2') compute_host_3 = fakes.FakeNovaServiceList(host='host-3') nova_client_mock.nova.services.list.return_value = [compute_host_1, compute_host_2, compute_host_3] # setup fake nova api flavor list response flavor_no_exta_specs = fakes.FakeNovaFlavorList( name='flavor_no_exta_specs') nova_client_mock.nova.flavors.list.return_value = [ flavor_no_exta_specs] deployment = deploy.Deployment() deployment.flavor_name = 'flavor_no_exta_specs' deployment.openstack_client = nova_client_mock accommodation = {'compute_nodes': 3} expected = [{'host': 'host-1', 'zone': 'nova'}, {'host': 'host-2', 'zone': 'nova'}, {'host': 'host-3', 'zone': 'nova'}] observed = deployment._get_compute_nodes(accommodation) self.assertEqual(expected, observed)
def test_deploy_from_hot_with_env_file(self, nova_nodes_mock, openstack_mock, create_stack_mock, stack_output_mock): test_file = 'shaker/scenarios/test/sample_with_env.yaml' absolute_path = utils.resolve_relative_path(test_file) scenario = utils.read_yaml_file(absolute_path) stack_name = 'shaker_abcdefg' server_endpoint = "127.0.0.01" base_dir = os.path.dirname(absolute_path) deployment = deploy.Deployment() deployment.stack_name = stack_name deployment.external_net = 'test-external_net' deployment.image_name = 'test-image' deployment.flavor_name = 'test-flavor' deployment.dns_nameservers = '8.8.8.8' deployment.openstack_client = openstack_mock # read the env file to determine what cidr is set to # minus the last digit env_file = utils.read_file(scenario['deployment']['env_file'], base_dir) cidr = re.findall(r'[0-9]+(?:\.[0-9]+){2}', env_file)[0] nova_nodes_mock.return_value = [{'host': 'host-1', 'zone': 'nova'}] create_stack_mock.return_value = uuid.uuid4() heat_outputs = { stack_name + '_master_0_instance_name': 'instance-0000052f', stack_name + '_master_0_ip': '192.0.0.3', stack_name + '_slave_0_ip': '192.0.0.4', stack_name + '_slave_0_instance_name': 'instance-0000052c'} stack_output_mock.return_value = heat_outputs expected = { 'shaker_abcdefg_master_0': {'availability_zone': 'nova:host-1', 'id': 'shaker_abcdefg_master_0', 'ip': cidr + '.3', 'mode': 'master', 'node': 'host-1', 'slave_id': 'shaker_abcdefg_slave_0', 'zone': 'nova'}, 'shaker_abcdefg_slave_0': {'availability_zone': 'nova:host-1', 'id': 'shaker_abcdefg_slave_0', 'ip': cidr + '.4', 'master_id': 'shaker_abcdefg_master_0', 'mode': 'slave', 'node': 'host-1', 'zone': 'nova'}} agents = deployment._deploy_from_hot(scenario['deployment'], server_endpoint, base_dir=base_dir) self.assertEqual(expected, agents)
def test_deploy_local(self): deployment = deploy.Deployment() expected = { 'local': {'id': 'local', 'mode': 'alone', 'node': 'localhost'} } agents = deployment.deploy({}) self.assertEqual(expected, agents)
def test_deploy_static(self): deployment = deploy.Deployment() expected = { 'agent': {'id': 'agent', 'mode': 'alone'} } agents = deployment.deploy( {'agents': [{'id': 'agent', 'mode': 'alone'}]}) self.assertEqual(expected, agents)
def play_scenario(scenario): deployment = None output = dict(scenario=scenario, records={}, agents={}) output['tests'] = dict((_make_test_title(test), test) for test in scenario['execution']['tests']) try: deployment = deploy.Deployment(cfg.CONF.server_endpoint) if (cfg.CONF.os_username and cfg.CONF.os_password and cfg.CONF.os_tenant_name and cfg.CONF.os_auth_url): deployment.connect_to_openstack( cfg.CONF.os_username, cfg.CONF.os_password, cfg.CONF.os_tenant_name, cfg.CONF.os_auth_url, cfg.CONF.os_region_name, cfg.CONF.external_net, cfg.CONF.flavor_name, cfg.CONF.image_name, cfg.CONF.os_cacert) base_dir = os.path.dirname(scenario['file_name']) agents = deployment.deploy(scenario['deployment'], base_dir=base_dir) agents = _extend_agents(agents) output['agents'] = agents LOG.debug('Deployed agents: %s', agents) if not agents: raise Exception('No agents deployed.') quorum = quorum_pkg.make_quorum(agents.keys(), cfg.CONF.server_endpoint, cfg.CONF.polling_interval, cfg.CONF.agent_loss_timeout, cfg.CONF.agent_join_timeout) output['records'] = execute(quorum, scenario['execution'], agents) except BaseException as e: if isinstance(e, KeyboardInterrupt): LOG.info('Caught SIGINT. Terminating') record = dict(id=utils.make_record_id(), status='interrupted') else: error_msg = 'Error while executing scenario: %s' % e LOG.error(error_msg) LOG.exception(e) record = dict(id=utils.make_record_id(), status='error', stderr=error_msg) output['records'][record['id']] = record finally: if deployment: deployment.cleanup() # extend every record with reference to scenario for record in output['records'].values(): record['scenario'] = scenario['title'] return output
def test_deploy_from_hot_with_support_stacks(self, nova_nodes_mock, openstack_mock, create_stack_mock, stack_output_mock): test_file = 'shaker/scenarios/test/sample_with_support_stacks.yaml' absolute_path = utils.resolve_relative_path(test_file) scenario = utils.read_yaml_file(absolute_path) stack_name = 'shaker_abcdefg' server_endpoint = "127.0.0.01" base_dir = os.path.dirname(absolute_path) deployment = deploy.Deployment() deployment.stack_name = stack_name deployment.external_net = 'test-external_net' deployment.image_name = 'test-image' deployment.flavor_name = 'test-flavor' deployment.dns_nameservers = '8.8.8.8' deployment.openstack_client = openstack_mock nova_nodes_mock.return_value = [{'host': 'host-1', 'zone': 'nova'}] create_stack_mock.return_value = uuid.uuid4() heat_outputs = { stack_name + '_master_0_instance_name': 'instance-0000052f', stack_name + '_master_0_ip': '10.0.0.3', stack_name + '_slave_0_ip': '10.0.0.4', stack_name + '_slave_0_instance_name': 'instance-0000052c'} stack_output_mock.return_value = heat_outputs expected = { 'shaker_abcdefg_master_0': {'availability_zone': 'nova:host-1', 'id': 'shaker_abcdefg_master_0', 'ip': '10.0.0.3', 'mode': 'master', 'node': 'host-1', 'slave_id': 'shaker_abcdefg_slave_0', 'zone': 'nova'}, 'shaker_abcdefg_slave_0': {'availability_zone': 'nova:host-1', 'id': 'shaker_abcdefg_slave_0', 'ip': '10.0.0.4', 'master_id': 'shaker_abcdefg_master_0', 'mode': 'slave', 'node': 'host-1', 'zone': 'nova'}} agents = deployment._deploy_from_hot(scenario['deployment'], server_endpoint, base_dir=base_dir) self.assertEqual(create_stack_mock.call_count, 3) self.assertEqual(expected, agents)
def test_get_compute_nodes_non_admin_not_configured(self, nova_nodes_mock): deployment = deploy.Deployment() deployment.openstack_client = mock.Mock() def raise_error(arg): raise nova.ForbiddenException('err') nova_nodes_mock.side_effect = raise_error accommodation = {} self.assertRaises(deploy.DeploymentException, deployment._get_compute_nodes, accommodation)
def test_get_compute_nodes_non_admin(self, nova_nodes_mock): deployment = deploy.Deployment() deployment.openstack_client = mock.Mock() def raise_error(arg): raise nova.ForbiddenException('err') nova_nodes_mock.side_effect = raise_error accommodation = {'compute_nodes': 4} expected = list(itertools.repeat({'host': None, 'zone': 'nova'}, 4)) observed = deployment._get_compute_nodes(accommodation) self.assertEqual(expected, observed)
def test_deploy_support_stacks(self, openstack_mock, create_stack_mock): test_file = 'shaker/scenarios/test/sample_with_support_stacks.yaml' absolute_path = utils.resolve_relative_path(test_file) scenario = utils.read_yaml_file(absolute_path) support_stacks = scenario['deployment']['support_templates'] base_dir = os.path.dirname(absolute_path) deployment = deploy.Deployment() deployment.stack_name = 'shaker_abcdefg' deployment.openstack_client = openstack_mock support_stack_1 = uuid.uuid4() support_stack_2 = uuid.uuid4() create_stack_mock.side_effect = (support_stack_1, support_stack_2) deployment._deploy_support_stacks(support_stacks, base_dir) self.assertEqual(support_stack_1, deployment.support_stacks[0].id) self.assertEqual(support_stack_2, deployment.support_stacks[1].id)
def test_get_compute_nodes_flavor_extra_specs_with_match( self, nova_client_mock): # setup fake nova api service list response compute_host_1 = fakes.FakeNovaServiceList(host='host-1') compute_host_2 = fakes.FakeNovaServiceList(host='host-2') compute_host_3 = fakes.FakeNovaServiceList(host='host-3') nova_client_mock.nova.services.list.return_value = [ compute_host_1, compute_host_2, compute_host_3 ] # setup fake nova api flavor list response flavor_with_extra_specs = fakes.FakeNovaFlavorList( name='flavor_with_extra_specs', extra_specs={'aggregate_instance_extra_specs:special_hw': 'true'}) nova_client_mock.nova.flavors.list.return_value = [ flavor_with_extra_specs ] # setup fake nova api aggregate list response agg_host_1 = fakes.FakeNovaAggregateList(hosts=['host-1']) agg_host_2 = fakes.FakeNovaAggregateList( hosts=['host-2'], metadata={'special_hw': 'true'}) agg_host_3 = fakes.FakeNovaAggregateList(hosts=['host-3']) nova_client_mock.nova.aggregates.list.return_value = [ agg_host_1, agg_host_2, agg_host_3 ] deployment = deploy.Deployment() deployment.flavor_name = 'flavor_with_extra_specs' deployment.openstack_client = nova_client_mock accommodation = {'compute_nodes': 3} expected = [{'host': 'host-2', 'zone': 'nova'}] observed = deployment._get_compute_nodes(accommodation) self.assertEqual(expected, observed)
def play_scenario(message_queue, scenario): deployment = None output = dict(scenarios={}, records={}, agents={}, tests={}) output['scenarios'][scenario['title']] = scenario try: deployment = deploy.Deployment() if _under_openstack(): openstack_params = utils.pack_openstack_params(cfg.CONF) try: deployment.connect_to_openstack(openstack_params, cfg.CONF.flavor_name, cfg.CONF.image_name, cfg.CONF.external_net, cfg.CONF.dns_nameservers) except openstack_clients.OpenStackClientException: raise except Exception as e: LOG.warning( 'Failed to connect to OpenStack: %s. Please ' 'verify parameters: %s', e, openstack_params) # try to proceed even if OpenStack connection fails # (in case scenario does not need it) base_dir = os.path.dirname(scenario['file_name']) scenario_deployment = scenario.get('deployment', {}) server_endpoint = (cfg.CONF.server_endpoint if 'server_endpoint' in cfg.CONF else None) agents = deployment.deploy(scenario_deployment, base_dir=base_dir, server_endpoint=server_endpoint) agents = _extend_agents(agents) output['agents'] = agents LOG.debug('Deployed agents: %s', agents) if not agents: raise Exception('No agents deployed.') if scenario_deployment: quorum = quorum_pkg.make_quorum(agents.keys(), message_queue, cfg.CONF.polling_interval, cfg.CONF.agent_loss_timeout, cfg.CONF.agent_join_timeout) else: # local quorum = quorum_pkg.make_local_quorum() matrix = cfg.CONF.matrix if 'matrix' in cfg.CONF else None if matrix: scenario['matrix'] = matrix execute(output, quorum, scenario['execution'], agents, matrix) except BaseException as e: if isinstance(e, KeyboardInterrupt): LOG.info('Caught SIGINT. Terminating') record = dict(id=utils.make_record_id(), status='interrupted') else: error_msg = 'Error while executing scenario: %s' % e LOG.exception(e) record = dict(id=utils.make_record_id(), status='error', stderr=error_msg) output['records'][record['id']] = record finally: if deployment: try: deployment.cleanup() except Exception as e: LOG.error('Failed to cleanup the deployment: %s', e, exc_info=True) # extend every record with reference to scenario for record in output['records'].values(): record['scenario'] = scenario['title'] return output
def play_scenario(scenario): deployment = None output = dict(scenario=scenario, records={}, agents={}, tests={}) try: deployment = deploy.Deployment() if _under_openstack(): deployment.connect_to_openstack( cfg.CONF.os_username, cfg.CONF.os_password, cfg.CONF.os_tenant_name, cfg.CONF.os_auth_url, cfg.CONF.os_region_name, cfg.CONF.external_net, cfg.CONF.flavor_name, cfg.CONF.image_name, cfg.CONF.os_cacert, cfg.CONF.os_insecure) base_dir = os.path.dirname(scenario['file_name']) scenario_deployment = scenario.get('deployment', {}) server_endpoint = (cfg.CONF.server_endpoint if 'server_endpoint' in cfg.CONF else None) agents = deployment.deploy(scenario_deployment, base_dir=base_dir, server_endpoint=server_endpoint) agents = _extend_agents(agents) output['agents'] = agents LOG.debug('Deployed agents: %s', agents) if not agents: raise Exception('No agents deployed.') if scenario_deployment: quorum = quorum_pkg.make_quorum(agents.keys(), server_endpoint, cfg.CONF.polling_interval, cfg.CONF.agent_loss_timeout, cfg.CONF.agent_join_timeout) else: # local quorum = quorum_pkg.make_local_quorum() matrix = cfg.CONF.matrix if 'matrix' in cfg.CONF else None if matrix: scenario['matrix'] = matrix execute(output, quorum, scenario['execution'], agents, matrix) except BaseException as e: if isinstance(e, KeyboardInterrupt): LOG.info('Caught SIGINT. Terminating') record = dict(id=utils.make_record_id(), status='interrupted') else: error_msg = 'Error while executing scenario: %s' % e LOG.error(error_msg) LOG.exception(e) record = dict(id=utils.make_record_id(), status='error', stderr=error_msg) output['records'][record['id']] = record finally: if deployment: try: deployment.cleanup() except Exception as e: LOG.error('Failed to cleanup the deployment: %s', e, exc_info=True) # extend every record with reference to scenario for record in output['records'].values(): record['scenario'] = scenario['title'] return output
def test_deploy_template_error_when_non_initialized(self): deployment = deploy.Deployment() self.assertRaises(deploy.DeploymentException, deployment.deploy, {'template': 'foo'})