# Copyright 2015 Reliance Jio Infocomm Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import collections
from keystoneauth1 import exceptions
import mock
from oslotest import base
from oslotest import mockpatch
import testscenarios.testcase
from ceilometer.agent import manager
from ceilometer.objectstore import rgw
from ceilometer.objectstore.rgw_client import RGWAdminClient as rgw_client
bucket_list1 = [rgw_client.Bucket('somefoo1', 10, 7)]
bucket_list2 = [rgw_client.Bucket('somefoo2', 2, 9)]
bucket_list3 = [rgw_client.Bucket('unlisted', 100, 100)]
GET_BUCKETS = [('tenant-000', {'num_buckets': 2, 'size': 1042,
'num_objects': 1001, 'buckets': bucket_list1}),
('tenant-001', {'num_buckets': 2, 'size': 1042,
'num_objects': 1001, 'buckets': bucket_list2}),
('tenant-002-ignored', {'num_buckets': 2, 'size': 1042,
'num_objects': 1001,
'buckets': bucket_list3})]
GET_USAGE = [('tenant-000', 10),
('tenant-001', 11),
('tenant-002-ignored', 12)]
Tenant = collections.namedtuple('Tenant', 'id')
ASSIGNED_TENANTS = [Tenant('tenant-000'), Tenant('tenant-001')]
[docs]class TestManager(manager.AgentManager):
def __init__(self):
super(TestManager, self).__init__()
self._keystone = mock.Mock()
self._catalog = (self._keystone.session.auth.get_access.
return_value.service_catalog)
self._catalog.url_for.return_value = 'http://foobar/endpoint'
[docs]class TestRgwPollster(testscenarios.testcase.WithScenarios,
base.BaseTestCase):
# Define scenarios to run all of the tests against all of the
# pollsters.
scenarios = [
('radosgw.objects',
{'factory': rgw.ObjectsPollster}),
('radosgw.objects.size',
{'factory': rgw.ObjectsSizePollster}),
('radosgw.objects.containers',
{'factory': rgw.ObjectsContainersPollster}),
('radosgw.containers.objects',
{'factory': rgw.ContainersObjectsPollster}),
('radosgw.containers.objects.size',
{'factory': rgw.ContainersSizePollster}),
('radosgw.api.request',
{'factory': rgw.UsagePollster}),
]
@staticmethod
[docs] def fake_ks_service_catalog_url_for(*args, **kwargs):
raise exceptions.EndpointNotFound("Fake keystone exception")
[docs] def fake_iter_accounts(self, ksclient, cache, tenants):
tenant_ids = [t.id for t in tenants]
for i in self.ACCOUNTS:
if i[0] in tenant_ids:
yield i
@mock.patch('ceilometer.pipeline.setup_pipeline', mock.MagicMock())
[docs] def setUp(self):
super(TestRgwPollster, self).setUp()
self.pollster = self.factory()
self.manager = TestManager()
if self.pollster.CACHE_KEY_METHOD == 'rgw.get_bucket':
self.ACCOUNTS = GET_BUCKETS
else:
self.ACCOUNTS = GET_USAGE
[docs] def tearDown(self):
super(TestRgwPollster, self).tearDown()
rgw._Base._ENDPOINT = None
[docs] def test_iter_accounts_no_cache(self):
cache = {}
with mockpatch.PatchObject(self.factory, '_get_account_info',
return_value=[]):
data = list(self.pollster._iter_accounts(mock.Mock(), cache,
ASSIGNED_TENANTS))
self.assertIn(self.pollster.CACHE_KEY_METHOD, cache)
self.assertEqual([], data)
[docs] def test_iter_accounts_cached(self):
# Verify that if a method has already been called, _iter_accounts
# uses the cached version and doesn't call rgw_clinet.
mock_method = mock.Mock()
mock_method.side_effect = AssertionError(
'should not be called',
)
api_method = 'get_%s' % self.pollster.METHOD
with mockpatch.PatchObject(rgw_client, api_method, new=mock_method):
cache = {self.pollster.CACHE_KEY_METHOD: [self.ACCOUNTS[0]]}
data = list(self.pollster._iter_accounts(mock.Mock(), cache,
ASSIGNED_TENANTS))
self.assertEqual([self.ACCOUNTS[0]], data)
[docs] def test_metering(self):
with mockpatch.PatchObject(self.factory, '_iter_accounts',
side_effect=self.fake_iter_accounts):
samples = list(self.pollster.get_samples(self.manager, {},
ASSIGNED_TENANTS))
self.assertEqual(2, len(samples), self.pollster.__class__)
[docs] def test_get_meter_names(self):
with mockpatch.PatchObject(self.factory, '_iter_accounts',
side_effect=self.fake_iter_accounts):
samples = list(self.pollster.get_samples(self.manager, {},
ASSIGNED_TENANTS))
self.assertEqual(set([samples[0].name]),
set([s.name for s in samples]))
[docs] def test_only_poll_assigned(self):
mock_method = mock.MagicMock()
endpoint = 'http://127.0.0.1:8000/admin'
api_method = 'get_%s' % self.pollster.METHOD
with mockpatch.PatchObject(rgw_client, api_method, new=mock_method):
with mockpatch.PatchObject(
self.manager._catalog, 'url_for',
return_value=endpoint):
list(self.pollster.get_samples(self.manager, {},
ASSIGNED_TENANTS))
expected = [mock.call(t.id)
for t in ASSIGNED_TENANTS]
self.assertEqual(expected, mock_method.call_args_list)
[docs] def test_get_endpoint_only_once(self):
mock_url_for = mock.MagicMock()
mock_url_for.return_value = '/endpoint'
api_method = 'get_%s' % self.pollster.METHOD
with mockpatch.PatchObject(rgw_client, api_method,
new=mock.MagicMock()):
with mockpatch.PatchObject(
self.manager._catalog, 'url_for',
new=mock_url_for):
list(self.pollster.get_samples(self.manager, {},
ASSIGNED_TENANTS))
list(self.pollster.get_samples(self.manager, {},
ASSIGNED_TENANTS))
self.assertEqual(1, mock_url_for.call_count)
[docs] def test_endpoint_notfound(self):
with mockpatch.PatchObject(
self.manager._catalog, 'url_for',
side_effect=self.fake_ks_service_catalog_url_for):
samples = list(self.pollster.get_samples(self.manager, {},
ASSIGNED_TENANTS))
self.assertEqual(0, len(samples))