Skip to content

Commit 920b791

Browse files
committed
Let operators mark projects directly on keystone
This change allows to mark a project directly on Keystone with a configurable tag in order to be extracted. The list of projects will be merged with the configured projects in caso.conf Sem-Ver: feature
1 parent 330b8fc commit 920b791

File tree

10 files changed

+123
-12
lines changed

10 files changed

+123
-12
lines changed

caso/_cmd/projects.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# -*- coding: utf-8 -*-
2+
3+
# Copyright 2014 Spanish National Research Council (CSIC)
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
6+
# not use this file except in compliance with the License. You may obtain
7+
# a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
# License for the specific language governing permissions and limitations
15+
# under the License.
16+
17+
import sys
18+
19+
from oslo_config import cfg
20+
from oslo_log import log
21+
22+
import caso.config
23+
import caso.manager
24+
25+
CONF = cfg.CONF
26+
27+
28+
def main():
29+
"""Get cASO configured projects."""
30+
caso.config.parse_args(sys.argv)
31+
log.setup(cfg.CONF, "caso")
32+
manager = caso.manager.Manager()
33+
for prj in manager.projects():
34+
print(prj)
35+
36+
37+
if __name__ == "__main__":
38+
main()

caso/extract/base.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,14 @@
3333
"projects",
3434
default=[],
3535
deprecated_name="tenants",
36-
help="List of projects to extract accounting records from.",
36+
help="List of projects to extract accounting records from. You can "
37+
"use this option, or add 'caso' tag to the project in Keystone. "
38+
"Please refer to the documentation for more details.",
39+
),
40+
cfg.StrOpt(
41+
"caso_tag",
42+
default="caso",
43+
help="Tag used to mark a project in Keystone to be extracted by cASO",
3744
),
3845
cfg.StrOpt(
3946
"mapping_file",

caso/extract/manager.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from oslo_log import log
2727
import six
2828

29+
from caso import keystone_client
2930
from caso import loading
3031

3132
cli_opts = [
@@ -65,6 +66,7 @@
6566

6667
CONF.register_cli_opts(cli_opts)
6768
CONF.import_opt("projects", "caso.extract.base")
69+
CONF.import_opt("caso_tag", "caso.extract.base")
6870

6971
LOG = log.getLogger(__name__)
7072

@@ -84,6 +86,20 @@ def __init__(self):
8486
self.extractors = extractors
8587
self.last_run_base = os.path.join(CONF.spooldir, "lastrun")
8688

89+
self.keystone = self._get_keystone_client()
90+
91+
@property
92+
def projects(self):
93+
"""Get list of configured projects."""
94+
projects = CONF.projects
95+
aux = [i.id for i in self.keystone.projects.list(tags=CONF.caso_tag)]
96+
return set(projects + aux)
97+
98+
def _get_keystone_client(self):
99+
"""Get a Keystone Client to get the projects that we will use."""
100+
client = keystone_client.get_client(CONF, system_scope="all")
101+
return client
102+
87103
def get_lastrun(self, project):
88104
"""Get lastrun file for a given project."""
89105
lfile = f"{self.last_run_base}.{project}"
@@ -143,7 +159,7 @@ def get_records(self):
143159
extract_to = now
144160

145161
all_records = []
146-
for project in CONF.projects:
162+
for project in self.projects:
147163
LOG.info(f"Extracting records for project '{project}'")
148164

149165
extract_from = CONF.extract_from or self.get_lastrun(project)

caso/keystone_client.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@
3434
opts += loading.get_auth_plugin_conf_options("password")
3535

3636

37-
def get_session(conf, project):
37+
def get_session(conf, project, system_scope=None):
3838
"""Get an auth session."""
3939
# First try using project_id
4040
auth_plugin = loading.load_auth_from_conf_options(
41-
conf, CFG_GROUP, project_id=project
41+
conf, CFG_GROUP, project_id=project, system_scope=system_scope
4242
)
4343
sess = loading.load_session_from_conf_options(conf, CFG_GROUP, auth=auth_plugin)
4444
try:
@@ -52,7 +52,7 @@ def get_session(conf, project):
5252
return sess
5353

5454

55-
def get_client(conf, project):
55+
def get_client(conf, project=None, system_scope=None):
5656
"""Return a client for Keystone."""
57-
sess = get_session(conf, project)
57+
sess = get_session(conf, project, system_scope)
5858
return ks_client_v3.Client(session=sess, interface="public")

caso/manager.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,18 @@ def __init__(self):
7878

7979
self.lock_path = CONF.lock_path
8080

81+
def _load_managers(self):
82+
# Load the managers here to have the config options loaded and
83+
# available
84+
self.extractor_manager = caso.extract.manager.Manager()
85+
self.messenger = caso.messenger.Manager()
86+
87+
def projects(self):
88+
"""Get the configured projects."""
89+
self._load_managers()
90+
91+
return self.extractor_manager.projects
92+
8193
def run(self):
8294
"""Run the manager.
8395
@@ -86,10 +98,7 @@ def run(self):
8698
- Gets all records from the configured extractors
8799
- Pushes all the records to the messengers
88100
"""
89-
# Load the managers here to have the config options loaded and
90-
# available
91-
self.extractor_manager = caso.extract.manager.Manager()
92-
self.messenger = caso.messenger.Manager()
101+
self._load_managers()
93102

94103
@lockutils.synchronized(
95104
"caso_should_not_run_in_parallel", lock_path=self.lock_path, external=True

caso/tests/extract/test_manager.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,18 @@ def setUp(self):
3939
self.m_extractor = mock.MagicMock()
4040
self.m_extractor.return_value.extract.return_value = self.records
4141
patched.return_value = {"mock": self.m_extractor}
42+
43+
self.p_keystone = mock.patch(
44+
"caso.extract.manager.Manager._get_keystone_client"
45+
)
46+
self.p_keystone.start()
47+
4248
self.manager = manager.Manager()
4349

4450
def tearDown(self):
4551
"""Run after each test, reset state and environment."""
4652
self.p_extractors.stop()
53+
self.p_keystone.stop()
4754
self.reset_flags()
4855

4956
super(TestCasoManager, self).tearDown()

doc/source/configuration.rst

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,26 @@ that you are applying the correct changes as listed in the following table.
6666
| | Modified | ``“identity:get_user”: “rule:admin_or_owner or role:accounting”`` |
6767
+-------------+----------+-------------------------------------------------------------------+
6868

69+
Selecting projects to get usages
70+
================================
71+
72+
``cASO`` will extract project usages for those projects that have been explictly marked
73+
by the operator by either of the ways explained below. The final project list will
74+
result from the merge of both methods, so thay are not mutually exclusive.
75+
76+
* Tagging the project with the configured ``caso_tag`` in OpenStack Keystone. By default
77+
this option is set to ``caso``, so in order to mark a project to get extracted you
78+
should use the following command for each of the projects::
79+
80+
openstack project set --tag caso <project id>
81+
82+
You can check the list of projects to get usages by using::
83+
84+
openstack project list --tags caso
85+
86+
* Using the ``projects`` list in the ``[DEFAULT]`` section of your configuration file
87+
(see below).
88+
6989
cASO configuration
7090
==================
7191

@@ -91,7 +111,11 @@ of every option. You should check at least the following options:
91111
records from. You can use either the project ID or the project name. We
92112
recommend that you use the project ID, especially if you are using
93113
domain-based authentication, as otherwise gathering the information might
94-
fail.
114+
fail. This option, and the usage of ``caso_tag`` below will set up the final
115+
project list.
116+
* ``caso_tag`` (default value: ``caso``), specified the tag to be used filter
117+
projects to extract their usage. The projects that are listed with this tag,
118+
as well as the ``projects`` list set above will set up the final project list.
95119
* ``messengers`` (list, default: ``noop``). List of the messengers to publish
96120
data to. Records will be pushed to all these messengers, in order. Valid
97121
messengers shipped with cASO are:

etc/caso/caso.conf.sample

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,15 @@
2828
# Service name within the site (string value)
2929
#service_name = $site_name
3030

31-
# List of projects to extract accounting records from. (list value)
31+
# List of projects to extract accounting records from. You can use this option,
32+
# or add 'caso' tag to the project in Keystone. Please refer to the
33+
# documentation for more details. (list value)
3234
# Deprecated group/name - [DEFAULT]/tenants
3335
#projects =
3436

37+
# Tag used to mark a project in Keystone to be extracted by cASO (string value)
38+
#caso_tag = caso
39+
3540
# File containing the VO <-> project mapping as used in Keystone-VOMS. (string
3641
# value)
3742
#mapping_file = /etc/caso/voms.json
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
features:
3+
- |
4+
Allow to use Keystone project tags to get usages from projects.

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ oslo.config.opts =
4646

4747
console_scripts =
4848
caso-extract = caso._cmd.extract:main
49+
caso-projects = caso._cmd.projects:main
4950

5051
caso.extractors =
5152
nova = caso.extract.openstack.nova:NovaExtractor

0 commit comments

Comments
 (0)