panko/ceilometer/tests/objectstore/test_rgw.py
Swami Reddy 98005590ef Add ceph object storage meters
Implemented pollster classes to get the basic meters from ceph
object storage (i.e radosgw) and added corresponding unittests.

DocImpact

Co-Authored-By: Abhishek Lekshmanan <abhishek.lekshmanan@ril.com>

Change-Id: Ib90b1d5bbaa36760a2563a044ab256c045772e20
Implements: blueprint ceph-ceilometer-integration
2015-02-24 17:25:47 +05:30

180 lines
7.1 KiB
Python

#!/usr/bin/env python
#
# 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 keystoneclient 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')]
class TestManager(manager.AgentManager):
def __init__(self):
super(TestManager, self).__init__()
self.keystone = mock.MagicMock()
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
def fake_ks_service_catalog_url_for(*args, **kwargs):
raise exceptions.EndpointNotFound("Fake keystone exception")
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())
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
def tearDown(self):
super(TestRgwPollster, self).tearDown()
rgw._Base._ENDPOINT = None
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)
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)
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__)
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]))
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.keystone.service_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)
def test_get_endpoint_only_once(self):
mock_url_for = mock.MagicMock()
api_method = 'get_%s' % self.pollster.METHOD
with mockpatch.PatchObject(rgw_client, api_method,
new=mock.MagicMock()):
with mockpatch.PatchObject(
self.manager.keystone.service_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)
def test_endpoint_notfound(self):
with mockpatch.PatchObject(
self.manager.keystone.service_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))