Mini Shell
# 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()
Zerion Mini Shell 1.0