215 lines
8.0 KiB
Python
215 lines
8.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Copyright 2014 Objectif Libre
|
|
#
|
|
# 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 datetime
|
|
|
|
import mock
|
|
from oslo_messaging import conffixture
|
|
from stevedore import extension
|
|
from tooz import coordination
|
|
from tooz.drivers import file
|
|
|
|
from cloudkitty import collector
|
|
from cloudkitty import orchestrator
|
|
from cloudkitty.storage.v2 import influx
|
|
from cloudkitty import storage_state
|
|
from cloudkitty import tests
|
|
from cloudkitty.utils import tz as tzutils
|
|
|
|
|
|
class FakeKeystoneClient(object):
|
|
|
|
class FakeTenants(object):
|
|
def list(self):
|
|
return ['f266f30b11f246b589fd266f85eeec39',
|
|
'4dfb25b0947c4f5481daf7b948c14187']
|
|
|
|
tenants = FakeTenants()
|
|
|
|
|
|
class ScopeEndpointTest(tests.TestCase):
|
|
def setUp(self):
|
|
super(ScopeEndpointTest, self).setUp()
|
|
messaging_conf = self.useFixture(conffixture.ConfFixture(self.conf))
|
|
messaging_conf.transport_url = 'fake:/'
|
|
self.conf.set_override('backend', 'influxdb', 'storage')
|
|
|
|
def test_reset_state(self):
|
|
coord_start_patch = mock.patch.object(
|
|
coordination.CoordinationDriverWithExecutor, 'start')
|
|
lock_acquire_patch = mock.patch.object(
|
|
file.FileLock, 'acquire', return_value=True)
|
|
|
|
storage_delete_patch = mock.patch.object(
|
|
influx.InfluxStorage, 'delete')
|
|
state_set_patch = mock.patch.object(
|
|
storage_state.StateManager, 'set_state')
|
|
|
|
with coord_start_patch, lock_acquire_patch, \
|
|
storage_delete_patch as sd, state_set_patch as ss:
|
|
|
|
endpoint = orchestrator.ScopeEndpoint()
|
|
endpoint.reset_state({}, {
|
|
'scopes': [
|
|
{
|
|
'scope_id': 'f266f30b11f246b589fd266f85eeec39',
|
|
'scope_key': 'project_id',
|
|
'collector': 'prometheus',
|
|
'fetcher': 'prometheus',
|
|
},
|
|
{
|
|
'scope_id': '4dfb25b0947c4f5481daf7b948c14187',
|
|
'scope_key': 'project_id',
|
|
'collector': 'gnocchi',
|
|
'fetcher': 'gnocchi',
|
|
},
|
|
],
|
|
'state': '20190716T085501Z',
|
|
})
|
|
|
|
sd.assert_has_calls([
|
|
mock.call(
|
|
begin=tzutils.utc_to_local(
|
|
datetime.datetime(2019, 7, 16, 8, 55, 1)),
|
|
end=None,
|
|
filters={'project_id': 'f266f30b11f246b589fd266f85eeec39'}
|
|
),
|
|
mock.call(
|
|
begin=tzutils.utc_to_local(
|
|
datetime.datetime(2019, 7, 16, 8, 55, 1)),
|
|
end=None,
|
|
filters={'project_id': '4dfb25b0947c4f5481daf7b948c14187'},
|
|
)
|
|
], any_order=True)
|
|
|
|
ss.assert_has_calls([
|
|
mock.call(
|
|
'f266f30b11f246b589fd266f85eeec39',
|
|
tzutils.utc_to_local(
|
|
datetime.datetime(2019, 7, 16, 8, 55, 1)),
|
|
scope_key='project_id',
|
|
collector='prometheus',
|
|
fetcher='prometheus'),
|
|
mock.call(
|
|
'4dfb25b0947c4f5481daf7b948c14187',
|
|
tzutils.utc_to_local(
|
|
datetime.datetime(2019, 7, 16, 8, 55, 1)),
|
|
scope_key='project_id',
|
|
collector='gnocchi',
|
|
fetcher='gnocchi')], any_order=True)
|
|
|
|
|
|
class OrchestratorTest(tests.TestCase):
|
|
def setUp(self):
|
|
super(OrchestratorTest, self).setUp()
|
|
messaging_conf = self.useFixture(conffixture.ConfFixture(self.conf))
|
|
messaging_conf.transport_url = 'fake:/'
|
|
self.conf.set_override('backend', 'keystone', 'fetcher')
|
|
self.conf.import_group('fetcher_keystone',
|
|
'cloudkitty.fetcher.keystone')
|
|
|
|
def setup_fake_modules(self):
|
|
fake_module1 = tests.FakeRatingModule()
|
|
fake_module1.module_name = 'fake1'
|
|
fake_module1.set_priority(3)
|
|
fake_module2 = tests.FakeRatingModule()
|
|
fake_module2.module_name = 'fake2'
|
|
fake_module2.set_priority(1)
|
|
fake_module3 = tests.FakeRatingModule()
|
|
fake_module3.module_name = 'fake3'
|
|
fake_module3.set_priority(2)
|
|
fake_extensions = [
|
|
extension.Extension(
|
|
'fake1',
|
|
'cloudkitty.tests.FakeRatingModule1',
|
|
None,
|
|
fake_module1),
|
|
extension.Extension(
|
|
'fake2',
|
|
'cloudkitty.tests.FakeRatingModule2',
|
|
None,
|
|
fake_module2),
|
|
extension.Extension(
|
|
'fake3',
|
|
'cloudkitty.tests.FakeRatingModule3',
|
|
None,
|
|
fake_module3)]
|
|
return fake_extensions
|
|
|
|
def test_processors_ordering_in_workers(self):
|
|
fake_extensions = self.setup_fake_modules()
|
|
ck_ext_mgr = 'cloudkitty.extension_manager.EnabledExtensionManager'
|
|
with mock.patch(ck_ext_mgr) as stevemock:
|
|
fake_mgr = extension.ExtensionManager.make_test_instance(
|
|
fake_extensions,
|
|
'cloudkitty.rating.processors')
|
|
stevemock.return_value = fake_mgr
|
|
worker = orchestrator.BaseWorker()
|
|
stevemock.assert_called_once_with(
|
|
'cloudkitty.rating.processors',
|
|
invoke_kwds={'tenant_id': None})
|
|
self.assertEqual('fake1', worker._processors[0].name)
|
|
self.assertEqual(3, worker._processors[0].obj.priority)
|
|
self.assertEqual('fake3', worker._processors[1].name)
|
|
self.assertEqual(2, worker._processors[1].obj.priority)
|
|
self.assertEqual('fake2', worker._processors[2].name)
|
|
self.assertEqual(1, worker._processors[2].obj.priority)
|
|
|
|
|
|
class WorkerTest(tests.TestCase):
|
|
|
|
def setUp(self):
|
|
super(WorkerTest, self).setUp()
|
|
|
|
class FakeWorker(orchestrator.Worker):
|
|
def __init__(self):
|
|
self._tenant_id = 'a'
|
|
self._worker_id = '0'
|
|
self._log_prefix = '[IGNORE THIS MESSAGE]'
|
|
|
|
self.worker = FakeWorker()
|
|
self.worker._collect = mock.MagicMock()
|
|
|
|
def test_do_collection_all_valid(self):
|
|
metrics = ['metric{}'.format(i) for i in range(5)]
|
|
side_effect = [(
|
|
metrics[i],
|
|
{'period': {'begin': 0,
|
|
'end': 3600},
|
|
'usage': i},
|
|
) for i in range(5)]
|
|
self.worker._collect.side_effect = side_effect
|
|
output = sorted(self.worker._do_collection(metrics, 0).items(),
|
|
key=lambda x: x[1]['usage'])
|
|
self.assertEqual(side_effect, output)
|
|
|
|
def test_do_collection_some_empty(self):
|
|
metrics = ['metric{}'.format(i) for i in range(7)]
|
|
side_effect = [(
|
|
metrics[i],
|
|
{'period': {'begin': 0,
|
|
'end': 3600},
|
|
'usage': i},
|
|
) for i in range(5)]
|
|
side_effect.insert(2, collector.NoDataCollected('a', 'b'))
|
|
side_effect.insert(4, collector.NoDataCollected('a', 'b'))
|
|
self.worker._collect.side_effect = side_effect
|
|
output = sorted(self.worker._do_collection(metrics, 0).items(),
|
|
key=lambda x: x[1]['usage'])
|
|
self.assertEqual([
|
|
i for i in side_effect
|
|
if not isinstance(i, collector.NoDataCollected)
|
|
], output)
|