diff --git a/src/httprest.py b/src/httprest.py index 74e5672..ef7120e 100755 --- a/src/httprest.py +++ b/src/httprest.py @@ -520,6 +520,10 @@ def user_quotainfo_monitor(user, beans, form, issue): logger.info("handle request: monitor/user/createdvnodes/") res = G_historymgr.getCreatedVNodes(user) return json.dumps({'success':'true', 'createdvnodes':res}) + elif issue == 'net_stats': + logger.info("handle request: monitor/user/net_stats/") + res = G_historymgr.get_user_net_stats(user) + return json.dumps({'success':'true', 'net_stats':res}) else: return json.dumps({'success':'false', 'message':"Unspported Method!"}) diff --git a/src/monitor.py b/src/monitor.py index a59f400..bc4d136 100755 --- a/src/monitor.py +++ b/src/monitor.py @@ -74,6 +74,11 @@ workerinfo = {} # has the second keys same as the third keys in monitor_vnodes. workercinfo = {} +# store the network statistics of users' gateways on current Worker. +# key is username +# bytes_sent and bytes_recv are the second keys +gateways_stats = {} + # only use on worker containerpids = [] pid2name = {} @@ -218,6 +223,7 @@ class Container_Collector(threading.Thread): nowbillingval = workercinfo[vnode_name]['basic_info']['billing'] nowbillingval += billingval workercinfo[vnode_name]['basic_info']['billing'] = nowbillingval + workercinfo[vnode_name]['basic_info']['billing_history'] = get_billing_history(vnode_name) workercinfo[vnode_name]['basic_info']['billing_history']['cpu'] += billing['cpu'] workercinfo[vnode_name]['basic_info']['billing_history']['mem'] += billing['mem'] workercinfo[vnode_name]['basic_info']['billing_history']['disk'] += billing['disk'] @@ -266,6 +272,12 @@ class Container_Collector(threading.Thread): self.net_stats[key]['errout'] = int(raw_stats[key].errin) self.net_stats[key]['dropin'] = int(raw_stats[key].dropout) self.net_stats[key]['dropout'] = int(raw_stats[key].dropin) + else: + if key not in gateways_stats.keys(): + gateways_stats[key] = {} + gateways_stats[key]['bytes_recv'] = int(raw_stats[key].bytes_sent) + gateways_stats[key]['bytes_sent'] = int(raw_stats[key].bytes_recv) + gateways_stats[key]['bytes_total'] = gateways_stats[key]['bytes_recv'] + gateways_stats[key]['bytes_sent'] #logger.info(self.net_stats) # the main function to collect monitoring data of a container @@ -565,10 +577,11 @@ class Collector(threading.Thread): def workerFetchInfo(master_ip): global workerinfo global workercinfo + global gateways_stats global G_masterip # tell the worker the ip address of the master G_masterip = master_ip - return str([workerinfo, workercinfo]) + return str([workerinfo, workercinfo, gateways_stats]) # get owner name of a container def get_owner(container_name): @@ -649,8 +662,27 @@ class Master_Collector(threading.Thread): self.thread_stop = False self.nodemgr = nodemgr self.master_ip = master_ip + self.net_lastbillings = {} + self.bytes_per_beans = 1000000000 return + def net_billings(self, username, now_bytes_total): + global monitor_vnodes + if not username in self.net_lastbillings.keys(): + self.net_lastbillings[username] = 0 + elif int(now_bytes_total/self.bytes_per_beans) < self.net_lastbillings[username]: + self.net_lastbillings[username] = 0 + diff = int(now_bytes_total/self.bytes_per_beans) - self.net_lastbillings[username] + if diff > 0: + auth_key = env.getenv('AUTH_KEY') + data = {"owner_name":username,"billing":diff, "auth_key":auth_key} + header = {'Content-Type':'application/x-www-form-urlencoded'} + http = Http() + [resp,content] = http.request("http://"+self.master_ip+"/billing/beans/","POST",urlencode(data),headers = header) + logger.info("response from master:"+content.decode('utf-8')) + self.net_lastbillings[username] += diff + monitor_vnodes[username]['net_stats']['net_billings'] = self.net_lastbillings[username] + def run(self): global monitor_hosts global monitor_vnodes @@ -672,6 +704,12 @@ class Master_Collector(threading.Thread): if not owner in monitor_vnodes.keys(): monitor_vnodes[owner] = {} monitor_vnodes[owner][container] = info[1][container] + for user in info[2].keys(): + if not user in monitor_vnodes.keys(): + continue + else: + monitor_vnodes[user]['net_stats'] = info[2][user] + self.net_billings(user, info[2][user]['bytes_total']) except Exception as err: logger.warning(traceback.format_exc()) logger.warning(err) @@ -912,3 +950,14 @@ class History_Manager: tmp = {"name":vnode.name,"billing":vnode.billing} res.append(tmp) return res + + # get users' net_stats + def get_user_net_stats(self,owner): + global monitor_vnodes + try: + res = monitor_vnodes[owner]['net_stats'] + except Exception as err: + logger.warning(traceback.format_exc()) + logger.warning(err) + res = {} + return res diff --git a/web/static/js/plot_monitor.js b/web/static/js/plot_monitor.js index 4405152..971d132 100755 --- a/web/static/js/plot_monitor.js +++ b/web/static/js/plot_monitor.js @@ -1,6 +1,10 @@ var mem_usedp = 0; var cpu_usedp = 0; var is_running = true; +var ingress_rate = 0; +var egress_rate = 0; +var ingress_rate_limit = 0; +var egress_rate_limit = 0; function processMemData(data) { @@ -50,7 +54,20 @@ function getCpuY() return cpu_usedp*100; } -function plot_graph(container,url,processData,getY) { +function processRate(data) +{ +} +function getIngressRateP() +{ + //alert(ingress_rate*8 / 1000.0); + return ingress_rate * 8 / 1000.0; +} +function getEgressRateP() +{ + return egress_rate * 8 / 1000.0; +} + +function plot_graph(container,url,processData,getY,fetchdata=true, maxy=110) { //var container = $("#flot-line-chart-moving"); @@ -88,9 +105,10 @@ function plot_graph(container,url,processData,getY) { } if (data.length < maximum) { - $.post(url,{user:"root",key:"root"},processData,"json"); - var y = getY(); - data.push(y < 0 ? 0 : y > 100 ? 100 : y); + if(fetchdata) + $.post(url,{},processData,"json"); + var y = getY(); + data.push(y < 0 ? 0 : y > maxy ? maxy : y); } // zip the generated y values with the x values @@ -152,7 +170,7 @@ function plot_graph(container,url,processData,getY) { }, yaxis: { min: 0, - max: 110 + max: maxy }, legend: { show: true @@ -227,12 +245,14 @@ function processBasicInfo() var secs = Math.floor(total % 3600 % 60); $("#con_time").html(hour+"h "+min+"m "+secs+"s"); $("#con_billing").html(""+basic_info.billing+" "); - $("#con_billingthishour").html(""+basic_info.billing_this_hour+" "); + $("#con_billingthishour").html(""+basic_info.billing_this_hour.total+" "); },"json"); $.post(url+"/net_stats/",{},function(data){ var net_stats = data.monitor.net_stats; var in_rate = parseInt(net_stats.bytes_recv_per_sec); var out_rate = parseInt(net_stats.bytes_sent_per_sec); + ingress_rate = in_rate; + egress_rate = out_rate; $("#net_in_rate").html(num2human(in_rate)+"Bps"); $("#net_out_rate").html(num2human(out_rate)+"Bps"); $("#net_in_bytes").html(num2human(net_stats.bytes_recv)+"B"); @@ -245,6 +265,20 @@ function processBasicInfo() $("#net_out_drop").html(net_stats.dropin); },"json"); } + +function plot_net(host,monitorurl) +{ + var url = "http://" + host + "/user/selfQuery/"; + + $.post(url,{},function(data){ + ingress_rate_limit = parseInt(data.groupinfo.input_rate_limit); + egress_rate_limit = parseInt(data.groupinfo.output_rate_limit); + plot_graph($("#ingress-chart"), monitorurl, processRate, getIngressRateP,false,ingress_rate_limit); + plot_graph($("#egress-chart"), monitorurl, processRate, getEgressRateP,false,egress_rate_limit*1.5); + },"json"); +} + setInterval(processBasicInfo,1000); plot_graph($("#mem-chart"),url + "/mem_use/",processMemData,getMemY); plot_graph($("#cpu-chart"),url + "/cpu_use/",processCpuData,getCpuY); +plot_net(host, url + "/net_stats/"); diff --git a/web/templates/monitor/status.html b/web/templates/monitor/status.html index 5aedfd7..b4d0693 100644 --- a/web/templates/monitor/status.html +++ b/web/templates/monitor/status.html @@ -73,6 +73,41 @@ {% for master in allcontainers %} +
+
+
+
+

Total Network Statistics @ {{master.split("@")[1]}}

+
+ + +
+
+
+ + + + + + + + + + + + + + + + + + +
Total Bytes SentTotal Bytes ReceivedTotal Bytes TranseferNetwork Billings
--------
+
+
+
+
{% for clustername, clusterinfo in allcontainers[master].items() %}
@@ -243,6 +278,31 @@