Test Failed
Push — master ( aea994...69b639 )
by Nicolas
03:44 queued 10s
created

glances.actions.GlancesActions.run()   C

Complexity

Conditions 9

Size

Total Lines 45
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 25
nop 6
dl 0
loc 45
rs 6.6666
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of Glances.
4
#
5
# Copyright (C) 2021 Nicolargo <[email protected]>
6
#
7
# Glances is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU Lesser General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Glances is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU Lesser General Public License for more details.
16
#
17
# You should have received a copy of the GNU Lesser General Public License
18
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20
"""Manage on alert actions."""
21
22
from glances.logger import logger
23
from glances.timer import Timer
24
from glances.secure import secure_popen
25
26
try:
27
    import chevron
28
except ImportError:
29
    logger.debug("Chevron library not found (action scripts won't work)")
30
    chevron_tag = False
31
else:
32
    chevron_tag = True
33
34
35
class GlancesActions(object):
36
37
    """This class manage action if an alert is reached."""
38
39
    def __init__(self, args=None):
40
        """Init GlancesActions class."""
41
        # Dict with the criticity status
42
        # - key: stat_name
43
        # - value: criticity
44
        # Goal: avoid to execute the same command twice
45
        self.status = {}
46
47
        # Add a timer to avoid any trigger when Glances is started (issue#732)
48
        # Action can be triggered after refresh * 2 seconds
49
        if hasattr(args, 'time'):
50
            self.start_timer = Timer(args.time * 2)
51
        else:
52
            self.start_timer = Timer(3)
53
54
    def get(self, stat_name):
55
        """Get the stat_name criticity."""
56
        try:
57
            return self.status[stat_name]
58
        except KeyError:
59
            return None
60
61
    def set(self, stat_name, criticity):
62
        """Set the stat_name to criticity."""
63
        self.status[stat_name] = criticity
64
65
    def run(self, stat_name, criticity, commands, repeat, mustache_dict=None):
66
        """Run the commands (in background).
67
68
        - stats_name: plugin_name (+ header)
69
        - criticity: criticity of the trigger
70
        - commands: a list of command line with optional {{mustache}}
71
        - If True, then repeat the action
72
        - mustache_dict: Plugin stats (can be use within {{mustache}})
73
74
        Return True if the commands have been ran.
75
        """
76
        if (self.get(stat_name) == criticity and not repeat) or \
77
           not self.start_timer.finished():
78
            # Action already executed => Exit
79
            return False
80
81
        logger.debug("{} action {} for {} ({}) with stats {}".format(
82
            "Repeat" if repeat else "Run",
83
            commands, stat_name, criticity, mustache_dict))
84
85
        # Run all actions in background
86
        for cmd in commands:
87
            # Replace {{arg}} by the dict one (Thk to {Mustache})
88
            if chevron_tag:
89
                cmd_full = chevron.render(cmd, mustache_dict)
90
            else:
91
                cmd_full = cmd
92
            # Execute the action
93
            logger.info("Action triggered for {} ({}): {}".format(stat_name,
94
                                                                  criticity,
95
                                                                  cmd_full))
96
            try:
97
                ret = secure_popen(cmd_full)
98
            except OSError as e:
99
                logger.error("Action error for {} ({}): {}".format(stat_name,
100
                                                                   criticity,
101
                                                                   e))
102
            else:
103
                logger.debug("Action result for {} ({}): {}".format(stat_name,
104
                                                                    criticity, 
105
                                                                    ret))
106
107
        self.set(stat_name, criticity)
108
109
        return True
110