grpc added simple throughputs stream events
This commit is contained in:
parent
5542dbbce2
commit
4c1d7bfb22
4 changed files with 109 additions and 2 deletions
|
@ -276,6 +276,17 @@ class CoreGrpcClient(object):
|
||||||
stream = self.stub.Events(request)
|
stream = self.stub.Events(request)
|
||||||
start_streamer(stream, handler)
|
start_streamer(stream, handler)
|
||||||
|
|
||||||
|
def throughputs(self, handler):
|
||||||
|
"""
|
||||||
|
Listen for throughput events with information for interfaces and bridges.
|
||||||
|
|
||||||
|
:param handler: handler for every event
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
request = core_pb2.ThroughputsRequest()
|
||||||
|
stream = self.stub.Throughputs(request)
|
||||||
|
start_streamer(stream, handler)
|
||||||
|
|
||||||
def add_node(self, session_id, node):
|
def add_node(self, session_id, node):
|
||||||
"""
|
"""
|
||||||
Add node to session.
|
Add node to session.
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
import atexit
|
import atexit
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import tempfile
|
import tempfile
|
||||||
import time
|
import time
|
||||||
from Queue import Queue, Empty
|
from Queue import Queue, Empty
|
||||||
from core.data import NodeData, LinkData, EventData, ConfigData, ExceptionData, FileData
|
|
||||||
|
|
||||||
import grpc
|
import grpc
|
||||||
from concurrent import futures
|
from concurrent import futures
|
||||||
|
|
||||||
|
from core.data import NodeData, LinkData, EventData, ConfigData, ExceptionData, FileData
|
||||||
from core.emulator.emudata import NodeOptions, InterfaceData, LinkOptions
|
from core.emulator.emudata import NodeOptions, InterfaceData, LinkOptions
|
||||||
from core.enumerations import NodeTypes, EventTypes, LinkTypes
|
from core.enumerations import NodeTypes, EventTypes, LinkTypes
|
||||||
from core.grpc import core_pb2
|
from core.grpc import core_pb2
|
||||||
|
@ -19,6 +20,7 @@ from core.mobility import BasicRangeModel, Ns2ScriptedMobility
|
||||||
from core.service import ServiceManager
|
from core.service import ServiceManager
|
||||||
|
|
||||||
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
|
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
|
||||||
|
_INTERFACE_REGEX = re.compile("\d+")
|
||||||
|
|
||||||
|
|
||||||
def convert_value(value):
|
def convert_value(value):
|
||||||
|
@ -105,6 +107,22 @@ def convert_link(session, link_data):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_net_stats():
|
||||||
|
with open("/proc/net/dev", "r") as f:
|
||||||
|
data = f.readlines()[2:]
|
||||||
|
|
||||||
|
stats = {}
|
||||||
|
for line in data:
|
||||||
|
line = line.strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
line = line.split()
|
||||||
|
line[0] = line[0].strip(":")
|
||||||
|
stats[line[0]] = {"rx": float(line[1]), "tx": float(line[9])}
|
||||||
|
|
||||||
|
return stats
|
||||||
|
|
||||||
|
|
||||||
class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
def __init__(self, coreemu):
|
def __init__(self, coreemu):
|
||||||
super(CoreGrpcServer, self).__init__()
|
super(CoreGrpcServer, self).__init__()
|
||||||
|
@ -407,6 +425,46 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
compressed_data=event.compressed_data
|
compressed_data=event.compressed_data
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def Throughputs(self, request, context):
|
||||||
|
delay = 3
|
||||||
|
last_check = None
|
||||||
|
last_stats = None
|
||||||
|
while self._is_running(context):
|
||||||
|
now = time.time()
|
||||||
|
stats = get_net_stats()
|
||||||
|
|
||||||
|
# calculate average
|
||||||
|
if last_check is not None:
|
||||||
|
interval = now - last_check
|
||||||
|
throughputs_event = core_pb2.ThroughputsEvent()
|
||||||
|
for key, current_rxtx in stats.iteritems():
|
||||||
|
previous_rxtx = last_stats.get(key)
|
||||||
|
if not previous_rxtx:
|
||||||
|
continue
|
||||||
|
rx_kbps = (current_rxtx["rx"] - previous_rxtx["rx"]) * 8.0 / interval
|
||||||
|
tx_kbps = (current_rxtx["tx"] - previous_rxtx["tx"]) * 8.0 / interval
|
||||||
|
throughput = rx_kbps + tx_kbps
|
||||||
|
print "%s - %s" % (key, throughput)
|
||||||
|
if key.startswith("veth"):
|
||||||
|
key = key.split(".")
|
||||||
|
node_id = int(_INTERFACE_REGEX.search(key[0]).group())
|
||||||
|
interface_id = int(key[1])
|
||||||
|
interface_throughput = throughputs_event.interface_throughputs.add()
|
||||||
|
interface_throughput.node_id = node_id
|
||||||
|
interface_throughput.interface_id = interface_id
|
||||||
|
interface_throughput.throughput = throughput
|
||||||
|
elif key.startswith("b."):
|
||||||
|
node_id = int(key.split(".")[1])
|
||||||
|
bridge_throughput = throughputs_event.bridge_throughputs.add()
|
||||||
|
bridge_throughput.node_id = node_id
|
||||||
|
bridge_throughput.throughput = throughput
|
||||||
|
|
||||||
|
yield throughputs_event
|
||||||
|
|
||||||
|
last_check = now
|
||||||
|
last_stats = stats
|
||||||
|
time.sleep(delay)
|
||||||
|
|
||||||
def AddNode(self, request, context):
|
def AddNode(self, request, context):
|
||||||
logging.debug("add node: %s", request)
|
logging.debug("add node: %s", request)
|
||||||
session = self.get_session(request.session_id, context)
|
session = self.get_session(request.session_id, context)
|
||||||
|
|
|
@ -26,9 +26,11 @@ service CoreApi {
|
||||||
rpc SetSessionState (SetSessionStateRequest) returns (SetSessionStateResponse) {
|
rpc SetSessionState (SetSessionStateRequest) returns (SetSessionStateResponse) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// event streams
|
// streams
|
||||||
rpc Events (EventsRequest) returns (stream Event) {
|
rpc Events (EventsRequest) returns (stream Event) {
|
||||||
}
|
}
|
||||||
|
rpc Throughputs (ThroughputsRequest) returns (stream ThroughputsEvent) {
|
||||||
|
}
|
||||||
|
|
||||||
// node rpc
|
// node rpc
|
||||||
rpc AddNode (AddNodeRequest) returns (AddNodeResponse) {
|
rpc AddNode (AddNodeRequest) returns (AddNodeResponse) {
|
||||||
|
@ -195,6 +197,25 @@ message EventsRequest {
|
||||||
int32 session_id = 1;
|
int32 session_id = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ThroughputsRequest {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ThroughputsEvent {
|
||||||
|
repeated BridgeThroughput bridge_throughputs = 1;
|
||||||
|
repeated InterfaceThroughput interface_throughputs = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message InterfaceThroughput {
|
||||||
|
int32 node_id = 1;
|
||||||
|
int32 interface_id = 2;
|
||||||
|
double throughput = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BridgeThroughput {
|
||||||
|
int32 node_id = 1;
|
||||||
|
double throughput = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message Event {
|
message Event {
|
||||||
oneof event_type {
|
oneof event_type {
|
||||||
SessionEvent session_event = 1;
|
SessionEvent session_event = 1;
|
||||||
|
|
|
@ -772,6 +772,23 @@ class TestGrpc:
|
||||||
# then
|
# then
|
||||||
queue.get(timeout=5)
|
queue.get(timeout=5)
|
||||||
|
|
||||||
|
def test_throughputs(self, grpc_server):
|
||||||
|
# given
|
||||||
|
client = CoreGrpcClient()
|
||||||
|
session = grpc_server.coreemu.create_session()
|
||||||
|
queue = Queue()
|
||||||
|
|
||||||
|
def handle_event(event_data):
|
||||||
|
queue.put(event_data)
|
||||||
|
|
||||||
|
# then
|
||||||
|
with client.context_connect():
|
||||||
|
client.throughputs(handle_event)
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
# then
|
||||||
|
queue.get(timeout=5)
|
||||||
|
|
||||||
def test_session_events(self, grpc_server):
|
def test_session_events(self, grpc_server):
|
||||||
# given
|
# given
|
||||||
client = CoreGrpcClient()
|
client = CoreGrpcClient()
|
||||||
|
|
Loading…
Add table
Reference in a new issue