def _fake_instlist(ctxt, id): if id == src_secgroup['id']: insts = objects.InstanceList() insts.objects.append(src_instance_ref) return insts else: insts = objects.InstanceList() insts.objects.append(instance_ref) return insts
def test_update_instance_info_unknown_host(self): self.host_manager._recreate_instance_info = mock.MagicMock() host_name = 'fake_host' inst1 = fake_instance.fake_instance_obj('fake_context', uuid='aaa', host=host_name) inst2 = fake_instance.fake_instance_obj('fake_context', uuid='bbb', host=host_name) orig_inst_dict = {inst1.uuid: inst1, inst2.uuid: inst2} self.host_manager._instance_info = { host_name: { 'instances': orig_inst_dict, 'updated': False, } } bad_host = 'bad_host' inst3 = fake_instance.fake_instance_obj('fake_context', uuid='ccc', host=bad_host) inst_list3 = objects.InstanceList(objects=[inst3]) self.host_manager.update_instance_info('fake_context', bad_host, inst_list3) new_info = self.host_manager._instance_info[host_name] self.host_manager._recreate_instance_info.assert_called_once_with( 'fake_context', bad_host) self.assertEqual(len(new_info['instances']), len(orig_inst_dict)) self.assertFalse(new_info['updated'])
def test_update_instance_info(self): host_name = 'fake_host' inst1 = fake_instance.fake_instance_obj('fake_context', uuid='aaa', host=host_name) inst2 = fake_instance.fake_instance_obj('fake_context', uuid='bbb', host=host_name) orig_inst_dict = {inst1.uuid: inst1, inst2.uuid: inst2} self.host_manager._instance_info = { host_name: { 'instances': orig_inst_dict, 'updated': False, } } inst3 = fake_instance.fake_instance_obj('fake_context', uuid='ccc', host=host_name) inst4 = fake_instance.fake_instance_obj('fake_context', uuid='ddd', host=host_name) update = objects.InstanceList(objects=[inst3, inst4]) self.host_manager.update_instance_info('fake_context', host_name, update) new_info = self.host_manager._instance_info[host_name] self.assertEqual(len(new_info['instances']), 4) self.assertTrue(new_info['updated'])
def fake_compute_get_all(*args, **kwargs): db_list = [ fakes.stub_instance(1, uuid=UUID1, nw_cache=NW_CACHE), fakes.stub_instance(2, uuid=UUID2, nw_cache=NW_CACHE), ] fields = instance_obj.INSTANCE_DEFAULT_FIELDS return instance_obj._make_instance_list(args[1], objects.InstanceList(), db_list, fields)
def test_get_all_host_states(self, mock_get_by_host): mock_get_by_host.return_value = objects.InstanceList() context = 'fake_context' self.mox.StubOutWithMock(objects.ServiceList, 'get_by_binary') self.mox.StubOutWithMock(objects.ComputeNodeList, 'get_all') self.mox.StubOutWithMock(host_manager.LOG, 'warning') objects.ServiceList.get_by_binary(context, 'patron-compute').AndReturn( fakes.SERVICES) objects.ComputeNodeList.get_all(context).AndReturn(fakes.COMPUTE_NODES) # node 3 host physical disk space is greater than database host_manager.LOG.warning( "Host %(hostname)s has more disk space " "than database expected (%(physical)sgb >" " %(database)sgb)", { 'physical': 3333, 'database': 3072, 'hostname': 'node3' }) # Invalid service host_manager.LOG.warning( "No compute service record found for " "host %(host)s", {'host': 'fake'}) self.mox.ReplayAll() self.host_manager.get_all_host_states(context) host_states_map = self.host_manager.host_state_map self.assertEqual(len(host_states_map), 4) # Check that .service is set properly for i in xrange(4): compute_node = fakes.COMPUTE_NODES[i] host = compute_node['host'] node = compute_node['hypervisor_hostname'] state_key = (host, node) self.assertEqual( host_states_map[state_key].service, obj_base.obj_to_primitive(fakes.get_service_by_host(host))) self.assertEqual(host_states_map[('host1', 'node1')].free_ram_mb, 512) # 511GB self.assertEqual(host_states_map[('host1', 'node1')].free_disk_mb, 524288) self.assertEqual(host_states_map[('host2', 'node2')].free_ram_mb, 1024) # 1023GB self.assertEqual(host_states_map[('host2', 'node2')].free_disk_mb, 1048576) self.assertEqual(host_states_map[('host3', 'node3')].free_ram_mb, 3072) # 3071GB self.assertEqual(host_states_map[('host3', 'node3')].free_disk_mb, 3145728) self.assertThat( objects.NUMATopology.obj_from_db_obj( host_states_map[('host3', 'node3')].numa_topology)._to_dict(), matchers.DictMatches(fakes.NUMA_TOPOLOGY._to_dict())) self.assertEqual(host_states_map[('host4', 'node4')].free_ram_mb, 8192) # 8191GB self.assertEqual(host_states_map[('host4', 'node4')].free_disk_mb, 8388608)
def fake_compute_get_all(*args, **kwargs): inst1 = fakes.stub_instance(1, uuid=UUID1, host="all-host", vm_state=vm_states.ACTIVE) inst2 = fakes.stub_instance(2, uuid=UUID2, host="all-host", vm_state=vm_states.ACTIVE) db_list = [inst1, inst2] fields = instance_obj.INSTANCE_DEFAULT_FIELDS return instance_obj._make_instance_list(args[1], objects.InstanceList(), db_list, fields)
def fake_compute_get_all(*args, **kwargs): db_list = [ fakes.stub_instance(2, uuid=UUID1, launched_at=DATE2, terminated_at=DATE3), fakes.stub_instance(3, uuid=UUID2, launched_at=DATE1, terminated_at=DATE3), ] fields = instance_obj.INSTANCE_DEFAULT_FIELDS return instance_obj._make_instance_list(args[1], objects.InstanceList(), db_list, fields)
def test_get_all_host_states_with_no_aggs(self, svc_get_by_binary, cn_get_all, update_from_cn, mock_get_by_host): svc_get_by_binary.return_value = [objects.Service(host='fake')] cn_get_all.return_value = [ objects.ComputeNode(host='fake', hypervisor_hostname='fake') ] mock_get_by_host.return_value = objects.InstanceList() self.host_manager.host_aggregates_map = collections.defaultdict(set) self.host_manager.get_all_host_states('fake-context') host_state = self.host_manager.host_state_map[('fake', 'fake')] self.assertEqual([], host_state.aggregates)
def test_get_all_host_states(self, mock_get_by_host): mock_get_by_host.return_value = objects.InstanceList() context = 'fake_context' self.mox.StubOutWithMock(objects.ServiceList, 'get_by_binary') self.mox.StubOutWithMock(objects.ComputeNodeList, 'get_all') objects.ServiceList.get_by_binary(context, 'patron-compute').AndReturn( fakes.SERVICES) objects.ComputeNodeList.get_all(context).AndReturn(fakes.COMPUTE_NODES) self.mox.ReplayAll() self.host_manager.get_all_host_states(context) host_states_map = self.host_manager.host_state_map self.assertEqual(len(host_states_map), 4)
def test_list_with_host(self): output = StringIO.StringIO() sys.stdout = output with mock.patch.object(objects.InstanceList, 'get_by_host') as get: get.return_value = objects.InstanceList(objects=[ fake_instance.fake_instance_obj(context.get_admin_context(), instance_type=self.fake_flavor, expected_attrs=('flavor')) ]) self.commands.list(host='fake-host') sys.stdout = sys.__stdout__ result = output.getvalue() self.assertIn('node', result) # check the header line self.assertIn('m1.tiny', result) # flavor.name self.assertIn('fake-host', result)
def fake_compute_get_all(*args, **kwargs): db_list = [ fakes.stub_instance(1, uuid=UUID1, task_state="task-1", vm_state="vm-1", power_state=1), fakes.stub_instance(2, uuid=UUID2, task_state="task-2", vm_state="vm-2", power_state=2), ] fields = instance_obj.INSTANCE_DEFAULT_FIELDS return instance_obj._make_instance_list(args[1], objects.InstanceList(), db_list, fields)
def test_init_instance_info(self, mock_spawn, mock_get_all, mock_get_by_filters): mock_spawn.side_effect = lambda f, *a, **k: f(*a, **k) cn1 = objects.ComputeNode(host='host1') cn2 = objects.ComputeNode(host='host2') inst1 = objects.Instance(host='host1', uuid='uuid1') inst2 = objects.Instance(host='host1', uuid='uuid2') inst3 = objects.Instance(host='host2', uuid='uuid3') mock_get_all.return_value = objects.ComputeNodeList(objects=[cn1, cn2]) mock_get_by_filters.return_value = objects.InstanceList( objects=[inst1, inst2, inst3]) hm = self.host_manager hm._instance_info = {} hm._init_instance_info() self.assertEqual(len(hm._instance_info), 2) fake_info = hm._instance_info['host1'] self.assertIn('uuid1', fake_info['instances']) self.assertIn('uuid2', fake_info['instances']) self.assertNotIn('uuid3', fake_info['instances'])
def test_get_all_host_states_with_not_matching_aggs( self, svc_get_by_binary, cn_get_all, update_from_cn, mock_get_by_host): svc_get_by_binary.return_value = [ objects.Service(host='fake'), objects.Service(host='other') ] cn_get_all.return_value = [ objects.ComputeNode(host='fake', hypervisor_hostname='fake'), objects.ComputeNode(host='other', hypervisor_hostname='other') ] mock_get_by_host.return_value = objects.InstanceList() fake_agg = objects.Aggregate(id=1) self.host_manager.host_aggregates_map = collections.defaultdict( set, {'other': set([1])}) self.host_manager.aggs_by_id = {1: fake_agg} self.host_manager.get_all_host_states('fake-context') host_state = self.host_manager.host_state_map[('fake', 'fake')] self.assertEqual([], host_state.aggregates)
def test_get_all_host_states_after_delete_all(self, mock_get_by_host): mock_get_by_host.return_value = objects.InstanceList() context = 'fake_context' self.mox.StubOutWithMock(objects.ServiceList, 'get_by_binary') self.mox.StubOutWithMock(objects.ComputeNodeList, 'get_all') # all nodes active for first call objects.ServiceList.get_by_binary(context, 'patron-compute').AndReturn( fakes.SERVICES) objects.ComputeNodeList.get_all(context).AndReturn(fakes.COMPUTE_NODES) # remove all nodes for second call objects.ServiceList.get_by_binary(context, 'patron-compute').AndReturn( fakes.SERVICES) objects.ComputeNodeList.get_all(context).AndReturn([]) self.mox.ReplayAll() self.host_manager.get_all_host_states(context) self.host_manager.get_all_host_states(context) host_states_map = self.host_manager.host_state_map self.assertEqual(len(host_states_map), 0)
def test_recreate_instance_info(self, mock_get_by_host): host_name = 'fake_host' inst1 = fake_instance.fake_instance_obj('fake_context', uuid='aaa', host=host_name) inst2 = fake_instance.fake_instance_obj('fake_context', uuid='bbb', host=host_name) orig_inst_dict = {inst1.uuid: inst1, inst2.uuid: inst2} new_inst_list = objects.InstanceList(objects=[inst1, inst2]) mock_get_by_host.return_value = new_inst_list self.host_manager._instance_info = { host_name: { 'instances': orig_inst_dict, 'updated': True, } } self.host_manager._recreate_instance_info('fake_context', host_name) new_info = self.host_manager._instance_info[host_name] self.assertEqual(len(new_info['instances']), len(new_inst_list)) self.assertFalse(new_info['updated'])
def build_instances(self, ctxt, build_inst_kwargs): """Pick a cell (possibly ourselves) to build new instance(s) and forward the request accordingly. """ # Target is ourselves first. filter_properties = build_inst_kwargs.get('filter_properties') if (filter_properties is not None and not isinstance( filter_properties['instance_type'], objects.Flavor)): # NOTE(danms): Handle pre-1.30 build_instances() call. Remove me # when we bump the RPC API version to 2.0. flavor = objects.Flavor(**filter_properties['instance_type']) build_inst_kwargs['filter_properties'] = dict(filter_properties, instance_type=flavor) instances = build_inst_kwargs['instances'] if not isinstance(instances[0], objects.Instance): # NOTE(danms): Handle pre-1.32 build_instances() call. Remove me # when we bump the RPC API version to 2.0 build_inst_kwargs['instances'] = instance_obj._make_instance_list( ctxt, objects.InstanceList(), instances, ['system_metadata', 'metadata']) our_cell = self.state_manager.get_my_state() self.msg_runner.build_instances(ctxt, our_cell, build_inst_kwargs)
def test_get_all_host_states_not_updated(self, mock_get_by_host, mock_get_all_comp, mock_get_svc_by_binary): mock_get_all_comp.return_value = fakes.COMPUTE_NODES mock_get_svc_by_binary.return_value = fakes.SERVICES context = 'fake_context' hm = self.host_manager inst1 = objects.Instance(uuid='uuid1') cn1 = objects.ComputeNode(host='host1') hm._instance_info = { 'host1': { 'instances': { 'uuid1': inst1 }, 'updated': False } } host_state = host_manager.HostState('host1', cn1) self.assertFalse(host_state.instances) mock_get_by_host.return_value = objects.InstanceList(objects=[inst1]) hm._add_instance_info(context, cn1, host_state) mock_get_by_host.assert_called_once_with(context, cn1.host) self.assertTrue(host_state.instances) self.assertEqual(host_state.instances['uuid1'], inst1)
def test_sync_power_states_instance_not_found(self): db_instance = fake_instance.fake_db_instance() ctxt = context.get_admin_context() instance_list = instance_obj._make_instance_list( ctxt, objects.InstanceList(), [db_instance], None) instance = instance_list[0] self.mox.StubOutWithMock(objects.InstanceList, 'get_by_host') self.mox.StubOutWithMock(self.compute.driver, 'get_num_instances') self.mox.StubOutWithMock(vm_utils, 'lookup') self.mox.StubOutWithMock(self.compute, '_sync_instance_power_state') objects.InstanceList.get_by_host( ctxt, self.compute.host, expected_attrs=[], use_slave=True).AndReturn(instance_list) self.compute.driver.get_num_instances().AndReturn(1) vm_utils.lookup(self.compute.driver._session, instance['name'], False).AndReturn(None) self.compute._sync_instance_power_state(ctxt, instance, power_state.NOSTATE) self.mox.ReplayAll() self.compute._sync_power_states(ctxt)
def fake_compute_get_all(*args, **kwargs): db_list = [fakes.stub_instance(1), fakes.stub_instance(2)] fields = instance_obj.INSTANCE_DEFAULT_FIELDS return instance_obj._make_instance_list(args[1], objects.InstanceList(), db_list, fields)
def _get_servers(self, req, is_detail): """Returns a list of servers, based on any search options specified.""" search_opts = {} search_opts.update(req.GET) context = req.environ['patron.context'] remove_invalid_options(context, search_opts, self._get_server_search_options()) # Verify search by 'status' contains a valid status. # Convert it to filter by vm_state or task_state for compute_api. search_opts.pop('status', None) if 'status' in req.GET.keys(): statuses = req.GET.getall('status') states = common.task_and_vm_state_from_status(statuses) vm_state, task_state = states if not vm_state and not task_state: return {'servers': []} search_opts['vm_state'] = vm_state # When we search by vm state, task state will return 'default'. # So we don't need task_state search_opt. if 'default' not in task_state: search_opts['task_state'] = task_state if 'changes-since' in search_opts: try: parsed = timeutils.parse_isotime(search_opts['changes-since']) except ValueError: msg = _('Invalid changes-since value') raise exc.HTTPBadRequest(explanation=msg) search_opts['changes-since'] = parsed # By default, compute's get_all() will return deleted instances. # If an admin hasn't specified a 'deleted' search option, we need # to filter out deleted instances by setting the filter ourselves. # ... Unless 'changes-since' is specified, because 'changes-since' # should return recently deleted images according to the API spec. if 'deleted' not in search_opts: if 'changes-since' not in search_opts: # No 'changes-since', so we only want non-deleted servers search_opts['deleted'] = False if search_opts.get("vm_state") == ['deleted']: if context.is_admin: search_opts['deleted'] = True else: msg = _("Only administrators may list deleted instances") raise exc.HTTPForbidden(explanation=msg) # If all tenants is passed with 0 or false as the value # then remove it from the search options. Nothing passed as # the value for all_tenants is considered to enable the feature all_tenants = search_opts.get('all_tenants') if all_tenants: try: if not strutils.bool_from_string(all_tenants, True): del search_opts['all_tenants'] except ValueError as err: raise exception.InvalidInput(six.text_type(err)) if 'all_tenants' in search_opts: policy.enforce(context, 'compute:get_all_tenants', { 'project_id': context.project_id, 'user_id': context.user_id }) del search_opts['all_tenants'] else: if context.project_id: search_opts['project_id'] = context.project_id else: search_opts['user_id'] = context.user_id limit, marker = common.get_limit_and_marker(req) # Sorting by multiple keys and directions is conditionally enabled sort_keys, sort_dirs = None, None if self.ext_mgr.is_loaded('os-server-sort-keys'): sort_keys, sort_dirs = common.get_sort_params(req.params) try: instance_list = self.compute_api.get_all(context, search_opts=search_opts, limit=limit, marker=marker, want_objects=True, sort_keys=sort_keys, sort_dirs=sort_dirs) except exception.MarkerNotFound: msg = _('marker [%s] not found') % marker raise exc.HTTPBadRequest(explanation=msg) except exception.FlavorNotFound: LOG.debug("Flavor '%s' could not be found", search_opts['flavor']) instance_list = objects.InstanceList() if is_detail: instance_list.fill_faults() response = self._view_builder.detail(req, instance_list) else: response = self._view_builder.index(req, instance_list) req.cache_db_instances(instance_list) return response
def _get_servers(self, req, is_detail): """Returns a list of servers, based on any search options specified.""" search_opts = {} search_opts.update(req.GET) context = req.environ['patron.context'] remove_invalid_options(context, search_opts, self._get_server_search_options()) # Verify search by 'status' contains a valid status. # Convert it to filter by vm_state or task_state for compute_api. search_opts.pop('status', None) if 'status' in req.GET.keys(): statuses = req.GET.getall('status') states = common.task_and_vm_state_from_status(statuses) vm_state, task_state = states if not vm_state and not task_state: return {'servers': []} search_opts['vm_state'] = vm_state # When we search by vm state, task state will return 'default'. # So we don't need task_state search_opt. if 'default' not in task_state: search_opts['task_state'] = task_state if 'changes-since' in search_opts: try: parsed = timeutils.parse_isotime(search_opts['changes-since']) except ValueError: msg = _('Invalid changes-since value') raise exc.HTTPBadRequest(explanation=msg) search_opts['changes-since'] = parsed # By default, compute's get_all() will return deleted instances. # If an admin hasn't specified a 'deleted' search option, we need # to filter out deleted instances by setting the filter ourselves. # ... Unless 'changes-since' is specified, because 'changes-since' # should return recently deleted images according to the API spec. if 'deleted' not in search_opts: if 'changes-since' not in search_opts: # No 'changes-since', so we only want non-deleted servers search_opts['deleted'] = False if search_opts.get("vm_state") == ['deleted']: if context.is_admin: search_opts['deleted'] = True else: msg = _("Only administrators may list deleted instances") raise exc.HTTPForbidden(explanation=msg) # If tenant_id is passed as a search parameter this should # imply that all_tenants is also enabled unless explicitly # disabled. Note that the tenant_id parameter is filtered out # by remove_invalid_options above unless the requestor is an # admin. # TODO(gmann): 'all_tenants' flag should not be required while # searching with 'tenant_id'. Ref bug# 1185290 # +microversions to achieve above mentioned behavior by # uncommenting below code. # if 'tenant_id' in search_opts and 'all_tenants' not in search_opts: # We do not need to add the all_tenants flag if the tenant # id associated with the token is the tenant id # specified. This is done so a request that does not need # the all_tenants flag does not fail because of lack of # policy permission for compute:get_all_tenants when it # doesn't actually need it. # if context.project_id != search_opts.get('tenant_id'): # search_opts['all_tenants'] = 1 # If all tenants is passed with 0 or false as the value # then remove it from the search options. Nothing passed as # the value for all_tenants is considered to enable the feature all_tenants = search_opts.get('all_tenants') if all_tenants: try: if not strutils.bool_from_string(all_tenants, True): del search_opts['all_tenants'] except ValueError as err: raise exception.InvalidInput(six.text_type(err)) if 'all_tenants' in search_opts: if is_detail: authorize(context, action="detail:get_all_tenants") else: authorize(context, action="index:get_all_tenants") del search_opts['all_tenants'] else: if context.project_id: search_opts['project_id'] = context.project_id else: search_opts['user_id'] = context.user_id limit, marker = common.get_limit_and_marker(req) sort_keys, sort_dirs = common.get_sort_params(req.params) try: instance_list = self.compute_api.get_all( context, search_opts=search_opts, limit=limit, marker=marker, want_objects=True, expected_attrs=['pci_devices'], sort_keys=sort_keys, sort_dirs=sort_dirs) except exception.MarkerNotFound: msg = _('marker [%s] not found') % marker raise exc.HTTPBadRequest(explanation=msg) except exception.FlavorNotFound: LOG.debug("Flavor '%s' could not be found ", search_opts['flavor']) instance_list = objects.InstanceList() if is_detail: instance_list.fill_faults() response = self._view_builder.detail(req, instance_list) else: response = self._view_builder.index(req, instance_list) req.cache_db_instances(instance_list) return response
def get_all(*args, **kwargs): fields = instance_obj.INSTANCE_DEFAULT_FIELDS return instance_obj._make_instance_list( args[1], objects.InstanceList(), instances, fields)