def setUp(self): super(SimpleTenantUsagePolicyTest, self).setUp() self.controller = simple_tenant_usage.SimpleTenantUsageController() self.req = fakes.HTTPRequest.blank('') self.controller._get_instances_all_cells = mock.MagicMock() # Check that reader(legacy admin) or and owner is able to get # the tenant usage statistics for a specific tenant. self.reader_or_owner_authorized_contexts = [ self.legacy_admin_context, self.system_admin_context, self.project_admin_context, self.project_member_context, self.project_reader_context, self.project_foo_context, self.system_member_context, self.system_reader_context ] # Check that non-reader(legacy non-admin) or owner is not able to get # the tenant usage statistics for a specific tenant. self.reader_or_owner_unauthorized_contexts = [ self.system_foo_context, self.other_project_member_context, self.other_project_reader_context ] # Check that reader is able to get the tenant usage statistics. self.reader_authorized_contexts = [ self.legacy_admin_context, self.system_admin_context, self.project_admin_context, self.system_member_context, self.system_reader_context ] # Check that non-reader is not able to get the tenant usage statistics. self.reader_unauthorized_contexts = [ self.system_foo_context, self.project_member_context, self.other_project_member_context, self.project_foo_context, self.project_reader_context, self.other_project_reader_context ]
def setUp(self): super(SimpleTenantUsagePolicyTest, self).setUp() self.controller = simple_tenant_usage.SimpleTenantUsageController() self.req = fakes.HTTPRequest.blank('') self.controller._get_instances_all_cells = mock.MagicMock() # Currently any admin can list other project usage. self.project_admin_authorized_contexts = [ self.legacy_admin_context, self.system_admin_context, self.project_admin_context] # and project reader can get their usage statistics. self.project_reader_authorized_contexts = [ self.legacy_admin_context, self.system_admin_context, self.project_admin_context, self.project_member_context, self.project_reader_context, self.project_foo_context, ]
class SimpleTenantUsageControllerTestV21(test.TestCase): controller = simple_tenant_usage_v21.SimpleTenantUsageController() def setUp(self): super(SimpleTenantUsageControllerTestV21, self).setUp() self.context = context.RequestContext('fakeuser', 'fake-project') self.baseinst = get_fake_db_instance(START, STOP, instance_id=1, tenant_id=self.context.project_id, vm_state=vm_states.DELETED) # convert the fake instance dict to an object flavor = fake_flavor.fake_flavor_obj(self.context, **FAKE_INST_TYPE) self.inst_obj = objects.Instance._from_db_object( self.context, objects.Instance(), self.baseinst) self.inst_obj.flavor = flavor @mock.patch('nova.objects.Instance.get_flavor', side_effect=exception.NotFound()) def test_get_flavor_from_non_deleted_with_id_fails(self, fake_get_flavor): # If an instance is not deleted and missing type information from # instance.flavor, then that's a bug self.assertRaises(exception.NotFound, self.controller._get_flavor, self.context, self.inst_obj, {}) @mock.patch('nova.objects.Instance.get_flavor', side_effect=exception.NotFound()) def test_get_flavor_from_deleted_with_notfound(self, fake_get_flavor): # If the flavor is not found from the instance and the instance is # deleted, attempt to look it up from the DB and if found we're OK. self.inst_obj.deleted = 1 flavor = self.controller._get_flavor(self.context, self.inst_obj, {}) self.assertEqual(objects.Flavor, type(flavor)) self.assertEqual(FAKE_INST_TYPE['id'], flavor.id) @mock.patch('nova.objects.Instance.get_flavor', side_effect=exception.NotFound()) def test_get_flavor_from_deleted_with_id_of_deleted(self, fake_get_flavor): # Verify the legacy behavior of instance_type_id pointing to a # missing type being non-fatal self.inst_obj.deleted = 1 self.inst_obj.instance_type_id = 99 flavor = self.controller._get_flavor(self.context, self.inst_obj, {}) self.assertIsNone(flavor)
def setUp(self): super(SimpleTenantUsagePolicyTest, self).setUp() self.controller = simple_tenant_usage.SimpleTenantUsageController() self.req = fakes.HTTPRequest.blank('') # Check that admin or and owner is able to get # the tenant usage statistics for a specific tenant. self.admin_or_owner_authorized_contexts = [ self.legacy_admin_context, self.system_admin_context, self.project_admin_context, self.project_member_context, self.project_reader_context, self.project_foo_context ] # Check that non-admin/owner is not able to get # the tenant usage statistics for a specific tenant. self.admin_or_owner_unauthorized_contexts = [ self.system_member_context, self.system_reader_context, self.system_foo_context, self.other_project_member_context, self.other_project_reader_context, ] # Check that admin is able to get the tenant usage statistics. self.admin_authorized_contexts = [ self.legacy_admin_context, self.system_admin_context, self.project_admin_context ] # Check that non-admin is not able to get the tenant usage statistics. self.admin_unauthorized_contexts = [ self.system_member_context, self.system_reader_context, self.system_foo_context, self.project_member_context, self.other_project_member_context, self.project_foo_context, self.project_reader_context, self.other_project_reader_context, ]
def setUp(self): super(SimpleTenantUsageLimitsTestV21, self).setUp() self.controller = simple_tenant_usage_v21.SimpleTenantUsageController() self.tenant_id = 1
class SimpleTenantUsageTestV21(test.TestCase): version = '2.1' policy_rule_prefix = "os_compute_api:os-simple-tenant-usage" controller = simple_tenant_usage_v21.SimpleTenantUsageController() def setUp(self): super(SimpleTenantUsageTestV21, self).setUp() self.admin_context = context.RequestContext('fakeadmin_0', 'faketenant_0', is_admin=True) self.user_context = context.RequestContext('fakeadmin_0', 'faketenant_0', is_admin=False) self.alt_user_context = context.RequestContext('fakeadmin_0', 'faketenant_1', is_admin=False) def _test_verify_index(self, start, stop, limit=None): url = '?start=%s&end=%s' if limit: url += '&limit=%s' % (limit) req = fakes.HTTPRequest.blank(url % (start.isoformat(), stop.isoformat()), version=self.version) req.environ['nova.context'] = self.admin_context res_dict = self.controller.index(req) usages = res_dict['tenant_usages'] for i in range(TENANTS): self.assertEqual(SERVERS * HOURS, int(usages[i]['total_hours'])) self.assertEqual(SERVERS * (ROOT_GB + EPHEMERAL_GB) * HOURS, int(usages[i]['total_local_gb_usage'])) self.assertEqual(SERVERS * MEMORY_MB * HOURS, int(usages[i]['total_memory_mb_usage'])) self.assertEqual(SERVERS * VCPUS * HOURS, int(usages[i]['total_vcpus_usage'])) self.assertFalse(usages[i].get('server_usages')) if limit: self.assertIn('tenant_usages_links', res_dict) self.assertEqual('next', res_dict['tenant_usages_links'][0]['rel']) else: self.assertNotIn('tenant_usages_links', res_dict) def test_verify_index(self): self._test_verify_index(START, STOP) def test_verify_index_future_end_time(self): future = NOW + datetime.timedelta(hours=HOURS) self._test_verify_index(START, future) def test_verify_show(self): self._test_verify_show(START, STOP) def test_verify_show_future_end_time(self): future = NOW + datetime.timedelta(hours=HOURS) self._test_verify_show(START, future) def _get_tenant_usages(self, detailed=''): req = fakes.HTTPRequest.blank( '?detailed=%s&start=%s&end=%s' % (detailed, START.isoformat(), STOP.isoformat()), version=self.version) req.environ['nova.context'] = self.admin_context # Make sure that get_active_by_window_joined is only called with # expected_attrs=['flavor']. orig_get_active_by_window_joined = ( objects.InstanceList.get_active_by_window_joined) def fake_get_active_by_window_joined(context, begin, end=None, project_id=None, host=None, expected_attrs=None, use_slave=False, limit=None, marker=None): self.assertEqual(['flavor'], expected_attrs) return orig_get_active_by_window_joined(context, begin, end, project_id, host, expected_attrs, use_slave) with mock.patch.object(objects.InstanceList, 'get_active_by_window_joined', side_effect=fake_get_active_by_window_joined): res_dict = self.controller.index(req) return res_dict['tenant_usages'] def test_verify_detailed_index(self): usages = self._get_tenant_usages('1') for i in range(TENANTS): servers = usages[i]['server_usages'] for j in range(SERVERS): self.assertEqual(HOURS, int(servers[j]['hours'])) def test_verify_simple_index(self): usages = self._get_tenant_usages(detailed='0') for i in range(TENANTS): self.assertIsNone(usages[i].get('server_usages')) def test_verify_simple_index_empty_param(self): # NOTE(lzyeval): 'detailed=&start=..&end=..' usages = self._get_tenant_usages() for i in range(TENANTS): self.assertIsNone(usages[i].get('server_usages')) def _test_verify_show(self, start, stop, limit=None): tenant_id = 1 url = '?start=%s&end=%s' if limit: url += '&limit=%s' % (limit) req = fakes.HTTPRequest.blank(url % (start.isoformat(), stop.isoformat()), version=self.version) req.environ['nova.context'] = self.user_context res_dict = self.controller.show(req, tenant_id) usage = res_dict['tenant_usage'] servers = usage['server_usages'] self.assertEqual(TENANTS * SERVERS, len(usage['server_usages'])) server_uuids = [ getattr(uuids, 'instance_%d' % x) for x in range(SERVERS) ] for j in range(SERVERS): delta = STOP - START # NOTE(javeme): cast seconds from float to int for clarity uptime = int(delta.total_seconds()) self.assertEqual(uptime, int(servers[j]['uptime'])) self.assertEqual(HOURS, int(servers[j]['hours'])) self.assertIn(servers[j]['instance_id'], server_uuids) if limit: self.assertIn('tenant_usage_links', res_dict) self.assertEqual('next', res_dict['tenant_usage_links'][0]['rel']) else: self.assertNotIn('tenant_usage_links', res_dict) def test_verify_show_cannot_view_other_tenant(self): req = fakes.HTTPRequest.blank('?start=%s&end=%s' % (START.isoformat(), STOP.isoformat()), version=self.version) req.environ['nova.context'] = self.alt_user_context rules = { self.policy_rule_prefix + ":show": [["role:admin"], ["project_id:%(project_id)s"]] } policy.set_rules(oslo_policy.Rules.from_dict(rules)) try: self.assertRaises(exception.PolicyNotAuthorized, self.controller.show, req, 'faketenant_0') finally: policy.reset() def test_get_tenants_usage_with_bad_start_date(self): future = NOW + datetime.timedelta(hours=HOURS) req = fakes.HTTPRequest.blank('?start=%s&end=%s' % (future.isoformat(), NOW.isoformat()), version=self.version) req.environ['nova.context'] = self.user_context self.assertRaises(webob.exc.HTTPBadRequest, self.controller.show, req, 'faketenant_0') def test_get_tenants_usage_with_invalid_start_date(self): req = fakes.HTTPRequest.blank('?start=%s&end=%s' % ("xxxx", NOW.isoformat()), version=self.version) req.environ['nova.context'] = self.user_context self.assertRaises(webob.exc.HTTPBadRequest, self.controller.show, req, 'faketenant_0') def _test_get_tenants_usage_with_one_date(self, date_url_param): req = fakes.HTTPRequest.blank('?%s' % date_url_param, version=self.version) req.environ['nova.context'] = self.user_context res = self.controller.show(req, 'faketenant_0') self.assertIn('tenant_usage', res) def test_get_tenants_usage_with_no_start_date(self): self._test_get_tenants_usage_with_one_date( 'end=%s' % (NOW + datetime.timedelta(5)).isoformat()) def test_get_tenants_usage_with_no_end_date(self): self._test_get_tenants_usage_with_one_date( 'start=%s' % (NOW - datetime.timedelta(5)).isoformat())
class SimpleTenantUsageTestV21(test.TestCase): version = '2.1' policy_rule_prefix = "os_compute_api:os-simple-tenant-usage" controller = simple_tenant_usage_v21.SimpleTenantUsageController() def setUp(self): super(SimpleTenantUsageTestV21, self).setUp() self.admin_context = context.RequestContext('fakeadmin_0', 'faketenant_0', is_admin=True) self.user_context = context.RequestContext('fakeadmin_0', 'faketenant_0', is_admin=False) self.alt_user_context = context.RequestContext('fakeadmin_0', 'faketenant_1', is_admin=False) self.num_cells = len(objects.CellMappingList.get_all( self.admin_context)) def _test_verify_index(self, start, stop, limit=None): url = '?start=%s&end=%s' if limit: url += '&limit=%s' % (limit) req = fakes.HTTPRequest.blank(url % (start.isoformat(), stop.isoformat()), version=self.version) req.environ['nova.context'] = self.admin_context res_dict = self.controller.index(req) usages = res_dict['tenant_usages'] if limit: num = 1 else: # NOTE(danms): We call our fake data mock once per cell, # and the default fixture has two cells (cell0 and cell1), # so all our math will be doubled. num = self.num_cells for i in range(TENANTS): self.assertEqual(SERVERS * HOURS * num, int(usages[i]['total_hours'])) self.assertEqual(SERVERS * (ROOT_GB + EPHEMERAL_GB) * HOURS * num, int(usages[i]['total_local_gb_usage'])) self.assertEqual(SERVERS * MEMORY_MB * HOURS * num, int(usages[i]['total_memory_mb_usage'])) self.assertEqual(SERVERS * VCPUS * HOURS * num, int(usages[i]['total_vcpus_usage'])) self.assertFalse(usages[i].get('server_usages')) if limit: self.assertIn('tenant_usages_links', res_dict) self.assertEqual('next', res_dict['tenant_usages_links'][0]['rel']) else: self.assertNotIn('tenant_usages_links', res_dict) # NOTE(artom) Test for bugs 1643444 and 1692893 (duplicates). We simulate a # situation where an instance has been deleted (moved to shadow table) and # its corresponding instance_extra row has been archived (deleted from # shadow table). @mock.patch('nova.objects.InstanceList.get_active_by_window_joined', fake_get_active_deleted_flavorless) @mock.patch.object( objects.Instance, '_load_flavor', side_effect=exception.InstanceNotFound(instance_id='fake-id')) def test_verify_index_deleted_flavorless(self, mock_load): with mock.patch.object(self.controller, '_get_flavor', return_value=None): self._test_verify_index(START, STOP) @mock.patch('nova.objects.InstanceList.get_active_by_window_joined', fake_get_active_by_window_joined) def test_verify_index(self): self._test_verify_index(START, STOP) @mock.patch('nova.objects.InstanceList.get_active_by_window_joined', fake_get_active_by_window_joined) def test_verify_index_future_end_time(self): future = NOW + datetime.timedelta(hours=HOURS) self._test_verify_index(START, future) def test_verify_show(self): self._test_verify_show(START, STOP) def test_verify_show_future_end_time(self): future = NOW + datetime.timedelta(hours=HOURS) self._test_verify_show(START, future) @mock.patch('nova.objects.InstanceList.get_active_by_window_joined', fake_get_active_by_window_joined) def _get_tenant_usages(self, detailed=''): req = fakes.HTTPRequest.blank('?detailed=%s&start=%s&end=%s' % (detailed, START.isoformat(), STOP.isoformat()), version=self.version) req.environ['nova.context'] = self.admin_context # Make sure that get_active_by_window_joined is only called with # expected_attrs=['flavor']. orig_get_active_by_window_joined = ( objects.InstanceList.get_active_by_window_joined) def fake_get_active_by_window_joined(context, begin, end=None, project_id=None, host=None, expected_attrs=None, use_slave=False, limit=None, marker=None): self.assertEqual(['flavor'], expected_attrs) return orig_get_active_by_window_joined(context, begin, end, project_id, host, expected_attrs, use_slave) with mock.patch.object(objects.InstanceList, 'get_active_by_window_joined', side_effect=fake_get_active_by_window_joined): res_dict = self.controller.index(req) return res_dict['tenant_usages'] def test_verify_detailed_index(self): usages = self._get_tenant_usages('1') for i in range(TENANTS): servers = usages[i]['server_usages'] for j in range(SERVERS): self.assertEqual(HOURS, int(servers[j]['hours'])) def test_verify_simple_index(self): usages = self._get_tenant_usages(detailed='0') for i in range(TENANTS): self.assertIsNone(usages[i].get('server_usages')) def test_verify_simple_index_empty_param(self): # NOTE(lzyeval): 'detailed=&start=..&end=..' usages = self._get_tenant_usages() for i in range(TENANTS): self.assertIsNone(usages[i].get('server_usages')) @mock.patch('nova.objects.InstanceList.get_active_by_window_joined', fake_get_active_by_window_joined) def _test_verify_show(self, start, stop, limit=None): tenant_id = 1 url = '?start=%s&end=%s' if limit: url += '&limit=%s' % (limit) req = fakes.HTTPRequest.blank(url % (start.isoformat(), stop.isoformat()), version=self.version) req.environ['nova.context'] = self.user_context res_dict = self.controller.show(req, tenant_id) if limit: num = 1 else: # NOTE(danms): We call our fake data mock once per cell, # and the default fixture has two cells (cell0 and cell1), # so all our math will be doubled. num = self.num_cells usage = res_dict['tenant_usage'] servers = usage['server_usages'] self.assertEqual(TENANTS * SERVERS * num, len(usage['server_usages'])) server_uuids = [getattr(uuids, 'instance_%d' % x) for x in range(SERVERS)] for j in range(SERVERS): delta = STOP - START # NOTE(javeme): cast seconds from float to int for clarity uptime = int(delta.total_seconds()) self.assertEqual(uptime, int(servers[j]['uptime'])) self.assertEqual(HOURS, int(servers[j]['hours'])) self.assertIn(servers[j]['instance_id'], server_uuids) if limit: self.assertIn('tenant_usage_links', res_dict) self.assertEqual('next', res_dict['tenant_usage_links'][0]['rel']) else: self.assertNotIn('tenant_usage_links', res_dict) def test_verify_show_cannot_view_other_tenant(self): req = fakes.HTTPRequest.blank('?start=%s&end=%s' % (START.isoformat(), STOP.isoformat()), version=self.version) req.environ['nova.context'] = self.alt_user_context rules = { self.policy_rule_prefix + ":show": [ ["role:admin"], ["project_id:%(project_id)s"]] } policy.set_rules(oslo_policy.Rules.from_dict(rules)) try: self.assertRaises(exception.PolicyNotAuthorized, self.controller.show, req, 'faketenant_0') finally: policy.reset() def test_get_tenants_usage_with_bad_start_date(self): future = NOW + datetime.timedelta(hours=HOURS) req = fakes.HTTPRequest.blank('?start=%s&end=%s' % (future.isoformat(), NOW.isoformat()), version=self.version) req.environ['nova.context'] = self.user_context self.assertRaises(webob.exc.HTTPBadRequest, self.controller.show, req, 'faketenant_0') def test_get_tenants_usage_with_invalid_start_date(self): req = fakes.HTTPRequest.blank('?start=%s&end=%s' % ("xxxx", NOW.isoformat()), version=self.version) req.environ['nova.context'] = self.user_context self.assertRaises(webob.exc.HTTPBadRequest, self.controller.show, req, 'faketenant_0') def _test_get_tenants_usage_with_one_date(self, date_url_param): req = fakes.HTTPRequest.blank('?%s' % date_url_param, version=self.version) req.environ['nova.context'] = self.user_context res = self.controller.show(req, 'faketenant_0') self.assertIn('tenant_usage', res) def test_get_tenants_usage_with_no_start_date(self): self._test_get_tenants_usage_with_one_date( 'end=%s' % (NOW + datetime.timedelta(5)).isoformat()) def test_get_tenants_usage_with_no_end_date(self): self._test_get_tenants_usage_with_one_date( 'start=%s' % (NOW - datetime.timedelta(5)).isoformat()) def test_index_additional_query_parameters(self): req = fakes.HTTPRequest.blank('?start=%s&end=%s&additional=1' % (START.isoformat(), STOP.isoformat()), version=self.version) res = self.controller.index(req) self.assertIn('tenant_usages', res) def _test_index_duplicate_query_parameters_validation(self, params): for param, value in params.items(): req = fakes.HTTPRequest.blank('?start=%s&%s=%s&%s=%s' % (START.isoformat(), param, value, param, value), version=self.version) res = self.controller.index(req) self.assertIn('tenant_usages', res) def test_index_duplicate_query_parameters_validation(self): params = { 'start': START.isoformat(), 'end': STOP.isoformat(), 'detailed': 1 } self._test_index_duplicate_query_parameters_validation(params) def test_show_additional_query_parameters(self): req = fakes.HTTPRequest.blank('?start=%s&end=%s&additional=1' % (START.isoformat(), STOP.isoformat()), version=self.version) res = self.controller.show(req, 1) self.assertIn('tenant_usage', res) def _test_show_duplicate_query_parameters_validation(self, params): for param, value in params.items(): req = fakes.HTTPRequest.blank('?start=%s&%s=%s&%s=%s' % (START.isoformat(), param, value, param, value), version=self.version) res = self.controller.show(req, 1) self.assertIn('tenant_usage', res) def test_show_duplicate_query_parameters_validation(self): params = { 'start': START.isoformat(), 'end': STOP.isoformat() } self._test_show_duplicate_query_parameters_validation(params)