Skip to content
/ hotsos Public
forked from canonical/hotsos

Commit

Permalink
hotsos/core: add name aliasing support
Browse files Browse the repository at this point in the history
at the moment, scenarios are using the long import paths in order to
reference to a Python property. this feature allows assigning an alias
to a Python class or variable in order to make using plugin property
interfaces easier.

Added aliases to the plugins.
Updated existing scenarios to use aliases.

Fixes canonical#912

Signed-off-by: Mustafa Kemal Gilor <[email protected]>
  • Loading branch information
xmkg committed Jul 5, 2024
1 parent bb1e90b commit b1f34bf
Show file tree
Hide file tree
Showing 104 changed files with 394 additions and 222 deletions.
82 changes: 82 additions & 0 deletions hotsos/core/alias.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
"""Aliasing utilities."""

from hotsos.core.log import log


class AliasAlreadyInUseError(Exception):
def __init__(self, name):
self.message = f"Alias '{name}` already in use!"

def __str__(self):
return self.message


class AliasRegistry:
"""
A class that provides a registry for aliasing Python things.
"""

# A class-level dictionary to store registered aliases.
registry = {}

@staticmethod
def register(name, decoratee):
"""
Register a function, method, or property under an alias.
This method handles different types of Python objects and creates
appropriate wrappers or registrations based on the object type.
Args:
name (str): The alias under which to register the decoratee.
decoratee (callable or property): The Python object to be
registered.
Raises:
AliasAlreadyInUseError: If the alias name is already registered.
"""
isprop = isinstance(decoratee, property)
target = decoratee.fget if isprop else decoratee

if name in AliasRegistry.registry:
raise AliasAlreadyInUseError(name)

import_path = f"{target.__module__}.{target.__qualname__}"
log.debug("registering alias `%s` --> {%s}", name, import_path)
# Register full import path.
AliasRegistry.registry[name] = import_path

@staticmethod
def resolve(the_alias):
"""
Retrieve a registered alias.
Args:
the_alias (str): The alias to retrieve.
Returns:
callable: The function or wrapper associated with the alias.
Raises:
NoSuchAliasError: No such alias in the registry.
"""

if the_alias not in AliasRegistry.registry:
return None

value = AliasRegistry.registry[the_alias]
log.debug("alias %s resolved to %s", the_alias, value)
return value


def alias(argument):
"""Create an alias for a property, function or a thing."""

def real_decorator(func):
"""We're not wrapping the func as we don't want
to do anything at runtime. We just want to alias
`func` to some user-defined name and call it on-demand."""
AliasRegistry.register(argument, func)
return func

return real_decorator
2 changes: 2 additions & 0 deletions hotsos/core/host_helpers/filestat.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from hotsos.core.config import HotSOSConfig
from hotsos.core.factory import FactoryBase
from hotsos.core.log import log
from hotsos.core.alias import alias


class FileObj():
Expand Down Expand Up @@ -38,6 +39,7 @@ def size(self):
return size


@alias("file")
class FileFactory(FactoryBase):
"""
Factory to dynamically create FileObj objects using file path as input.
Expand Down
2 changes: 2 additions & 0 deletions hotsos/core/host_helpers/ssl.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from hotsos.core.factory import FactoryBase
from hotsos.core.host_helpers.cli import CLIHelper
from hotsos.core.log import log
from hotsos.core.alias import alias


class SSLCertificate():
Expand Down Expand Up @@ -65,6 +66,7 @@ def certificate_expires_soon(self):
return self.certificate.days_to_expire <= self.expire_days


@alias('sslcert')
class SSLCertificatesFactory(FactoryBase):
"""
Factory to dynamically create SSLCertificate objects for given paths.
Expand Down
2 changes: 2 additions & 0 deletions hotsos/core/plugins/juju/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from hotsos.core.host_helpers import PebbleHelper, SystemdHelper
from hotsos.core.plugins.juju.resources import JujuBase
from hotsos.core import plugintools
from hotsos.core.alias import alias

SVC_VALID_SUFFIX = r'[0-9a-zA-Z-_]*'
JUJU_SVC_EXPRS = [r'mongod{}'.format(SVC_VALID_SUFFIX),
Expand All @@ -12,6 +13,7 @@
r'(?:^|[^\s])juju-db{}'.format(SVC_VALID_SUFFIX)]


