bw_agent.py
#!/usr/bin/python
import time
def get_bandwidth_info():
lines = open("/proc/net/dev", "r").readlines()
columnLine = lines[1]
_, receiveCols , transmitCols = columnLine.split("|")
receiveCols = map(lambda a:"recv_"+a, receiveCols.split())
transmitCols = map(lambda a:"trans_"+a, transmitCols.split())
cols = receiveCols+transmitCols
faces = {}
for line in lines[2:]:
if line.find(":") < 0: continue
face, data = line.split(":")
faceData = dict(zip(cols, data.split()))
faces[face.strip()] = faceData
if 'bond0' in faces:
return int(faces['bond0']['trans_bytes'])
if '0' != faces['eth1']['trans_bytes']:
out = int(faces['eth1']['trans_bytes'])
if '0' != faces['eth2']['trans_bytes']:
out += int(faces['eth2']['trans_bytes'])
return out
if __name__ == '__main__':
old_val = get_bandwidth_info()
time.sleep(1)
res = get_bandwidth_info() - old_val
#res = round((val - old_val)/1024/1024,3)
print res
bandwidth_watch.py
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# Author: 71standby@gmail.com
# Time: 2018-02-01
# Description: Show the vidc Transmit bandwidth.
import os
import re
import sys
import time
import paramiko
from multiprocessing import Pool
#print multiprocessing.cpu_count()
class Transmit(object):
def __init__(self, ipfile, port=22, user='admin', key='/path/.ssh/known_hosts', timeout=5):
self.ipfile = ipfile
self.port = port
self.user = user
self.key = key
self.timeout = timeout
self.agent_file = 'bw_agent.py'
self.remote_file = '/data/bw_agent.py'
self.log_file = 'paramiko.log'
self.cmd = 'python /data/bw_agent.py'
self.counter = 0
def get_ips(self):
if os.path.isfile(self.ipfile):
ips = []
with open(self.ipfile) as iplist:
content = iplist.readlines()
for line in content:
if line.startswith('#'):
continue
elif Transmit.check_ip(line.strip('\n')):
ips.append(line.strip('\n'))
else:
print '%s is invalid ip address!' % line.strip('\n')
continue
return ips
elif Transmit.check_ip(self.ipfile):
return [ipfile]
else:
print '%s is invalid ip address!' % self.ipfile
sys.exit(-1)
def prepare(self, ip):
paramiko.util.log_to_file (self.log_file)
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(ip, self.port, self.user, self.key, timeout=self.timeout)
return client
def scp_agent(self, ip, client):
sftp = paramiko.SFTPClient.from_transport(client.get_transport())
sftp = client.open_sftp()
sftp.put(self.agent_file, self.remote_file)
def get_transmit(self, ip):
res = {'ip':ip, 'result':None, 'code':None}
try:
client = self.prepare(ip)
self.scp_agent(ip, client)
chan = client.get_transport().open_session()
chan.settimeout(self.timeout)
chan.exec_command(self.cmd)
res['code'] = chan.recv_exit_status()
# chan.recv_ready() chan.recv_stderr_ready() chan.exit_status_ready()
val = chan.recv(8192).strip()
res['result'] = val if 0 == res['code'] else chan.recv_stderr(8192)
except Exception, e:
res['code'] = -1
res['result'] = 0
return res
def callback(self, res):
self.counter += 1
print "IP: %s, Transmit: %s" % (res.get('ip'), res.get('result', 0))
def statistics(self, res_list):
sum = 0
for res in res_list:
sum += int(res.get()['result'])
# byte -> bit
bits = float(sum*8)
kb = bits / 1024
if kb >= 1024:
Mb = kb / 1024
if Mb >= 1024:
Gb = Mb / 1024
print "\n%s transmit: %.3f Gb" % (self.ipfile, Gb)
else:
print "\n%s transmit: %.3f Mb" % (self.ipfile, Mb)
else:
print "\n%s transmit: %.3f Kb" % (self.ipfile, kb)
@staticmethod
def check_ip(ip):
ip_str = r'^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
return True if re.match(ip_str, ip) else False
'''
Attention:
- PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed
So, the run() method is need, like proxy. [https://strcpy.me/index.php/archives/318/]
- paramiko.SSHClient().connect() parameter
- client.connect('8.8.8.8', 22, 'admin', '/path/.ssh/known_hosts', timeout=5) is ok
- client.connect('8.8.8.8', 22, 'admin', '/path/.ssh/known_hosts', 5) will raise exception:
'int' object has no attribute 'get_fingerprint'
'''
def run(cls_instance, arg):
return cls_instance.get_transmit(arg)
if __name__ == '__main__':
if 2 != len(sys.argv):
print """Usage:\n\t- %s iplist_file\n\t- %s single_ip\n""" % (sys.argv[0],sys.argv[0])
sys.exit(-1)
transmit = Transmit(sys.argv[1])
ips = transmit.get_ips()
res_list = []
t_start = time.time()
pool = Pool(20)
for ip in ips:
res = pool.apply_async(func=run, args=(transmit, ip,), callback=transmit.callback)
res_list.append(res)
pool.close()
pool.join()
# pool.terminate()
transmit.statistics(res_list)
print 'Dealt %d, Runtime is: %s' % (transmit.counter, (time.time()-t_start))
从接口获取数据,在终端上实时显示,在原位置刷新
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# Author: 71standby@gmail.com
# Time: 2018-02-11
# Description: Show the vidc Transmit bandwidth.
import os
import sys
import json
import time
import signal
import urllib2
from extra import bandwidth_info
# print color
COLOR_PINK = '\033[95m'
COLOR_BLUE = '\033[94m'
COLOR_GREEN = '\033[92m'
COLOR_YELLOW = '\033[93m'
COLOR_RED = '\033[91m'
COLOR_DEFAULT = '\033[0m'
def get_flow_info(url):
'''从接口获取当前时刻机房出口带宽值'''
try:
response = urllib2.urlopen(url, timeout=10)
return json.loads(response.read())
except Exception, e:
print("urlopen error: %s" % e)
def output(result, details):
'''按照出口流量占比从高到低排序显示'''
info = "===========================================================================================\n"
fd = sys.stdout
result_li = sorted(result.items(), key=lambda x:x[1], reverse=True)
for idc,percent in result_li:
if percent > 90:
info += "{0}{1:<20}\t".format(COLOR_RED, idc)
info += "{0:<15}{1:<15}".format(details[idc]['real'], details[idc]['threshold'])
info += "%.2f%%%s" % (percent, COLOR_DEFAULT)
else:
info += "{0:<20}\t".format(idc)
info += "{0:<15}{1:<15}".format(details[idc]['real'], details[idc]['threshold'])
info += "%.2f%%" % percent
info += "\t\t{0}\n".format(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
sys.stdout.write(info)
sys.stdout.flush()
def handler(signal_num,frame):
print "Bye..."
sys.exit(0)
if __name__ == '__main__':
signal.signal(signal.SIGINT, handler)
os.system('clear')
result = {}
details = {}
realtime_api = "http://ip:port/path/to/interface"
while True:
t_start=time.time()
ret_list = get_flow_info(realtime_api)
for idc,threshold in bandwidth_info.core_idc_bw.items():
for item in ret_list:
if item['name'] == idc:
real = item['info']['flow']
result[idc] = float(real)/(threshold*1024)*100
details[idc] = {'real':real, 'threshold':threshold*1024}
#sys.stdout.write('\033[2J') which equals to `os.system('clear')`
#os.system('clear')
# 输出在原位置上刷新: 光标上移51行
sys.stdout.write('\033[51A') # https://www.v2ex.com/t/292204
output(result, details)
print "\n%sRuntime is %s%s" % (COLOR_BLUE, time.time()-t_start, COLOR_DEFAULT)
time.sleep(30)