관리-도구
편집 파일: lvedestroyer.py
# coding=utf-8 # # Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2019 All Rights Reserved # # Licensed under CLOUD LINUX LICENSE AGREEMENT # http://cloudlinux.com/docs/LICENSE.TXT import logging import subprocess from lvestats.core.plugin import LveStatsPlugin LVECTL = '/usr/sbin/lvectl' class LVERecord(object): def __init__(self, cpu, iterations): self.cpu = cpu self.count = 0 self.iterations = iterations def inc(self): self.count += 1 def check(self): return self.count >= self.iterations def has_changed(self, stat): if self.cpu != stat.cpu or stat.nproc > 0: self.count = 0 self.cpu = stat.cpu return True return False class LVEDestroyer(LveStatsPlugin): def __init__(self): self.log = logging.getLogger(__name__) self.default_stat = None self.iterations = 0 self.lves = {} self.to_be_destroyed = [] self._enabled = False def set_config(self, config): self._enabled = False try: self.iterations = int(config['iterations']) if self.iterations > 0: self._enabled = True self.lves = {} self.default_stat = None except (KeyError, ValueError): pass def set_default(self, stat): if self._enabled: self.default_stat = stat self.to_be_destroyed = [] def is_stat_tracked(self, stat) -> bool: # if any of this LVE's settings differ from the default, then don't track this LVE for destruction return ((stat.cpu != self.default_stat.cpu) or (stat.io != self.default_stat.io) or (stat.lmem != self.default_stat.lmem) or (stat.lep != self.default_stat.lep) or (stat.lmemphy != self.default_stat.lmemphy) or (stat.lcpuw != self.default_stat.lcpuw) or (stat.lnproc != self.default_stat.lnproc)) def check_lve(self, stat): r = self.lves[stat.id] if not r.has_changed(stat): if r.check(): self.to_be_destroyed.append(stat.id) self.lves.pop(stat.id) else: r.inc() def add_stat(self, stat): if self._enabled: id_ = stat.id if id_ == 0: self.set_default(stat) return if id_ in self.lves: self.check_lve(stat) elif self.is_stat_tracked(stat): return else: self.lves[id_] = LVERecord(stat.cpu, self.iterations) def process_destroy(self): if self._enabled: if self.to_be_destroyed: try: # run the command and suppress it's output with subprocess.Popen( [LVECTL, "destroy-many"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) as proc: # send input string to suprocess self.log.info("Destroying: %s", " ".join(map(str, self.to_be_destroyed))) proc.communicate(" ".join(map(str, self.to_be_destroyed)).encode()) except OSError: self.log.error("Error: failed to run %s destroy-many", LVECTL) def execute(self, lve_data): stats = lve_data['stats'] self.set_default(stats[0]) for stat in stats.values(): self.add_stat(stat) self.process_destroy()