-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial work on Auditor accounting plugin
- Loading branch information
Showing
2 changed files
with
108 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
from ..configuration.configuration import Configuration | ||
from ..interfaces.plugin import Plugin | ||
from ..interfaces.state import State | ||
from ..utilities.attributedict import AttributeDict | ||
from ..resources.dronestates import AvailableState, DownState | ||
|
||
from pyauditor import AuditorClientBuilder, Record, Component, Score | ||
|
||
import logging | ||
from datetime import timezone | ||
import pytz | ||
from tzlocal import get_localzone | ||
|
||
|
||
class Auditor(Plugin): | ||
""" | ||
The :py:class:`~tardis.plugins.auditor.Auditor` TODO | ||
""" | ||
|
||
def __init__(self): | ||
self.logger = logging.getLogger("cobald.runtime.tardis.plugins.auditor") | ||
config = Configuration() | ||
config_auditor = config.Plugins.Auditor | ||
|
||
self._resources = {} | ||
self._factors = {} | ||
for site in config.Sites: | ||
self._resources[site.name] = {} | ||
self._factors[site.name] = {} | ||
for machine_type in getattr(config, site.name).MachineTypes: | ||
self._resources[site.name][machine_type] = {} | ||
self._factors[site.name][machine_type] = {} | ||
for r in getattr(config, site.name).MachineMetaData[machine_type]: | ||
self._resources[site.name][machine_type][r] = getattr( | ||
config, site.name | ||
).MachineMetaData[machine_type][r] | ||
try: | ||
self._factors[site.name][machine_type][r] = config_auditor[ | ||
"factors" | ||
][machine_type][r] | ||
except KeyError: | ||
# Note: removed `'None': 1` | ||
self._factors[site.name][machine_type][r] = {} | ||
|
||
self._user = config_auditor.user if config_auditor.user else "tardis" | ||
self._group = config_auditor.group if config_auditor.group else "tardis" | ||
auditor_timeout = config_auditor.timeout if config_auditor.timeout else 30 | ||
self._local_timezone = get_localzone() | ||
self._client = ( | ||
AuditorClientBuilder() | ||
.address(config_auditor.host, config_auditor.port) | ||
.timeout(auditor_timeout) | ||
.build() | ||
) | ||
|
||
async def notify(self, state: State, resource_attributes: AttributeDict) -> None: | ||
""" | ||
TODO | ||
:param state: New state of the Drone | ||
:type state: State | ||
:param resource_attributes: Contains all meta-data of the Drone (created and | ||
updated timestamps, dns name, unique id, site_name, machine_type, etc.) | ||
:type resource_attributes: AttributeDict | ||
:return: None | ||
""" | ||
self.logger.debug( | ||
f"Drone: {str(resource_attributes)} has changed state to {state}" | ||
) | ||
|
||
if isinstance(state, AvailableState): | ||
record = self.construct_record(resource_attributes) | ||
await self._client.add(record) | ||
elif isinstance(state, DownState): | ||
record = self.construct_record(resource_attributes) | ||
record.with_stop_time( | ||
resource_attributes["updated"] | ||
.replace(tzinfo=self._local_timezone) | ||
.astimezone(pytz.utc) | ||
) | ||
await self._client.update(record) | ||
|
||
def construct_record(self, resource_attributes: AttributeDict): | ||
record = Record( | ||
resource_attribtues["drone_uuid"], | ||
resource_attributes["site_name"], | ||
self._user, | ||
self._group, | ||
resource_attribute["updated"] | ||
.replace(tzinfo=self._local_timezone) | ||
.astimezone(pytz.utc), | ||
) | ||
|
||
for (resource, amount) in self._resources[resource_attributes["site_name"]][ | ||
resource_attributes["machine_type"] | ||
].items(): | ||
component = Component(resource, amount) | ||
for score_name, score_val in self._factors[ | ||
resource_attributes["site_name"] | ||
][resource_attributes["machine_type"]][resource].items(): | ||
component = component.with_score(Score(score_name, score_val)) | ||
|
||
record = record.with_component(component) | ||
|
||
return record |