@alias('juju')
class JujuChecksBase(plugintools.PluginPartBase, JujuBase):
plugin_name = 'juju'
plugin_root_index = 12
Expand Down
2 changes: 2 additions & 0 deletions hotsos/core/plugins/juju/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from hotsos.core.config import HotSOSConfig
from hotsos.core.log import log
from hotsos.core import utils
from hotsos.core.alias import alias


class JujuMachine():
Expand Down Expand Up @@ -174,6 +175,7 @@ def __init__(self, name, version):
self.version = int(version)


@alias('juju.base')
class JujuBase():
CHARM_MANIFEST_GLOB = "agents/unit-*/state/deployer/manifests"

Expand Down
2 changes: 2 additions & 0 deletions hotsos/core/plugins/kernel/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
from hotsos.core import host_helpers, plugintools
from hotsos.core.config import HotSOSConfig
from hotsos.core.plugins.kernel.config import KernelConfig
from hotsos.core.alias import alias


@alias('kernel')
class KernelBase():

@cached_property
Expand Down
2 changes: 2 additions & 0 deletions hotsos/core/plugins/kernel/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from hotsos.core.config import HotSOSConfig
from hotsos.core import host_helpers
from hotsos.core.alias import alias


class KernelConfig(host_helpers.ConfigBase):
Expand Down Expand Up @@ -39,6 +40,7 @@ def _load(self):
break


@alias('kernel.systemdconfig')
class SystemdConfig(host_helpers.IniConfigBase):
"""Systemd configuration."""

Expand Down
2 changes: 2 additions & 0 deletions hotsos/core/plugins/kernel/kernlog/calltrace.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
TraceTypeBase,
KernLogBase,
)
from hotsos.core.alias import alias

KERNLOG_TS = r'\[\s*\d+\.\d+\]'
KERNLOG_PREFIX = (r'(?:\S+\s+\d+\s+[\d:]+\s+\S+\s+\S+:\s+)?{}'.
Expand Down Expand Up @@ -454,6 +455,7 @@ def __iter__(self):
yield from self.hungtasks


@alias("kernel.calltrace")
class CallTraceManager(KernLogBase):

def __init__(self, *args, **kwargs):
Expand Down
2 changes: 2 additions & 0 deletions hotsos/core/plugins/kernel/kernlog/events.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from hotsos.core.log import log
from hotsos.core.plugins.kernel.kernlog.common import KernLogBase
from hotsos.core.search import SearchDef
from hotsos.core.alias import alias


class OverMTUDroppedPacketEvent():
Expand All @@ -11,6 +12,7 @@ def searchdef(self):
hint='dropped', tag='over-mtu-dropped')


@alias('kernel.kernlog.events')
class KernLogEvents(KernLogBase):

def __init__(self, *args, **kwargs):
Expand Down
6 changes: 6 additions & 0 deletions hotsos/core/plugins/kernel/memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from hotsos.core.config import HotSOSConfig
from hotsos.core.utils import sorted_dict
from hotsos.core.alias import alias


class _BaseProcKeyValue():
Expand Down Expand Up @@ -50,6 +51,7 @@ def __getattr__(self, key):
format(key, self.__class__.__name__))


@alias('kernel.vmstat')
class VMStat(_BaseProcKeyValue):
VALID_KEYS = ['compact_fail', 'compact_success']

Expand All @@ -58,6 +60,7 @@ def path(self):
return os.path.join(HotSOSConfig.data_root, 'proc/vmstat')

@property
@alias("kernel.vmstat.compaction_failures_pct")
def compaction_failures_percent(self):
if not os.path.exists(self.path):
return 0
Expand All @@ -70,6 +73,7 @@ def compaction_failures_percent(self):
return int(fail_count / (success_count / 100))


@alias("kernel.meminfo")
class MemInfo(_BaseProcKeyValue):
VALID_KEYS = ['MemTotal', 'MemAvailable', 'Hugetlb', 'HugePages_Total',
'HugePages_Free']
Expand Down Expand Up @@ -111,6 +115,7 @@ def hugep_used_to_hugep_total_percentage(self):
return round(100 - (self.HugePages_Free * 100) / self.HugePages_Total)


@alias("kernel.slab")
class SlabInfo():

def __init__(self, filter_names=None):
Expand Down Expand Up @@ -284,6 +289,7 @@ def high_order_seq(self):
return count


@alias('kernel.memchecks')
class MemoryChecks():

@property
Expand Down
6 changes: 6 additions & 0 deletions hotsos/core/plugins/kernel/net.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from hotsos.core.host_helpers import SYSCtlFactory, CLIHelperFile
from hotsos.core.log import log
from hotsos.core.search import FileSearcher, SearchDef, ResultFieldInfo
from hotsos.core.alias import alias


