chg: containers (Podman) - cache version calls

To reduce update times
This commit is contained in:
Bharath Vignesh J K 2023-05-07 21:44:52 +05:30
parent 58a97cb4eb
commit 9e52775929

View File

@ -1,5 +1,6 @@
"""Podman Extension unit for Glances' Containers plugin.""" """Podman Extension unit for Glances' Containers plugin."""
import json import json
import time
from datetime import datetime from datetime import datetime
from glances.compat import iterkeys, itervalues, nativestr, pretty_date, string_value_to_float from glances.compat import iterkeys, itervalues, nativestr, pretty_date, string_value_to_float
@ -9,7 +10,7 @@ from glances.plugins.containers.stats_streamer import StatsStreamer
# Podman library (optional and Linux-only) # Podman library (optional and Linux-only)
# https://pypi.org/project/podman/ # https://pypi.org/project/podman/
try: try:
import podman from podman import PodmanClient
except Exception as e: except Exception as e:
import_podman_error_tag = True import_podman_error_tag = True
# Display debug message if import KeyError # Display debug message if import KeyError
@ -211,85 +212,86 @@ class PodmanContainersExtension:
if import_podman_error_tag: if import_podman_error_tag:
raise Exception("Missing libs required to run Podman Extension (Containers)") raise Exception("Missing libs required to run Podman Extension (Containers)")
self.ext_name = "containers (Podman)"
self.client = None self.client = None
self.ext_name = "Podman (Containers)"
self.podman_sock = podman_sock self.podman_sock = podman_sock
self.stats_fetchers = {} self.pods_stats_fetcher = None
self.pod_fetcher = None self.container_stats_fetchers = {}
# Cache version details as the version call is costly (in terms of time)
self._version = {} self._version = {}
self._last_version_update = 0
self.connect() self.connect()
def connect(self): def connect(self):
"""Connect to Podman.""" """Connect to Podman."""
try: try:
self.client = podman.PodmanClient(base_url=self.podman_sock) self.client = PodmanClient(base_url=self.podman_sock)
except Exception as e: except Exception as e:
logger.error("{} plugin - Can not connect to Podman ({})".format(self.ext_name, e)) logger.error("{} plugin - Can not connect to Podman ({})".format(self.ext_name, e))
def update_version(self):
try: try:
version_podman = self.client.version() self._version = self.client.version()
self._last_version_update = time.time()
except Exception as e: except Exception as e:
logger.error("{} plugin - Cannot get Podman version ({})".format(self.ext_name, e)) logger.error("{} plugin - Cannot get Podman version ({})".format(self.ext_name, e))
else:
self._version = {
'Version': version_podman['Version'],
'ApiVersion': version_podman['ApiVersion'],
'MinAPIVersion': version_podman['MinAPIVersion'],
}
def stop(self): def stop(self):
# Stop all streaming threads # Stop all streaming threads
for t in itervalues(self.stats_fetchers): for t in itervalues(self.container_stats_fetchers):
t.stop() t.stop()
if self.pods_stats_fetcher:
self.pods_stats_fetcher.stop()
def update(self, all_tag): def update(self, all_tag):
"""Update Podman stats using the input method.""" """Update Podman stats using the input method."""
try: curr_time = time.time()
version_stats = self.client.version() if curr_time - self._last_version_update > 300: # 300 seconds
except Exception as e: self.update_version()
# Correct issue#649
logger.error("{} plugin - Cannot get Podman version ({})".format(self.ext_name, e))
return {}, []
# Update current containers list # Update current containers list
try: try:
# Issue #1152: Podman module doesn't export details about stopped containers # Issue #1152: Podman module doesn't export details about stopped containers
# The Containers/all key of the configuration file should be set to True # The Containers/all key of the configuration file should be set to True
containers = self.client.containers.list(all=all_tag) containers = self.client.containers.list(all=all_tag)
if not self.pod_fetcher: if not self.pods_stats_fetcher:
self.pod_fetcher = PodmanPodStatsFetcher(self.client.pods) self.pods_stats_fetcher = PodmanPodStatsFetcher(self.client.pods)
except Exception as e: except Exception as e:
logger.error("{} plugin - Cannot get containers list ({})".format(self.ext_name, e)) logger.error("{} plugin - Cannot get containers list ({})".format(self.ext_name, e))
return version_stats, [] return self._version, []
# Start new thread for new container # Start new thread for new container
for container in containers: for container in containers:
if container.id not in self.stats_fetchers: if container.id not in self.container_stats_fetchers:
# StatsFetcher did not exist in the internal dict # StatsFetcher did not exist in the internal dict
# Create it, add it to the internal dict # Create it, add it to the internal dict
logger.debug("{} plugin - Create thread for container {}".format(self.ext_name, container.id[:12])) logger.debug("{} plugin - Create thread for container {}".format(self.ext_name, container.id[:12]))
self.stats_fetchers[container.id] = PodmanContainerStatsFetcher(container) self.container_stats_fetchers[container.id] = PodmanContainerStatsFetcher(container)
# Stop threads for non-existing containers # Stop threads for non-existing containers
absent_containers = set(iterkeys(self.stats_fetchers)) - set(c.id for c in containers) absent_containers = set(iterkeys(self.container_stats_fetchers)) - set(c.id for c in containers)
for container_id in absent_containers: for container_id in absent_containers:
# Stop the StatsFetcher # Stop the StatsFetcher
logger.debug("{} plugin - Stop thread for old container {}".format(self.ext_name, container_id[:12])) logger.debug("{} plugin - Stop thread for old container {}".format(self.ext_name, container_id[:12]))
self.stats_fetchers[container_id].stop() self.container_stats_fetchers[container_id].stop()
# Delete the StatsFetcher from the dict # Delete the StatsFetcher from the dict
del self.stats_fetchers[container_id] del self.container_stats_fetchers[container_id]
# Get stats for all containers # Get stats for all containers
container_stats = [self.generate_stats(container) for container in containers] container_stats = [self.generate_stats(container) for container in containers]
pod_stats = self.pod_fetcher.activity_stats pod_stats = self.pods_stats_fetcher.activity_stats
for stats in container_stats: for stats in container_stats:
if stats["Id"][:12] in pod_stats: if stats["Id"][:12] in pod_stats:
stats["pod_name"] = pod_stats[stats["Id"][:12]]["name"] stats["pod_name"] = pod_stats[stats["Id"][:12]]["name"]
stats["pod_id"] = pod_stats[stats["Id"][:12]]["pod_id"] stats["pod_id"] = pod_stats[stats["Id"][:12]]["pod_id"]
return version_stats, container_stats return self._version, container_stats
@property @property
def key(self): def key(self):
@ -314,7 +316,7 @@ class PodmanContainersExtension:
if stats['Status'] in self.CONTAINER_ACTIVE_STATUS: if stats['Status'] in self.CONTAINER_ACTIVE_STATUS:
stats['StartedAt'] = datetime.fromtimestamp(container.attrs['StartedAt']) stats['StartedAt'] = datetime.fromtimestamp(container.attrs['StartedAt'])
stats_fetcher = self.stats_fetchers[container.id] stats_fetcher = self.container_stats_fetchers[container.id]
activity_stats = stats_fetcher.activity_stats activity_stats = stats_fetcher.activity_stats
stats.update(activity_stats) stats.update(activity_stats)