Skip to content

Commit

Permalink
Improved the net module.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jahaja committed Mar 10, 2014
1 parent f270376 commit 26f89e0
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 46 deletions.
115 changes: 70 additions & 45 deletions psdash/net.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,83 +6,108 @@
import time
import sys

SIOCGIFCONF = 0x8912

if sys.maxsize > (1 << 31):
ifreq = struct.Struct("16sH2xI16x")
else:
# TODO fix format for 32 bit
ifreq = struct.Struct("16sH2xI16x")

ifconf = struct.Struct("iL")


class NetIOCounters(object):
_last_req = None
_last_req_time = None

@classmethod
def request(cls):
io_counters = psutil.network_io_counters(pernic=True)
def __init__(self, pernic=True):
self.last_req = None
self.last_req_time = None
self.pernic = pernic

def _get_net_io_counters(self):
"""
Fetch io counters from psutil and transform it to
dicts with the additional attributes defaulted
"""
counters = psutil.network_io_counters(pernic=self.pernic)

res = {}
for name, io in io_counters.iteritems():
for name, io in counters.iteritems():
res[name] = io._asdict()
res[name].update({"tx_per_sec": 0, "rx_per_sec": 0})

if not cls._last_req:
# no request to compare with so let's just return.
cls._last_req = io_counters
cls._last_req_time = time.time()
return res
return res

def _set_last_request(self, counters):
self.last_req = counters
self.last_req_time = time.time()

elapsed = int(time.time() - cls._last_req_time)
elapsed = max(elapsed, 1)
def get(self):
return self.last_req

for name, io in io_counters.iteritems():
last_io = cls._last_req.get(name)
def update(self):
counters = self._get_net_io_counters()

if not self.last_req:
self._set_last_request(counters)
return counters

time_delta = time.time() - self.last_req_time
if not time_delta:
return counters

for name, io in counters.iteritems():
last_io = self.last_req.get(name)
if not last_io:
continue

res[name].update({
"rx_per_sec": (io.bytes_recv - last_io.bytes_recv) / elapsed,
"tx_per_sec": (io.bytes_sent - last_io.bytes_sent) / elapsed
counters[name].update({
"rx_per_sec": (io["bytes_recv"] - last_io["bytes_recv"]) / time_delta,
"tx_per_sec": (io["bytes_sent"] - last_io["bytes_sent"]) / time_delta
})

cls._last_req = io_counters
cls._last_req_time = time.time()
self._set_last_request(counters)

return res
return counters


def get_network_interfaces(max_net_inf=10):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
bufsize = ifreq.size * max_net_inf
def get_interface_addresses(max_interfaces=10):
"""
Get addresses of available network interfaces.
See netdevice(7) and ioctl(2) for details.
Returns a list of dicts
"""

SIOCGIFCONF = 0x8912

if sys.maxsize > (1 << 31):
ifreq = struct.Struct("16sH2xI16x")
else:
# TODO fix format for 32 bit
ifreq = struct.Struct("16sH2xI16x")

# create request param struct
ifconf = struct.Struct("iL")
bufsize = ifreq.size * max_interfaces
buf = array.array("B", "\0" * bufsize)
ifconf_val = ifconf.pack(bufsize, buf.buffer_info()[0])

# make ioctl request
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ifconf_res = fcntl.ioctl(sock.fileno(), SIOCGIFCONF, ifconf_val)

sock.close()

buflen, _ = ifconf.unpack(ifconf_res)
resbuf = buf.tostring()

io_counters = NetIOCounters.request()

interfaces = []
addresses = []
for x in xrange(buflen / ifreq.size):
# read the size of the struct from the result buffer
# and unpack it.
start = x * ifreq.size
stop = start + ifreq.size

name, family, address = ifreq.unpack(resbuf[start:stop])

# transform the address to it's string representation
ip = socket.inet_ntoa(struct.pack("I", address))
name = name.rstrip("\0")

inf = {
addr = {
"name": name,
"family": family,
"ip": ip
}
inf.update(io_counters.get(name, {}))

interfaces.append(inf)
return interfaces
addresses.append(addr)

return addresses
28 changes: 27 additions & 1 deletion psdash/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@
import socket
import os
from datetime import datetime
import time
import threading
import uuid
from net import get_network_interfaces
from log import Logs
from net import NetIOCounters, get_interface_addresses

logs = Logs()
net_io_counters = NetIOCounters()


def get_disks(all_partitions=False):
Expand All @@ -37,6 +40,16 @@ def get_users():
return users


def get_network_interfaces():
io_counters = net_io_counters.get()
addresses = get_interface_addresses()

for inf in addresses:
inf.update(io_counters.get(inf["name"], {}))

return addresses


app = Flask(__name__)
app.config.from_envvar("PSDASH_CONFIG", silent=True)
# If the secret key is not read from the config just set it to something.
Expand Down Expand Up @@ -386,11 +399,24 @@ def parse_args():
return parser.parse_args()


def start_background_worker(sleep_time=3):
def work():
while True:
net_io_counters.update()
time.sleep(sleep_time)

t = threading.Thread(target=work)
t.daemon = True
t.start()


def main():
args = parse_args()
for log in args.logs:
logs.add_available(log)

start_background_worker()

app.run(
host=args.bind_host,
port=args.port,
Expand Down

0 comments on commit 26f89e0

Please sign in to comment.