コード例 #1
0
    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
        ]
コード例 #2
0
    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,
        ]
コード例 #3
0
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)
コード例 #4
0
    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,
        ]
コード例 #5
0
 def setUp(self):
     super(SimpleTenantUsageLimitsTestV21, self).setUp()
     self.controller = simple_tenant_usage_v21.SimpleTenantUsageController()
     self.tenant_id = 1
コード例 #6
0
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())
コード例 #7
0
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)