diff --git a/source/tools/detect/netinfo/Makefile b/source/tools/detect/netinfo/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..70f265f8969bfa98ea513654973da4c130bc9714 --- /dev/null +++ b/source/tools/detect/netinfo/Makefile @@ -0,0 +1,3 @@ +target := netinfo +DEPEND := "prev{default python};" +include $(SRC)/mk/py.mk diff --git a/source/tools/detect/netinfo/collector/__init__.py b/source/tools/detect/netinfo/collector/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..63df34d31ffbfc667acb4edd253b21d2c2db7cf4 --- /dev/null +++ b/source/tools/detect/netinfo/collector/__init__.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +""" +------------------------------------------------- + File Name: __init__.py + Description : + Author : liaozhaoyan + date: 2021/10/23 +------------------------------------------------- + Change Activity: + 2021/10/23: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +if __name__ == "__main__": + pass diff --git a/source/tools/detect/netinfo/collector/baseCollector.py b/source/tools/detect/netinfo/collector/baseCollector.py new file mode 100644 index 0000000000000000000000000000000000000000..8f4a355083df0f12f07da6209a685c8e759a219c --- /dev/null +++ b/source/tools/detect/netinfo/collector/baseCollector.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# cython:language_level=3 +""" +------------------------------------------------- + File Name: baseCollector + Description : + Author : liaozhaoyan + date: 2021/10/23 +------------------------------------------------- + Change Activity: + 2021/10/23: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +class CbaseCollector(object): + def __init__(self, sender): + super(CbaseCollector, self).__init__() + self._sender = sender + + def proc(self): + pass + +if __name__ == "__main__": + pass diff --git a/source/tools/detect/netinfo/collector/diskFree.py b/source/tools/detect/netinfo/collector/diskFree.py new file mode 100644 index 0000000000000000000000000000000000000000..609db85fcd37ca519198b4b23d287377bf21a458 --- /dev/null +++ b/source/tools/detect/netinfo/collector/diskFree.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# cython:language_level=3 +""" +------------------------------------------------- + File Name: conHost + Description : + Author : liaozhaoyan + date: 2021/9/17 +------------------------------------------------- + Change Activity: + 2021/9/17: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +import sys +from .baseCollector import CbaseCollector +import time +sys.path.append("../") +from common.cmds import execCmd + +LONG_COUNT = 600 + + +class CdiskFree(CbaseCollector): + def __init__(self, sender): + super(CdiskFree, self).__init__(sender) + self.__count = 0 + + def _transSize(self, s): + unitD = {"K": 1024, "M": 1024 * 1024, "G": 1024 * 1024 * 1024, "T": 1024 * 1024 * 1024 * 1024, "P": 1024 * 1024 * 1024 * 1024 * 1024, "E": 1024 * 1024 * 1024 * 1024 * 1024 * 1024, "Z": 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024} + if str.isdigit(s): + return float(s) + else: + f = float(s[:-1]) + unit = s[-1] + return f * unitD[unit] / (unitD['G']) + + def proc(self): + # get file system + dfs = execCmd('df -h') + for l in dfs.split('\n'): + if l.startswith("/dev/"): + # Filesystem Size Used Avail Use% Mounted on + hard, total, use, free, percent, mount = l.split() + mount = '/' + mount[9:] + self._sender.put("fsinfo", ',disk=%s total=%f,use=%f,free=%f,percent=%f,mount="%s"' % (hard, self._transSize(total), self._transSize(use), self._transSize(free), float(percent[:-1]), mount)) + + if self.__count % LONG_COUNT: + self.__count += 1 + return + self.__count += 1 + + # os-release + dRelease = {} + heads = ["NAME", "VERSION", "PRETTY_NAME", "VERSION_ID"] + lines = execCmd('cat /etc/os-release').split('\n') + for line in lines: + try: + head, content = line.split('=', 1) + except ValueError: + break + if head in heads: + dRelease[str.lower(head)] = content.strip('"') + dRelease['os_kernel'] = execCmd('uname -r') + s = "" + for k, v in dRelease.items(): + s += '%s="%s",' % (k, v) + self._sender.put('os_host_release', " %s" % s[:-1]) + +if __name__ == "__main__": + h = CdiskFree() + while True: + h.proc() + time.sleep(60) + pass diff --git a/source/tools/detect/netinfo/collector/longBase.py b/source/tools/detect/netinfo/collector/longBase.py new file mode 100644 index 0000000000000000000000000000000000000000..7e3febbef2c91fed6392716a8af7b242e4a43699 --- /dev/null +++ b/source/tools/detect/netinfo/collector/longBase.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# cython:language_level=3 +""" +------------------------------------------------- + File Name: longBase + Description : + Author : liaozhaoyan + date: 2021/8/14 +------------------------------------------------- + Change Activity: + 2021/8/14: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +import sys +from .baseCollector import CbaseCollector +import time +import os +from collections import deque +sys.path.append("../") +from common.cmds import CasyncCmdQue + + +class ClongBase(CbaseCollector): + def __init__(self, sender): + super(ClongBase, self).__init__(sender) + cmd = "%s/longcheer -d -C -X %s" % (os.getcwd(), sender.host) + self.__toKill = 0 + self._t = CasyncCmdQue(cmd, self._proc) + self._q = deque() + + def __getKilling(self, lines): + if lines.startswith("pid:"): + _, pid = lines.split(":", 1) + self.__toKill = int(pid.strip()) + else: + print("longtrace start: %s, not pid: xxxx" % lines) + sys.exit(1) + + def _proc(self, lines): + self._q.append(lines) + + def loop(self): + while True: + time.sleep(1) + + def proc(self): + lines = "" + while True: + try: + lines += self._q.pop() + except IndexError: + break + if len(lines) > 0: + self._sender.puts(lines[:-1]) + + +if __name__ == "__main__": + l = ClongBase() + l.loop() diff --git a/source/tools/detect/netinfo/collector/packetCollector.py b/source/tools/detect/netinfo/collector/packetCollector.py new file mode 100644 index 0000000000000000000000000000000000000000..f3129fda3a343bb44b83f06e1cf70093228ddac7 --- /dev/null +++ b/source/tools/detect/netinfo/collector/packetCollector.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# cython:language_level=3 +""" +------------------------------------------------- + File Name: pktMon + Description : + Author : liaozhaoyan + date: 2021/6/27 +------------------------------------------------- + Change Activity: + 2021/6/27: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +from .pktDrop import CprocCat +from .baseCollector import CbaseCollector +cellsMon = ['Abort', 'PAWS', 'Err', 'Fail', 'Drop', 'Overflow'] + + +class ClocalDrop(CprocCat): + def __init__(self, cmds, cell): + super(ClocalDrop, self).__init__(cmds, cell) + + def checkAdditon(self, dSum): + d = self.proc() + log = "" + for k in d.keys(): + if d[k] > self._d[k]: + delta = d[k] - self._d[k] + log += "%s: %d, " %(k, delta) + for cell in self.cells: + if cell in k: + dSum[cell] += delta + self._d[k] = d[k] + return log + +class CpacketCollector(CbaseCollector): + def __init__(self, sender, cells=cellsMon): + super(CpacketCollector, self).__init__(sender) + catCmds = ["cat /proc/net/snmp", "cat /proc/net/netstat"] + self.__ps = [] + self.__cell = cells + for c in catCmds: + self.__ps.append(ClocalDrop(c, cells)) + + def __createCellDict(self): + vList = [0] * len(self.__cell) + return dict(zip(self.__cell, vList)) + + def proc(self): + dSum = self.__createCellDict() + logs = "" + for p in self.__ps: + logs += p.checkAdditon(dSum) + if len(logs): + self._sender.put("pkt_log", ' logs="%s"' % logs[:-2]) + for k in dSum.keys(): + self._sender.put("pkt_staus", ",status=%s count=%d" % (k, dSum[k])) + +if __name__ == "__main__": + pass diff --git a/source/tools/detect/netinfo/collector/pingTrace.py b/source/tools/detect/netinfo/collector/pingTrace.py new file mode 100644 index 0000000000000000000000000000000000000000..e0eeb5647409cd68d233e191899a904416fc5c36 --- /dev/null +++ b/source/tools/detect/netinfo/collector/pingTrace.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# cython:language_level=3 +""" +------------------------------------------------- + File Name: pingSls.py + Description : + Author : liaozhaoyan + date: 2021/8/3 +------------------------------------------------- + Change Activity: + 2021/8/3: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +import os +import sys +import time +import json +from threading import Lock +from collections import deque +from .baseCollector import CbaseCollector +sys.path.append("../") +from common.cmds import CasyncCmdQue, execCmd + +getIndex = ["l_tx_kern", "l_tx_qdisc", "l_rx_kern", "l_rx_task_waking", "l_rx_task_queue", "l_tx_merged_kern", "l_rx_merged_kern", "total"] + + +class CpingTrace(CbaseCollector): + def __init__(self, sender): + super(CpingTrace, self).__init__(sender) + self._gw = self._getGW() + self._lock = Lock() + self.t = CasyncCmdQue("%s/pingtrace -c %s" %(os.getcwd(), self._gw), self._cb) + self.q = deque(maxlen=60) + self._dRec = None + + def parse(self, line): + d = json.loads(line) + delays = d['delays'] + dRet = {} + dRet['seq'] = d['meta']['seq'] + for ddelay in delays: + if ddelay['delay'] in getIndex: + dRet[ddelay['delay']] = ddelay['ts'] + return dRet + + def _cb(self, line): + r = self.parse(line) + with self._lock: + if self._dRec is None: + self._dRec = r + elif r['total'] > self._dRec['total']: + self._dRec = r + + def _getGW(self): + lines = execCmd('ip route').split('\n') + for line in lines: + if line.startswith("default via"): + ls = line.split(' ') + return ls[2] + raise Exception("no default gw.") + + def popEle(self): + with self._lock: + if self._dRec is None: + return + for k, v in self._dRec.items(): + self._sender.put('pingtrace', " %s=%d" % (k, v)) + self._dRec = None + + def proc(self): + self.popEle() + + def loop(self): + while True: + time.sleep(60) + self.popEle() + + +if __name__ == "__main__": + p = CpingTrace() + p.loop() + pass diff --git a/source/tools/detect/netinfo/collector/pktDrop.py b/source/tools/detect/netinfo/collector/pktDrop.py new file mode 100644 index 0000000000000000000000000000000000000000..c0ed3352f30063cbadbf4974cbb68e0451f4b89e --- /dev/null +++ b/source/tools/detect/netinfo/collector/pktDrop.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# cython:language_level=3 +""" +------------------------------------------------- + File Name: pktdrop + Description : + Author : liaozhaoyan + date: 2021/6/22 +------------------------------------------------- + Change Activity: + 2021/6/22: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +from subprocess import PIPE, Popen +import shlex +import time + +catCmds = ["cat /proc/net/snmp", "cat /proc/net/netstat"] +cells = ['Abort', 'PAWS', 'Err', 'Fail', 'Drop'] + +class CprocCat(object): + def __init__(self, cmds, cell): + self.__cmds = shlex.split(cmds) + self.cells = cell + self._d = self.proc() + + def merge_dict(self, ds): + r = {} + for d in ds: + for k, v in d.items(): + for cell in self.cells: + if cell in k: + r[k] = v + continue + return r + + def parse_vars(self, h, v): + ss = h.split(" ") + t = ss[0] + ts = ss[1:] + ss = v.split(" ") + vs = ss[1:] + ret = {} + for i, s in enumerate(ts): + ret[t + s] = int(vs[i]) + return ret + + def _exec(self): + p = Popen(self.__cmds, stdout=PIPE) + return p.stdout.read().decode('utf-8') + + def proc(self): + hs = self._exec().split('\n') + size = (len(hs) - 1) >> 1 + ds = [] + for i in range(size): + ds.append(self.parse_vars(hs[2 * i].strip(), hs[2 * i + 1].strip())) + return self.merge_dict(ds) + + def check(self): + d = self.proc() + for k in d.keys(): + if d[k] > self._d[k]: + print(k, d[k] - self._d[k]) + self._d[k] = d[k] + +if __name__ == "__main__": + ps = [] + for c in catCmds: + ps.append(CprocCat(c, cells)) + while True: + time.sleep(60) + for p in ps: + p.check() + pass diff --git a/source/tools/detect/netinfo/collector/retransCollector.py b/source/tools/detect/netinfo/collector/retransCollector.py new file mode 100644 index 0000000000000000000000000000000000000000..37dea448957abf1805f8a0485e9631ea4d4116e8 --- /dev/null +++ b/source/tools/detect/netinfo/collector/retransCollector.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# cython:language_level=3 +""" +------------------------------------------------- + File Name: retransCollector + Description : + Author : liaozhaoyan + date: 2021/10/24 +------------------------------------------------- + Change Activity: + 2021/10/24: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +import sys +from .baseCollector import CbaseCollector +import re +sys.path.append("../") +from common.cmds import execCmd + +socketStatCmd = "/usr/sbin/ss -tnpi" + +class CretransCollector(CbaseCollector): + def __init__(self, sender): + super(CretransCollector, self).__init__(sender) + self.__reComm = re.compile("\"(.+)\"") + self.__rePid = re.compile("pid=[0-9]+") + self.__reRetrans = re.compile("retrans:\\d+/\\d+") + self.__lastDict = self.__getDict() + + """ + ['State Recv-Q Send-Q Local Address:Port Peer Address:Port \n', 'ESTAB 0 0 172.24.183.145:22 42.120.75.145:35828 users:(("sshd",pid=680615,fd=3))\n', '\t cubic wscale:6,7 rto:247 rtt:46.089/0.209 ato:40 mss:1448 rcvmss:1392 advmss:1448 cwnd:8 ssthresh:7 bytes_acked:26373 bytes_received:19193 segs_out:548 segs_in:831 send 2.0Mbps lastsnd:23134 lastrcv:23093 lastack:23088 pacing_rate 4.0Mbps retrans:0/1 rcv_rtt:50 rcv_space:28960\n', 'ESTAB 0 0 172.24.183.145:22 42.120.75.145:23932 users:(("sshd",pid=611623,fd=3))\n', '\t cubic wscale:6,7 rto:253 rtt:52.271/24.335 ato:40 mss:1448 rcvmss:1392 advmss:1448 cwnd:7 ssthresh:4 bytes_acked:7736697 bytes_received:55437 segs_out:9248 segs_in:7753 send 1.6Mbps lastsnd:1008 lastrcv:7154 lastack:905 pacing_rate 3.1Mbps retrans:0/743 reordering:4 rcv_rtt:41 rcv_space:28960\n'] + """ + + def __transDict(self, lines): + l = (len(lines) - 1) >> 1 + d = {} + for i in range(l): + l1 = lines[2 * i].strip() + l2 = lines[2 * i + 1] + l1 = re.sub(" +", " ", l1) + src, dst, comm = l1.split(" ")[-3:] + try: + name = self.__reComm.findall(comm)[0] + except IndexError: + continue + pid = self.__rePid.findall(comm)[0].split('=')[1] + ss = self.__reRetrans.findall(l2) + if len(ss): + retrans = ss[0].split('/')[1] + else: + continue + k = "%s %s %s %s" % (name, pid, src, dst) + d[k] = int(retrans) + return d + + def __getDict(self): + lines = execCmd(socketStatCmd).split('\n') + return self.__transDict(lines[1:]) + + def proc(self): + dNow = self.__getDict() + total = 0 + log = "" + for k, v in dNow.items(): + if k in self.__lastDict.keys(): + delta = dNow[k] - self.__lastDict[k] + if delta > 0: + total += delta + log += "%s retrans %d; " % (k, delta) + if len(log): + self._sender.put('net_retrans_log', ' log="%s"' % log[:-2]) + self._sender.put('net_retrans', ' total=%di' % total) + self.__lastDict = dNow + +if __name__ == "__main__": + pass diff --git a/source/tools/detect/netinfo/collector/socketStatus.py b/source/tools/detect/netinfo/collector/socketStatus.py new file mode 100644 index 0000000000000000000000000000000000000000..89d13970297842b47253cb9f1a735a93a357194b --- /dev/null +++ b/source/tools/detect/netinfo/collector/socketStatus.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# cython:language_level=3 +""" +------------------------------------------------- + File Name: socketStatus + Description : + Author : liaozhaoyan + date: 2021/10/23 +------------------------------------------------- + Change Activity: + 2021/10/23: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' +import sys +from .baseCollector import CbaseCollector +import re +sys.path.append("..") +from common.cmds import execCmd + +class CsocketStatus(CbaseCollector): + def __init__(self, sender): + super(CsocketStatus, self).__init__(sender) + + def putDict(self, tbl, d): + s = " " + for k, v in d.items(): + s += "%s=%d," %(k, v) + self._sender.put(tbl, s[:-1]) + """ + Total: 77 (kernel 350) + TCP: 11 (estab 3, closed 3, orphaned 0, synrecv 0, timewait 3/0), ports 0 + + Transport Total IP IPv6 + * 350 - - + RAW 0 0 0 + UDP 9 5 4 + TCP 8 6 2 + INET 17 11 6 + FRAG 0 0 0 + """ + + def proc(self): + cmd = "/usr/sbin/ss -s" + lines = execCmd(cmd).split('\n') + if len(lines) < 10: + return + d = {} + + line = lines[0] + v = line.split(":")[1].strip() + total, title, kernel = v.split(" ") + d['total'] = int(total) + d['kernel'] = int(kernel[:-1]) + + line = lines[1] + v = line.split(":")[1].strip() + tcp, vv = v.split("(") + d['tcp'] = int(tcp.strip()) + stats, port = vv.split(")") + for stat in stats.split(","): + h, v = stat.strip().split(' ') + if '/' in v: + v = v.split("/")[0] + d['tcp_' + h] = int(v) + + for line in lines[5:]: + line = re.sub(" +", " ", line) + ts = line.split(" ") + if len(ts) < 2 or ts[0][:-1] == "TCP": + continue + d[ts[0][:-1]] = int(ts[1]) + self.putDict('socket', d) + +if __name__ == "__main__": + pass diff --git a/source/tools/detect/netinfo/common/__init__.py b/source/tools/detect/netinfo/common/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..2baa7a70e7483f5329fbc7b527e12dd824ae5807 --- /dev/null +++ b/source/tools/detect/netinfo/common/__init__.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +""" +------------------------------------------------- + File Name: __init__.py + Description : + Author : liaozhaoyan + date: 2022/2/15 +------------------------------------------------- + Change Activity: + 2022/2/15: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +if __name__ == "__main__": + pass diff --git a/source/tools/detect/netinfo/common/argParser.py b/source/tools/detect/netinfo/common/argParser.py new file mode 100644 index 0000000000000000000000000000000000000000..9f93e71470ce98d154aac30f4be62e6d4b7c8b9b --- /dev/null +++ b/source/tools/detect/netinfo/common/argParser.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +""" +------------------------------------------------- + File Name: argParser + Description : + Author : liaozhaoyan + date: 2022/2/16 +------------------------------------------------- + Change Activity: + 2022/2/16: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +from .codec import decodeArgs +from urllib import parse +tUrl = "http://pylcc.openanolis.cn:8086/?db=sysom&user=Y%3D4WatRW&pass=bpxWY%3DMjMxM3" + + +def installConfig(url, qList): + res = parse.urlparse(url) + qs = parse.parse_qs(res.query) + qDict = {} + if "host" in qList: + qDict["host"] = res.netloc + for q in qs: + if q not in qDict: + decodeArgs(qDict, q, qs[q][0]) + for k in qList: + if k not in qDict: + raise ValueError("%s is a variable that must be set" % k) + return qDict + + +if __name__ == "__main__": + wants = ["host", "db", "user", "pass"] + print(installConfig(tUrl, wants)) + pass diff --git a/source/tools/detect/netinfo/common/cmds.py b/source/tools/detect/netinfo/common/cmds.py new file mode 100644 index 0000000000000000000000000000000000000000..bc857571467708878e691eabad998abb36219de2 --- /dev/null +++ b/source/tools/detect/netinfo/common/cmds.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +""" +------------------------------------------------- + File Name: cmds + Description : + Author : liaozhaoyan + date: 2022/2/17 +------------------------------------------------- + Change Activity: + 2022/2/17: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +import sys +import json +from threading import Thread +import atexit +from subprocess import PIPE, Popen +import shlex +ON_POSIX = 'posix' in sys.builtin_module_names + +def execCmd(cmd): + p = Popen(shlex.split(cmd), stdout=PIPE) + return p.stdout.read().decode('utf-8') + +class CasyncCmdQue(Thread): + def __init__(self, cmd, callBack): + super(CasyncCmdQue, self).__init__() + self.daemon = True # thread dies with the program + + self.__p = Popen(shlex.split(cmd), stdout=PIPE, stdin=PIPE, close_fds=ON_POSIX) + self._callBack = callBack + self._stop = False + self.start() + atexit.register(self.hook) + + def hook(self): + print("stop.") + self._stop = True + self.__p.kill() + + def setCallBack(self, callBack): + self._callBack = callBack + + def run(self): + out = self.__p.stdout + for line in iter(out.readline, b''): + self._callBack(line.decode()) + if self._stop: + break + out.close() + +class CconProc(object): + def __init__(self): + super(CconProc, self).__init__() + + def getDockerName(self, serial): + if serial == '' or serial == '/': + return "host" + try: + con = serial.split("-", 1)[1].split(".", 1)[0] # docker-xxxxx.scope + except IndexError: + print(serial, type(serial)) + con = serial.split("-", 1)[1] + dDocker = json.loads(execCmd('docker inspect %s' % con)) + if dDocker is not None: + return dDocker[0]['Name'] + else: + return None + +if __name__ == "__main__": + pass diff --git a/source/tools/detect/netinfo/common/codec.py b/source/tools/detect/netinfo/common/codec.py new file mode 100644 index 0000000000000000000000000000000000000000..d45d1969ec4eb48db606c40d226b2174efa10915 --- /dev/null +++ b/source/tools/detect/netinfo/common/codec.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# cython:language_level=3 +""" +------------------------------------------------- + File Name: codec + Description : + Author : liaozhaoyan + date: 2022/1/17 +------------------------------------------------- + Change Activity: + 2022/1/17: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' +import base64 + +rotateN = 7 + + +def encodeWord(word): + r = base64.b64encode(word)[::-1] + return r[rotateN:] + r[:rotateN] + + +def decodeWord(word): + w = word[-rotateN:] + word[:-rotateN] + return base64.b64decode(w[::-1]).decode() + + +decodeList = ("user", "pass") + + +def decodeArgs(qDict, arg, val): + if arg in decodeList: + qDict[arg] = decodeWord(val) + else: + qDict[arg] = val + +if __name__ == "__main__": + pass diff --git a/source/tools/detect/netinfo/common/hostId.py b/source/tools/detect/netinfo/common/hostId.py new file mode 100644 index 0000000000000000000000000000000000000000..5a996539f43d195475d36fd53b5fbf64299f9c76 --- /dev/null +++ b/source/tools/detect/netinfo/common/hostId.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +""" +------------------------------------------------- + File Name: hostId + Description : + Author : liaozhaoyan + date: 2022/2/17 +------------------------------------------------- + Change Activity: + 2022/2/17: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +import socket +from subprocess import PIPE, Popen +import shlex +from threading import Timer + +class ChostId(object): + def __init__(self, confd): + """ + setup confd + :param confd: configure dict for common use + """ + super(ChostId, self).__init__() + self._disDict = {"local": self._formNetloc, + "instance": self._instance, + } + self._dispatchMode(confd) + + def _exec(self, cmd): + kill = lambda process: process.kill() + p = Popen(shlex.split(cmd), stdout=PIPE, stderr=PIPE) + mtimer = Timer(5, kill, [p]) + r = "" + try: + mtimer.start() + r = p.stdout.read().decode('') + finally: + mtimer.cancel() + return r + + def _instance(self, dummy): + l = self._exec("curl 100.100.100.200/latest/meta-data/instance-id").strip() + if l in ["", b'']: + return self._exec('hostname').strip() + return l + + def _formNetloc(self, confd): + loc = confd['host'] + dst, port = loc.split(":") + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.connect((dst, int(port))) + ip = s.getsockname()[0] + s.close() + return ip + + def _dispatchMode(self, confd): + """ + + :param confd: configure dict for common use + """ + if "hostId" not in confd: + mode = confd['hMode'] + if mode not in self._disDict: + raise ValueError("unknown hMode: %s" % mode) + confd["hostId"] = self._disDict[mode](confd) + + +if __name__ == "__main__": + pass diff --git a/source/tools/detect/netinfo/lccApp/__init__.py b/source/tools/detect/netinfo/lccApp/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..db48ca5c0464cdb2558229192aeb23a926efbc91 --- /dev/null +++ b/source/tools/detect/netinfo/lccApp/__init__.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +""" +------------------------------------------------- + File Name: __init__.py + Description : + Author : liaozhaoyan + date: 2022/2/17 +------------------------------------------------- + Change Activity: + 2022/2/17: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +if __name__ == "__main__": + pass diff --git a/source/tools/detect/netinfo/lccApp/lccEntry.py b/source/tools/detect/netinfo/lccApp/lccEntry.py new file mode 100644 index 0000000000000000000000000000000000000000..20301e15631850b36beb63ce01a90387ee2128e0 --- /dev/null +++ b/source/tools/detect/netinfo/lccApp/lccEntry.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +""" +------------------------------------------------- + File Name: lccEntry + Description : + Author : liaozhaoyan + date: 2022/2/18 +------------------------------------------------- + Change Activity: + 2022/2/18: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' +import sys +import threading +from .netCollect import netCLoop +from .runlatency import runqLoop +sys.path.append("../") +from common.cmds import execCmd +from collector.baseCollector import CbaseCollector + + +class ClccEntry(CbaseCollector): + def __init__(self, sender): + super(ClccEntry, self).__init__(sender) + self._entry(sender) + + def _entry(self, send): + version = execCmd('uname -r') + ts = [threading.Thread(target=runqLoop, args=(send, version)), + threading.Thread(target=netCLoop, args=(send, version))] + for t in ts: + t.start() + +if __name__ == "__main__": + pass diff --git a/source/tools/detect/netinfo/lccApp/netCollect.py b/source/tools/detect/netinfo/lccApp/netCollect.py new file mode 100644 index 0000000000000000000000000000000000000000..8142dcb92bdcbcec1659a0fcefa68881517e9993 --- /dev/null +++ b/source/tools/detect/netinfo/lccApp/netCollect.py @@ -0,0 +1,157 @@ +# -*- coding: utf-8 -*- +# cython:language_level=3 +""" +------------------------------------------------- + File Name: netCollect.py + Description : + Author : liaozhaoyan + date: 2021/8/5 +------------------------------------------------- + Change Activity: + 2021/8/5: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +import os +import sys +sys.path.append("../") + +import time +import ctypes as ct +import socket +import struct +from threading import Thread +from queue import Queue + +from pylcc.lbcBase import ClbcBase + +typeList = ["rto_retrans", "zero_probe", "noport_reset", "bad_sync", "net_proc" ] +resetList = ['noport', 'bad_ack', "bad_syn", "tw_rst", "tcp_stat", "tcp_oom", "keep_alive", "bad_close", "disconnect", "tcp_abort"] + +class CPushThread(Thread): + def __init__(self, q, qName, sender): + super(CPushThread, self).__init__() + self.setDaemon(True) + self._q = q + self._name = qName + self._send = sender + + def run(self): + count = 0; i = 0 + while True: + logs = "" + while not self._q.empty(): + log = self._q.get() + logs += log + "; " + count += 1 + if len(logs): + self._send.put(self._name, ',level=warn log="%s"' % (logs[:-2])) + i += 1 + if i >= 60: + self._send.put(self._name + '_c', ' count=%d' % (count)) + i = 0; count = 0 + time.sleep(1) + + +class CnetCollect(ClbcBase): + def __init__(self, soPath, sender): + super(CnetCollect, self).__init__(soPath, workPath=os.path.split(os.path.realpath(__file__))[0]) + self._send = sender + self.__retransQ = Queue() + self.__retransQ.maxsize = 5 + self.__resetQ = Queue() + self.__resetQ.maxsize = 5 + + retransThread = CPushThread(self.__retransQ, 'net_retrans', sender) + resetThread = CPushThread(self.__resetQ, 'net_reset', sender) + + retransThread.start() + resetThread.start() + + def transPort(self, v): + return struct.unpack('H', struct.pack('>H', v))[0] + + def transIp(self, v): + return socket.inet_ntoa(struct.pack('>I', socket.htonl(v))) + + def sendLog(self, q, log): + try: + q.put(log, block=False) + except: + pass + + def dispatchReset(self, e, log): + q = self.__resetQ + if e.type == 2: #noport + log += "noport" + self.sendLog(q, log) + return + try: + stacks = self.maps['callStack'].getStacks(e.stack_id, 2) + except TypeError: + print("bad type.") + return + + if e.type == 3: + if stacks[1] == 'tcp_v4_rcv': + if e.sk_state == 12: #TCP_NEW_SYN_RECV + stat = "bad_ack" + else: + stat = "tw_rst" + elif stacks[1] == 'tcp_check_req': + stat = "bad_syn" + elif stacks[1] == 'tcp_v4_do_rcv': + stat = "tcp_stat" + else: + stat = 'unkown3%s' % stacks[1] + elif e.type == 4: + if stacks[1] == 'tcp_out_of_resources': + stat = 'tcp_oom' + elif stacks[1] == 'tcp_keepalive_timer': + stat = 'keep_alive' + elif stacks[1] == 'inet_release' or stacks[1] == 'tcp_close': + stat = 'bad_close' + elif stacks[1] == 'tcp_disconnect': + stat = 'tcp_abort' + elif stacks[1] == 'tcp_abort': + stat = 'tcp_abort' + else: + stat = 'unkown4%s' % stacks[1] + else: + stat = 'bad%d' % e.type + log += stat + self.sendLog(q, log) + + def _callback(self, cpu, data, size): + stream = ct.string_at(data, size) + e = self.maps['net_map'].event(stream) + # con = self._cp.getDockerName(e.con) + con = e.con + log = 'con:%s, task:%d|%s, tcp:%s:%d->%s:%d, state:%d, ' % (con, e.pid, e.comm, self.transIp(e.ip_src), self.transPort(e.sport), self.transIp(e.ip_dst), self.transPort(e.dport), e.sk_state) + + if e.type < 2: + log += "rcv_nxt:%d, rcv_wup:%d, snd_nxt:%d, snd_una:%d, copied_seq:%d, snd_wnd:%d, rcv_wnd:%d, lost_out:%d, packets_out:%d, retrans_out:%d, sacked_out:%d, reordering:%d, " % (e.rcv_nxt, e.rcv_wup, e.snd_nxt, e.snd_una, e.copied_seq, e.snd_wnd, e.rcv_wnd, e.lost_out, e.packets_out, e.retrans_out, e.sacked_out, e.reordering) + log += typeList[e.type] + self.sendLog(self.__retransQ, log) + else: + self.dispatchReset(e, log) + + def loop(self): + self.maps['net_map'].open_perf_buffer(self._callback) + try: + self.maps['net_map'].perf_buffer_poll() + except KeyboardInterrupt: + print("key interrupt.") + exit() + +def netCLoop(sender, version): + if "3.10" in version: + r = CnetCollect('netcollect.3.10', sender) + else: + r = CnetCollect('netcollect.4.plus', sender) + r.loop() + +if __name__ == "__main__": + n = CnetCollect('netcollect.4.plus') + n.loop() diff --git a/source/tools/detect/netinfo/lccApp/netcollect.4.plus.so b/source/tools/detect/netinfo/lccApp/netcollect.4.plus.so new file mode 100644 index 0000000000000000000000000000000000000000..e1604ab5cd56900275ee36f3c0dc97d8a5bd3024 Binary files /dev/null and b/source/tools/detect/netinfo/lccApp/netcollect.4.plus.so differ diff --git a/source/tools/detect/netinfo/lccApp/runlatency.py b/source/tools/detect/netinfo/lccApp/runlatency.py new file mode 100644 index 0000000000000000000000000000000000000000..0b56bf674bd41210283ba6e054db627f7370cd76 --- /dev/null +++ b/source/tools/detect/netinfo/lccApp/runlatency.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +# cython:language_level=3 +""" +------------------------------------------------- + File Name: runlantency + Description : + Author : liaozhaoyan + date: 2021/7/28 +------------------------------------------------- + Change Activity: + 2021/7/28: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +import os +import sys +sys.path.append("../") + +import time +import json +import ctypes as ct +from threading import Thread +from queue import Queue + +from pylcc.lbcBase import ClbcBase + +class CoomThread(Thread): + def __init__(self, e, q): + super(CoomThread, self).__init__() + self._q = q + self.setDaemon(True) + self._e = e + + def _callback(self, cpu, data, size): + stream = ct.string_at(data, size) + n = self._e.event(stream) + with open('/proc/loadavg') as stats: + avgline = stats.read().rstrip() + # con = self._cp.getDockerName(n.con) + con = n.con + log = "OOM kill task, con: %s, pid: %d, comm: %s, pages:%d, loadavg: %s" % (con, n.tpid, n.tcomm, n.pages, avgline) + try: + self._q.put(log, block=False) + except: + pass + + def run(self): + self._e.open_perf_buffer(self._callback) + try: + self._e.perf_buffer_poll() + except KeyboardInterrupt: + print("key interrupt.") + exit() + +class CrunLantency(ClbcBase): + def __init__(self, soPath, sender): + super(CrunLantency, self).__init__(soPath, workPath=os.path.split(os.path.realpath(__file__))[0]) + self.__q = Queue() + self.__q.maxsize = 60 + self._send = sender + oom = CoomThread(self.maps['oom_out'], self.__q) + oom.start() + + def _callback(self, cpu, data, size): + stream = ct.string_at(data, size) + e = self.maps['oom_out'].event(stream) + print(e.tcomm, e.fcomm) + + def loop(self): + count = 0; i = 0 + while True: + logs = "" + while not self.__q.empty(): + log = self.__q.get() + logs += log + "; " + count += 1 + if len(logs): + self._send.put("net_log", ',level=warn,src=run log="%s"' % (logs[:-2])) + i += 1 + if i >= 60: + self._send.put("net_log_c", ' count=%d' % (count)) + i = 0; count = 0 + time.sleep(1) + +def runqLoop(sender, version): + if "3.10" in version: + r = CrunLantency('runq.3.10', sender) + else: + r = CrunLantency('runq.4.plus', sender) + r.loop() + +if __name__ == "__main__": + pass diff --git a/source/tools/detect/netinfo/lccApp/runq.4.plus.so b/source/tools/detect/netinfo/lccApp/runq.4.plus.so new file mode 100644 index 0000000000000000000000000000000000000000..ebaf5175dbf788f4e04d5776a0e94f7e908014fe Binary files /dev/null and b/source/tools/detect/netinfo/lccApp/runq.4.plus.so differ diff --git a/source/tools/detect/netinfo/lccApp/sysHealth.py b/source/tools/detect/netinfo/lccApp/sysHealth.py new file mode 100644 index 0000000000000000000000000000000000000000..2c13a64bfe2425437b0a0659470b98f0c6a9c74e --- /dev/null +++ b/source/tools/detect/netinfo/lccApp/sysHealth.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +""" +------------------------------------------------- + File Name: sysHealth + Description : + Author : liaozhaoyan + date: 2022/2/17 +------------------------------------------------- + Change Activity: + 2022/2/17: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +import sys +from pylcc import ClbcBase +from surftrace import CexecCmd + +sys.path.append("../") +from collector.baseCollector import CbaseCollector + +class CsysHealth(ClbcBase): + def __init__(self, sender): + self._echo = False + self._sender = sender + super(CsysHealth, self).__init__("sysHealth") + self._c = CexecCmd() + self.setupSchedstats() + + def __del__(self): + if self._echo: + self._c.system("echo 0 > /proc/sys/kernel/sched_schedstats") + + def setupSchedstats(self): + res = self._c.cmd("cat /proc/sys/kernel/sched_schedstats") + if res == "0": + self._c.system("echo 1 > /proc/sys/kernel/sched_schedstats") + self._echo = True + + def _proc(self): + dMap = self.maps['outCnt'] + return dMap.get() + + def proc(self): + return self._proc() + + +class ChealthCollector(CbaseCollector): + def __init__(self, sender): + super(ChealthCollector, self).__init__(sender) + self._bpf = CsysHealth(sender) + self._hIndex = ("wait_ts", "waits", + "io_ts", "ios", + "hung_ts", "hungs", + "net_ts", "nets", + "mem_ts", "mems" + ) + self._vd = dict(zip(self._hIndex, [0] * len(self._hIndex))) + self._dLast = {} + + def proc(self): + d = self._bpf.proc() + dNow = {} + for k, v in d.items(): + dNow[self._hIndex[k]] = v + dDelta = self._vd.copy() + for k in dDelta.keys(): + if k in dNow: + if k in self._dLast: + dDelta[k] = dNow[k] - self._dLast[k] + else: + dDelta[k] = dNow[k] + self._dLast = dNow.copy() + + s = " " + for k, v in dDelta.items(): + s += "%s=%s," % (k, v) + self._sender.put("health", s[:-1]) + +if __name__ == "__main__": + pass diff --git a/source/tools/detect/netinfo/lccApp/sysHealth.so b/source/tools/detect/netinfo/lccApp/sysHealth.so new file mode 100644 index 0000000000000000000000000000000000000000..2a4520802a05c02c406b41903df47d9c605308d0 Binary files /dev/null and b/source/tools/detect/netinfo/lccApp/sysHealth.so differ diff --git a/source/tools/detect/netinfo/longcheer b/source/tools/detect/netinfo/longcheer new file mode 100755 index 0000000000000000000000000000000000000000..74d3659464ccbe7acbd49e10cbadcf3c516e72ee Binary files /dev/null and b/source/tools/detect/netinfo/longcheer differ diff --git a/source/tools/detect/netinfo/netinfo.py b/source/tools/detect/netinfo/netinfo.py new file mode 100644 index 0000000000000000000000000000000000000000..5e122e56edc3e8259e044fe2dcbe0c7e436b137e --- /dev/null +++ b/source/tools/detect/netinfo/netinfo.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +""" +------------------------------------------------- + File Name: entry + Description : + Author : liaozhaoyan + date: 2022/2/17 +------------------------------------------------- + Change Activity: + 2022/2/17: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +import sys +import time +from common.argParser import installConfig +from common.hostId import ChostId +from sender.influxSender import CinfluxSender + +from collector.retransCollector import CretransCollector +from collector.packetCollector import CpacketCollector +from collector.longBase import ClongBase +from collector.diskFree import CdiskFree +from collector.pingTrace import CpingTrace +from collector.socketStatus import CsocketStatus +from lccApp.sysHealth import ChealthCollector +from lccApp.lccEntry import ClccEntry + +tUrl = "http://pylcc.openanolis.cn:8086/?db=sysom&user=Y%3D4WatRW&pass=bpxWY%3DMjMxM3&baseMon=off&hMode=local" +baseConf = ["host", "db", "user", "pass"] +opdConf = {"baseMon": "on", + "pingtrace": "on", + "netMon": "on", + "lcc": "on", + "pusher": "influx"} +sendD = {"influx": CinfluxSender} +monD = { + "baseMon": [ClongBase, CdiskFree], + "pingtrace": [CpingTrace], + "netMon": [CpacketCollector, CsocketStatus, CretransCollector], + "lcc": [ChealthCollector, ClccEntry], +} + +def _setupCollector(send, op): + global monD + gms = [] + for k in monD: + if op[k] == "on": + for c in monD[k]: + gms.append(c(send)) + while True: + for m in gms: + m.proc() + print("loop.") + time.sleep(60) + +def checkConf(base, op, url): + op.update(installConfig(url, base)) + ChostId(op) + send = sendD[op["pusher"]](op) # setup pusher + _setupCollector(send, op) + +if __name__ == "__main__": + checkConf(baseConf, opdConf, sys.argv[1]) + # checkConf(baseConf, opdConf, tUrl) + pass diff --git a/source/tools/detect/netinfo/pingtrace b/source/tools/detect/netinfo/pingtrace new file mode 100755 index 0000000000000000000000000000000000000000..bf994135e9cd39d339abc355b5f1857ee8696403 Binary files /dev/null and b/source/tools/detect/netinfo/pingtrace differ diff --git a/source/tools/detect/netinfo/sender/__init__.py b/source/tools/detect/netinfo/sender/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..db48ca5c0464cdb2558229192aeb23a926efbc91 --- /dev/null +++ b/source/tools/detect/netinfo/sender/__init__.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +""" +------------------------------------------------- + File Name: __init__.py + Description : + Author : liaozhaoyan + date: 2022/2/17 +------------------------------------------------- + Change Activity: + 2022/2/17: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +if __name__ == "__main__": + pass diff --git a/source/tools/detect/netinfo/sender/influxSender.py b/source/tools/detect/netinfo/sender/influxSender.py new file mode 100644 index 0000000000000000000000000000000000000000..ad0e8fabdebdd770e611354033955a2c52d66131 --- /dev/null +++ b/source/tools/detect/netinfo/sender/influxSender.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +""" +------------------------------------------------- + File Name: influxSender + Description : + Author : liaozhaoyan + date: 2022/2/17 +------------------------------------------------- + Change Activity: + 2022/2/17: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +import requests +from .netSender import CnetSender + +class CinfluxSender(CnetSender): + def __init__(self, confd): + super(CinfluxSender, self).__init__(confd) + self._head = self._setupHead() + self._url = self._setupUrl() + + def _setupHead(self): + return "host=%s" % (self._confd['hostId']) + + def _setupUrl(self): + return "http://%s/write?db=%s&u=%s&p=%s" % ( + self._confd['host'], + self._confd['db'], + self._confd['user'], + self._confd['pass'] + ) + + def push(self, s): + if s: + response = requests.post(self._url, data=s) + if response.status_code != 204: + print("sever return %d: %s" % (response.status_code, response.headers)) + + def put(self, table, s): + w = "%s,%s%s" % (table, self._head, s) + super(CinfluxSender, self).puts(w) + +if __name__ == "__main__": + pass diff --git a/source/tools/detect/netinfo/sender/netSender.py b/source/tools/detect/netinfo/sender/netSender.py new file mode 100644 index 0000000000000000000000000000000000000000..c0b07a4030f97133beac52d13168db4f493998f5 --- /dev/null +++ b/source/tools/detect/netinfo/sender/netSender.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +""" +------------------------------------------------- + File Name: netSender + Description : + Author : liaozhaoyan + date: 2022/2/17 +------------------------------------------------- + Change Activity: + 2022/2/17: +------------------------------------------------- +""" +__author__ = 'liaozhaoyan' + +import time +from threading import Thread +from queue import Queue, Empty + +class CnetSender(Thread): + def __init__(self, confd): + super(CnetSender, self).__init__() + self.host = confd["hostId"] + self._confd = confd + self._pStr = "" + self._q = Queue() + self.start() + + def run(self): + while True: + count = 0 + try: + send = self._q.get(timeout=30) + "\n" + except Empty: + continue + + while count < 20: + try: + send += self._q.get(timeout=0.1) + "\n" + count += 1 + except Empty: + break + if len(send) > 0: + self.push(send[:-1]) + + def puts(self, s): + self._q.put(s) + + def put(self, table, s): + self._q.put(s) + + def push(self, s): + print(s) + pass + + +if __name__ == "__main__": + pass