Test Failed
Push — master ( ee826a...d9056e )
by Nicolas
03:09
created

glances.amps_list.AmpsList.load_configs()   B

Complexity

Conditions 8

Size

Total Lines 33
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 19
nop 1
dl 0
loc 33
rs 7.3333
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of Glances.
4
#
5
# SPDX-FileCopyrightText: 2022 Nicolas Hennion <[email protected]>
6
#
7
# SPDX-License-Identifier: LGPL-3.0-only
8
#
9
10
"""Manage the AMPs list."""
11
12
import os
13
import re
14
import threading
15
16
from glances.globals import listkeys, iteritems, amps_path
17
from glances.logger import logger
18
from glances.processes import glances_processes
19
20
21
class AmpsList(object):
22
    """This class describes the optional application monitoring process list.
23
24
    The AMP list is a list of processes with a specific monitoring action.
25
26
    The list (Python list) is composed of items (Python dict).
27
    An item is defined (dict keys):
28
    *...
29
    """
30
31
    # The dict
32
    __amps_dict = {}
33
34
    def __init__(self, args, config):
35
        """Init the AMPs list."""
36
        self.args = args
37
        self.config = config
38
39
        # Load the AMP configurations / scripts
40
        self.load_configs()
41
42
    def load_configs(self):
43
        """Load the AMP configuration files."""
44
        if self.config is None:
45
            return False
46
47
        # For each AMP script, call the load_config method
48
        for s in self.config.sections():
49
            if s.startswith("amp_"):
50
                # An AMP section exists in the configuration file
51
                # If an AMP module exist in amps_path (glances/amps) folder then use it
52
                amp_name = s[4:]
53
                amp_module = os.path.join(amps_path, amp_name)
54
                if not os.path.exists(amp_module):
55
                    # If not, use the default script
56
                    amp_module = os.path.join(amps_path, "default")
57
                try:
58
                    amp = __import__(os.path.basename(amp_module))
59
                except ImportError as e:
60
                    logger.warning("Missing Python Lib ({}), cannot load AMP {}".format(e, amp_name))
61
                except Exception as e:
62
                    logger.warning("Cannot load AMP {} ({})".format(amp_name, e))
63
                else:
64
                    # Add the AMP to the dictionary
65
                    # The key is the AMP name
66
                    # for example, the file glances_xxx.py
67
                    # generate self._amps_list["xxx"] = ...
68
                    self.__amps_dict[amp_name] = amp.Amp(name=amp_name, args=self.args)
69
                    # Load the AMP configuration
70
                    self.__amps_dict[amp_name].load_config(self.config)
71
        # Log AMPs list
72
        logger.debug("AMPs list: {}".format(self.getList()))
73
74
        return True
75
76
    def __str__(self):
77
        return str(self.__amps_dict)
78
79
    def __repr__(self):
80
        return self.__amps_dict
81
82
    def __getitem__(self, item):
83
        return self.__amps_dict[item]
84
85
    def __len__(self):
86
        return len(self.__amps_dict)
87
88
    def update(self):
89
        """Update the command result attributed."""
90
        # Get the current processes list (once)
91
        processlist = glances_processes.get_list()
92
93
        # Iter upon the AMPs dict
94
        for k, v in iteritems(self.get()):
95
            if not v.enable():
96
                # Do not update if the enable tag is set
97
                continue
98
99
            if v.regex() is None:
100
                # If there is no regex, execute anyway (see issue #1690)
101
                v.set_count(0)
102
                # Call the AMP update method
103
                thread = threading.Thread(target=v.update_wrapper, args=[[]])
104
                thread.start()
105
                continue
106
107
            amps_list = self._build_amps_list(v, processlist)
108
109
            if len(amps_list) > 0:
110
                # At least one process is matching the regex
111
                logger.debug("AMPS: {} processes {} detected ({})".format(len(amps_list), k, amps_list))
112
                # Call the AMP update method
113
                thread = threading.Thread(target=v.update_wrapper, args=[amps_list])
114
                thread.start()
115
            else:
116
                # Set the process number to 0
117
                v.set_count(0)
118
                if v.count_min() is not None and v.count_min() > 0:
119
                    # Only display the "No running process message" if count_min is defined
120
                    v.set_result("No running process")
121
122
        return self.__amps_dict
123
124
    def _build_amps_list(self, amp_value, processlist):
125
        """Return the AMPS process list according to the amp_value
126
127
        Search application monitored processes by a regular expression
128
        """
129
        ret = []
130
        try:
131
            # Search in both cmdline and name (for kernel thread, see #1261)
132
            for p in processlist:
133
                if (re.search(amp_value.regex(), p['name']) is not None) or (
134
                    p['cmdline'] is not None
135
                    and p['cmdline'] != []
136
                    and re.search(amp_value.regex(), ' '.join(p['cmdline'])) is not None
137
                ):
138
                    ret.append(
139
                        {'pid': p['pid'], 'cpu_percent': p['cpu_percent'], 'memory_percent': p['memory_percent']}
140
                    )
141
142
        except (TypeError, KeyError) as e:
143
            logger.debug("Can not build AMPS list ({})".format(e))
144
145
        return ret
146
147
    def getList(self):
148
        """Return the AMPs list."""
149
        return listkeys(self.__amps_dict)
150
151
    def get(self):
152
        """Return the AMPs dict."""
153
        return self.__amps_dict
154
155
    def set(self, new_dict):
156
        """Set the AMPs dict."""
157
        self.__amps_dict = new_dict
158