class ProcNetBase(abc.ABC):
Expand Down Expand Up @@ -109,6 +110,7 @@ def __init__(self):
'proc/net/snmp'))


@alias('kernel.net.snmp.tcp')
class SNMPTcp(SNMPBase):

def _percent_in_segs(self, field):
Expand Down Expand Up @@ -154,6 +156,7 @@ def __getattr__(self, fld):
return super().__getattr__(fld)


@alias('kernel.net.snmp.udp')
class SNMPUdp(SNMPBase):

@property
Expand Down Expand Up @@ -208,6 +211,7 @@ def __init__(self):
self.net_snmp_tcp = SNMPTcp()


@alias('kernel.net.netstat.tcp')
class NetStatTCP(NetStatBase):

@property
Expand Down Expand Up @@ -286,6 +290,7 @@ def __getattr__(self, fld):
return super().__getattr__(fld)


@alias('kernel.net.sockstat')
class SockStat(ProcNetBase):

"""
Expand Down Expand Up @@ -534,6 +539,7 @@ def all_with_inode(self, inode):
return list(filter(lambda x: (x.NODE == inode), self.data))


@alias('kernel.net.netlink')
class NetLink(STOVParserBase):
"""
Provides a way to extract fields from /proc/net/netlink.
Expand Down
2 changes: 2 additions & 0 deletions hotsos/core/plugins/kernel/sysfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from hotsos.core.config import HotSOSConfig
from hotsos.core import host_helpers
from hotsos.core.plugins.system.system import SystemBase
from hotsos.core.alias import alias


class SYSFSBase():
Expand All @@ -23,6 +24,7 @@ def get(relpath):
return fd.read().strip()


@alias('kernel.sysfs.cpu')
class CPU(SYSFSBase):

@property
Expand Down
3 changes: 2 additions & 1 deletion hotsos/core/plugins/lxd/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@
FileSearcher, SearchDef,
SequenceSearchDef
)

from hotsos.core.alias import alias

CORE_APT = ['lxd', 'lxc']
CORE_SNAPS = [r"(?:snap\.)?{}".format(p) for p in CORE_APT]
SERVICE_EXPRS = [r"{}\S*".format(s) for s in CORE_SNAPS]


@alias('lxd')
class LXD():

@cached_property
Expand Down
2 changes: 2 additions & 0 deletions hotsos/core/plugins/mysql.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
host_helpers,
plugintools,
)
from hotsos.core.alias import alias

SVC_VALID_SUFFIX = r'[0-9a-zA-Z-_]*'
MYSQL_SVC_EXPRS = [r'mysql{}'.format(SVC_VALID_SUFFIX)]
CORE_APT = ['mysql']


@alias('mysql')
class MySQLChecksBase(plugintools.PluginPartBase):
plugin_name = 'mysql'
plugin_root_index = 3
Expand Down
3 changes: 3 additions & 0 deletions hotsos/core/plugins/openstack/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@
from hotsos.core.plugins.openstack.octavia import OctaviaBase
from hotsos.core import plugintools
from hotsos.core.ycheck.events import EventHandlerBase, EventCallbackBase
from hotsos.core.alias import alias


@alias('openstack')
class OpenstackBase():

def __init__(self, *args, **kwargs):
Expand Down Expand Up @@ -239,6 +241,7 @@ def apache2_allow_encoded_slashes_on(self):
return False


@alias('openstack.checks')
class OpenstackChecksBase(OpenstackBase, plugintools.PluginPartBase):
plugin_name = "openstack"
plugin_root_index = 4
Expand Down
3 changes: 3 additions & 0 deletions hotsos/core/plugins/openstack/neutron.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
OpenstackConfig,
OSTServiceBase,
)
from hotsos.core.alias import alias

# See https://github.com/openstack/neutron-lib/blob/master/neutron_lib/constants.py#L346 # noqa, pylint: disable=C0301
IP_HEADER_BYTES = 20
Expand Down Expand Up @@ -44,6 +45,7 @@ def bind_interfaces(self):
return interfaces


@alias('neutron.service_checks')
class ServiceChecks():

@cached_property
Expand Down Expand Up @@ -128,6 +130,7 @@ def find_router_with_vr_id(self, vr_id):
return None


@alias('neutron.config')
class Config(FactoryBase):

def __getattr__(self, path):
Expand Down
Loading

0 comments on commit b1f34bf

Please sign in to comment.