You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
3.6 KiB

4 years ago
  1. # -*- coding: utf-8 -*-
  2. #
  3. # This file is part of Glances.
  4. #
  5. # Copyright (C) 2018 Nicolargo <nicolas@nicolargo.com>
  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. """Manage on alert actions."""
  20. from subprocess import Popen
  21. from glances.logger import logger
  22. from glances.timer import Timer
  23. try:
  24. import pystache
  25. except ImportError:
  26. logger.debug("Pystache library not found (action scripts won't work)")
  27. pystache_tag = False
  28. else:
  29. pystache_tag = True
  30. class GlancesActions(object):
  31. """This class manage action if an alert is reached."""
  32. def __init__(self, args=None):
  33. """Init GlancesActions class."""
  34. # Dict with the criticity status
  35. # - key: stat_name
  36. # - value: criticity
  37. # Goal: avoid to execute the same command twice
  38. self.status = {}
  39. # Add a timer to avoid any trigger when Glances is started (issue#732)
  40. # Action can be triggered after refresh * 2 seconds
  41. if hasattr(args, 'time'):
  42. self.start_timer = Timer(args.time * 2)
  43. else:
  44. self.start_timer = Timer(3)
  45. def get(self, stat_name):
  46. """Get the stat_name criticity."""
  47. try:
  48. return self.status[stat_name]
  49. except KeyError:
  50. return None
  51. def set(self, stat_name, criticity):
  52. """Set the stat_name to criticity."""
  53. self.status[stat_name] = criticity
  54. def run(self, stat_name, criticity, commands, repeat, mustache_dict=None):
  55. """Run the commands (in background).
  56. - stats_name: plugin_name (+ header)
  57. - criticity: criticity of the trigger
  58. - commands: a list of command line with optional {{mustache}}
  59. - If True, then repeat the action
  60. - mustache_dict: Plugin stats (can be use within {{mustache}})
  61. Return True if the commands have been ran.
  62. """
  63. if (self.get(stat_name) == criticity and not repeat) or \
  64. not self.start_timer.finished():
  65. # Action already executed => Exit
  66. return False
  67. logger.debug("{} action {} for {} ({}) with stats {}".format(
  68. "Repeat" if repeat else "Run",
  69. commands, stat_name, criticity, mustache_dict))
  70. # Run all actions in background
  71. for cmd in commands:
  72. # Replace {{arg}} by the dict one (Thk to {Mustache})
  73. if pystache_tag:
  74. cmd_full = pystache.render(cmd, mustache_dict)
  75. else:
  76. cmd_full = cmd
  77. # Execute the action
  78. logger.info("Action triggered for {} ({}): {}".format(stat_name,
  79. criticity,
  80. cmd_full))
  81. logger.debug("Stats value for the trigger: {}".format(
  82. mustache_dict))
  83. try:
  84. Popen(cmd_full, shell=True)
  85. except OSError as e:
  86. logger.error("Can't execute the action ({})".format(e))
  87. self.set(stat_name, criticity)
  88. return True