diff --git a/distil/common/openstack.py b/distil/common/openstack.py index a4ce9a7..0c8dc24 100644 --- a/distil/common/openstack.py +++ b/distil/common/openstack.py @@ -96,10 +96,36 @@ def get_nova_client(): @general.disable_ssl_warnings -def get_projects(): +def get_domain(domain): keystone = get_keystone_client() + try: + domain_obj = keystone.domains.get(domain) + except NotFound: + domains = keystone.domains.list(name=domain) + if not domains: + raise + domain_obj = domains[0] - return [obj.to_dict() for obj in keystone.projects.list()] + return domain_obj + + +@general.disable_ssl_warnings +def get_projects(domains=None): + keystone = get_keystone_client() + if not domains: + return [obj.to_dict() for obj in keystone.projects.list()] + + domain_objs = {} + for domain in domains: + domain_obj = get_domain(domain) + domain_objs[domain_obj.id] = domain_obj + + projects = [] + + for domain_obj in domain_objs.values(): + projects += [ + obj.to_dict() for obj in keystone.projects.list(domain=domain_obj)] + return projects @general.disable_ssl_warnings diff --git a/distil/config.py b/distil/config.py index 5fa2007..a233689 100644 --- a/distil/config.py +++ b/distil/config.py @@ -54,6 +54,8 @@ COLLECTOR_OPTS = [ help=('The meter mappings configuration.')), cfg.StrOpt('transformer_file', default='/etc/distil/transformer.yml', help=('The transformer configuration.')), + cfg.ListOpt('include_domains', default=[], + help=('Only collect usages for included domains.')), cfg.ListOpt('include_tenants', default=[], help=('Only collect usages for included tenants.')), cfg.ListOpt('ignore_tenants', default=[], diff --git a/distil/service/collector.py b/distil/service/collector.py index 8bdbf1d..d35f09f 100644 --- a/distil/service/collector.py +++ b/distil/service/collector.py @@ -117,7 +117,8 @@ class CollectorService(service.Service): "max_windows_per_cycle<=0.") return - projects = openstack.get_projects() + projects = openstack.get_projects( + domains=CONF.collector.include_domains) valid_projects = filter_projects(projects) project_ids = [p['id'] for p in valid_projects] diff --git a/distil/tests/unit/common/test_openstack.py b/distil/tests/unit/common/test_openstack.py new file mode 100644 index 0000000..d295620 --- /dev/null +++ b/distil/tests/unit/common/test_openstack.py @@ -0,0 +1,60 @@ +# 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 flask +import mock + +from keystoneauth1.exceptions import NotFound + +from distil import exceptions as ex +from distil.common import openstack +from distil.tests.unit import base + + +class TestOpenStack(base.DistilTestCase): + + @mock.patch('distil.common.openstack.get_keystone_client') + def test_get_domain(self, ks_client_factory): + ks_client = mock.MagicMock() + ks_client_factory.return_value = ks_client + + ks_client.domains.get.side_effect = NotFound() + ks_client.domains.list.return_value = ['domain_1'] + + my_domain = openstack.get_domain("some_domain_id") + ks_client.domains.get.assert_called_with("some_domain_id") + ks_client.domains.list.assert_called_with(name="some_domain_id") + self.assertEqual(my_domain, 'domain_1') + + @mock.patch('distil.common.openstack.get_keystone_client') + def test_get_projects(self, ks_client_factory): + ks_client = mock.MagicMock() + ks_client_factory.return_value = ks_client + + project_1 = mock.MagicMock() + project_1.to_dict.return_value = {'name': 'project_1'} + domain_1 = mock.MagicMock(id="domain_id_1") + + ks_client.projects.list.return_value = [project_1] + ks_client.domains.get.return_value = domain_1 + + projects = openstack.get_projects() + self.assertEqual([project_1.to_dict.return_value], projects) + ks_client.domains.get.assert_not_called() + ks_client.domains.list.assert_not_called() + + projects = openstack.get_projects(domains=['domain_1']) + + self.assertEqual([project_1.to_dict.return_value], projects) + ks_client.domains.get.assert_called_with("domain_1") + ks_client.projects.list.assert_called_with(domain=domain_1)