267 lines
8.1 KiB
Python
Executable File
267 lines
8.1 KiB
Python
Executable File
#!/usr/bin/python3
|
|
# -*- coding: utf-8 -*-
|
|
# Copyright (c) 2019 Huawei Technologies Co., Ltd.
|
|
# A-Tune is licensed under the Mulan PSL v1.
|
|
# You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
# You may obtain a copy of Mulan PSL v1 at:
|
|
# http://license.coscl.org.cn/MulanPSL
|
|
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
|
|
# PURPOSE.
|
|
# See the Mulan PSL v1 for more details.
|
|
# Create: 2019-10-29
|
|
|
|
"""
|
|
The plugin for monitor and configurator.
|
|
"""
|
|
|
|
import sys
|
|
import logging
|
|
import os
|
|
import threading
|
|
import monitor
|
|
import configurator
|
|
import time
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class ThreadedCall(threading.Thread):
|
|
"""class for function threaded calling"""
|
|
|
|
def __init__(self, func, args=()):
|
|
super(ThreadedCall, self).__init__()
|
|
self.func = func
|
|
self.args = args
|
|
|
|
def run(self):
|
|
self.result = self.func(*self.args)
|
|
|
|
def get_result(self):
|
|
threading.Thread.join(self)
|
|
try:
|
|
return self.result
|
|
except Exception as err:
|
|
return err
|
|
|
|
|
|
class MPI:
|
|
"""The monitor plugin"""
|
|
|
|
def __init__(self):
|
|
"""
|
|
Initialize.
|
|
|
|
:param: None
|
|
:returns: None
|
|
:raises: None
|
|
"""
|
|
all_mpis = []
|
|
all_modules = []
|
|
all_purposes = []
|
|
for m in monitor.common.Monitor.__subclasses__():
|
|
all_mpis.append((m._module, m._purpose))
|
|
all_modules.append(m._module)
|
|
all_purposes.append(m._purpose)
|
|
self.get_monitors.__func__.__doc__ = self.get_monitors.__func__.__doc__ % (
|
|
set(all_modules), set(all_purposes))
|
|
self.get_monitor.__func__.__doc__ = self.get_monitor.__func__.__doc__ % (
|
|
all_mpis)
|
|
|
|
@classmethod
|
|
def get_monitors(self, module=None, purpose=None):
|
|
"""
|
|
Get monitors of 'module' for 'purpose'.
|
|
|
|
:param module(optional): %s
|
|
:param purpose(optional): %s
|
|
:returns list: Success, all found monitors or null
|
|
:raises: None
|
|
"""
|
|
mpis = []
|
|
for m in monitor.common.Monitor.__subclasses__():
|
|
if (module is not None) and (m._module != module):
|
|
continue
|
|
if (purpose is not None) and (m._purpose != purpose):
|
|
continue
|
|
me = m()
|
|
mpis.append(me)
|
|
return mpis
|
|
|
|
@classmethod
|
|
def get_monitor(self, module, purpose):
|
|
"""
|
|
Get monitor of 'module' for 'purpose'.
|
|
|
|
:param module & purpose: %s
|
|
:returns mpi: Success, the found monitor
|
|
:raises LookupError: Fail, find monitor error
|
|
"""
|
|
mpis = MPI.get_monitors(module, purpose)
|
|
if len(mpis) != 1:
|
|
err = LookupError("Find {} {}-{} monitors".format(
|
|
len(mpis), module, purpose))
|
|
logger.error("MPI.{}: {}".format(
|
|
sys._getframe().f_code.co_name, str(err)))
|
|
raise err
|
|
else:
|
|
return mpis[0]
|
|
|
|
@classmethod
|
|
def get_monitor_pooled(self, module, purpose, pool):
|
|
"""
|
|
Get monitor of 'module' for 'purpose' in pool.
|
|
|
|
:param module & purpose: see get_monitor()
|
|
:param pool: monitors pool for looking up
|
|
:returns mpi: Success, the found monitor
|
|
:raises LookupError: Fail, find monitor error
|
|
"""
|
|
mpis = []
|
|
for m in pool:
|
|
if (module is not None) and (m._module != module):
|
|
continue
|
|
if (purpose is not None) and (m._purpose != purpose):
|
|
continue
|
|
mpis.append(m)
|
|
|
|
if len(mpis) != 1:
|
|
err = LookupError("Find {} {}-{} monitors in pool".format(
|
|
len(mpis), module, purpose))
|
|
logger.error("MPI.{}: {}".format(
|
|
sys._getframe().f_code.co_name, str(err)))
|
|
raise err
|
|
else:
|
|
return mpis[0]
|
|
|
|
@classmethod
|
|
def get_monitors_data(self, monitors, pool=None):
|
|
"""
|
|
Get given monitors report data in one.
|
|
|
|
:param monitors: ((module, purpose, options), ...)
|
|
options is for report(para)
|
|
:param pool: monitors pool for looking up
|
|
:returns list: Success, decoded data strings of all given monitors
|
|
:returns Exceptions: Success, formatted info
|
|
:raises LookupError: Fail, find monitor error
|
|
"""
|
|
mts = []
|
|
for m in monitors:
|
|
if pool is None:
|
|
mon = MPI.get_monitor(m[0], m[1])
|
|
else:
|
|
mon = MPI.get_monitor_pooled(m[0], m[1], pool)
|
|
mt = ThreadedCall(mon.report, ("data", None, m[2]))
|
|
mts.append(mt)
|
|
mt.start()
|
|
|
|
rets = []
|
|
for mt in mts:
|
|
start = time.time()
|
|
ret = mt.get_result()
|
|
end = time.time()
|
|
logger.debug("MPI.{}: Cost {} s to call {}, ret={}".format(
|
|
sys._getframe().f_code.co_name, end-start, mt.func, str(ret)))
|
|
if isinstance(ret, Exception):
|
|
return ret
|
|
rets += ret
|
|
return rets
|
|
|
|
|
|
class CPI:
|
|
"""The configurator plugin"""
|
|
|
|
def __init__(self):
|
|
"""
|
|
Initialize.
|
|
|
|
:param: None
|
|
:returns: None
|
|
:raises: None
|
|
"""
|
|
all_cpis = []
|
|
all_modules = []
|
|
all_submods = []
|
|
for m in configurator.common.Configurator.__subclasses__():
|
|
all_cpis.append((m._module, m._submod))
|
|
all_modules.append(m._module)
|
|
all_submods.append(m._submod)
|
|
self.get_configurators.__func__.__doc__ = self.get_configurators.__func__.__doc__ % (
|
|
set(all_modules), set(all_submods))
|
|
self.get_configurator.__func__.__doc__ = self.get_configurator.__func__.__doc__ % (
|
|
all_cpis)
|
|
|
|
@classmethod
|
|
def get_configurators(self, module=None, submod=None):
|
|
"""
|
|
Get configurators of 'module'.'submod'.
|
|
|
|
:param module(optional): %s
|
|
:param submod(optional): %s
|
|
:returns list: Success, all found configurators or null
|
|
:raises: None
|
|
"""
|
|
cpis = []
|
|
for c in configurator.common.Configurator.__subclasses__():
|
|
if (module is not None) and (c._module != module):
|
|
continue
|
|
if (submod is not None) and (c._submod != submod):
|
|
continue
|
|
ce = c()
|
|
cpis.append(ce)
|
|
return cpis
|
|
|
|
@classmethod
|
|
def get_configurator(self, module, submod):
|
|
"""
|
|
Get configurator of 'module'.'submod'.
|
|
|
|
:param module & submod: %s
|
|
:returns cpi: Success, the found configurator
|
|
:raises LookupError: Fail, find configurator error
|
|
"""
|
|
cpis = CPI.get_configurators(module, submod)
|
|
if len(cpis) != 1:
|
|
err = LookupError("Find {} {}-{} configurators".format(
|
|
len(cpis), module, submod))
|
|
logger.error("CPI.{}: {}".format(
|
|
sys._getframe().f_code.co_name, str(err)))
|
|
raise err
|
|
else:
|
|
return cpis[0]
|
|
|
|
|
|
# if __name__ == "__main__":
|
|
# if len(sys.argv) == 4:
|
|
# ret = MPI.get_monitors(sys.argv[1], sys.argv[2])
|
|
# print(ret[0].get(sys.argv[3]))
|
|
# elif len(sys.argv) == 3:
|
|
# ret = MPI.get_monitors(sys.argv[1], sys.argv[2])
|
|
# print(ret[0].get())
|
|
# else:
|
|
# print('usage: ' + sys.argv[0] + ' module purpose')
|
|
|
|
# if __name__ == "__main__":
|
|
# if len(sys.argv) == 3:
|
|
# ret = CPI.get_configurators(sys.argv[1])
|
|
# print(ret[0].set(sys.argv[2]))
|
|
# else:
|
|
# print('usage: ' + sys.argv[0] + ' module key=val')
|
|
|
|
if __name__ == "__main__":
|
|
monitors = (
|
|
("CPU",
|
|
"STAT",
|
|
"--interval=1;--cpu=1 --fields=usr --fields=sys --fields=iowait --fields=irq --fields=guest"),
|
|
("STORAGE",
|
|
"STAT",
|
|
"--interval=3;--device=sda --fields=rMBs --fields=wMBs"),
|
|
("NET",
|
|
"STAT",
|
|
"--interval=2;--nic=lo --fields=wKBs --fields=rKBs"),
|
|
("PERF",
|
|
"STAT",
|
|
"--interval=5;--fields=cycles --fields=instructions --fields=cache-misses"))
|
|
print(MPI.get_monitors_data(monitors))
|