-
Notifications
You must be signed in to change notification settings - Fork 684
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Portstat]: Add -p option to support portstat timer #16
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ import os.path | |
import re | ||
import subprocess | ||
import sys | ||
import time | ||
|
||
from collections import namedtuple, OrderedDict | ||
from tabulate import tabulate | ||
|
@@ -204,6 +205,76 @@ def parse_bcmcmd_ps(bcmcmd_output): | |
bcmcmd_lines = bcmcmd_output.split("\n") | ||
|
||
|
||
def get_cnstat(cnstat_dir): | ||
""" | ||
Get the cnstat from netstat. | ||
""" | ||
try: | ||
bcmcmd_output = subprocess.Popen(([BCMCMD_PATH, | ||
'show counters changed same nz']), | ||
stdout=subprocess.PIPE, | ||
shell=False).communicate()[0] | ||
except EnvironmentError as e: | ||
print e, e.errno | ||
sys.exit(e.errno) | ||
|
||
bcm_dict = parse_bcmcmd_output(bcmcmd_output) | ||
|
||
try: | ||
netstat_out = subprocess.Popen(([NETSTAT_PATH, '-i']), | ||
stdout=subprocess.PIPE, | ||
shell=False).communicate()[0] | ||
except EnvironmentError as e: | ||
print e, e.errno | ||
sys.exit(e.errno) | ||
|
||
netstat_lines = netstat_out.split("\n") | ||
|
||
# Since netstat -i returns some stats as 32-bits, get full 64-bit | ||
# stats from /prov/net/dev and display only the 64-bit stats. | ||
try: | ||
proc_out = subprocess.Popen(([CAT_PATH, '/proc/net/dev']), | ||
stdout=subprocess.PIPE, | ||
shell=False).communicate()[0] | ||
except EnvironmentError as e: | ||
print e, e.errno | ||
sys.exit(e.errno) | ||
|
||
proc = {} | ||
for line in proc_out.split("\n"): | ||
parsed = re.findall("\s*([^ ]+):(.*)", line) | ||
if not parsed: | ||
continue | ||
iface, stats = parsed[0] | ||
proc[iface] = stats.split() | ||
|
||
# At this point, either we'll create a file or open an existing one. | ||
if not os.path.exists(cnstat_dir): | ||
try: | ||
os.makedirs(cnstat_dir) | ||
except IOError as e: | ||
print e.errno, e | ||
sys.exit(1) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. here you only create a folder, but you do not use it anyway in the function. what's the purpose here? should we move it to some where else? |
||
|
||
# Build a dictionary of the stats | ||
cnstat_dict = OrderedDict() | ||
|
||
cnstat_dict['time'] = datetime.datetime.now() | ||
|
||
# We skip the first 2 lines since they contain no interface information | ||
for i in range(2, len(netstat_lines) - 1): | ||
netstats = netstat_lines[i].split() | ||
if ":" in netstats[0]: | ||
continue # Skip aliased interfaces | ||
if ("eth" in netstats[0] or "lo" in netstats[0] or "docker" in netstats[0] or | ||
"Vlan" in netstats[0] or "PortChannel" in netstats[0]): | ||
continue # Skip these types of interfaces | ||
else: | ||
cnstat_dict.update(cnstat_create_bcm_element(i, netstats, bcm_dict[netstats[0]])) | ||
|
||
|
||
return cnstat_dict | ||
|
||
def cnstat_diff_print(cnstat_new_dict, cnstat_old_dict, use_json): | ||
table = [] | ||
|
||
|
@@ -261,13 +332,15 @@ Examples: | |
portstat -d -t test | ||
portstat | ||
portstat -r | ||
portstat -p 20 | ||
""") | ||
parser.add_argument('-c', '--clear', action='store_true', help='Copy & clear stats') | ||
parser.add_argument('-d', '--delete', action='store_true', help='Delete saved stats, either the uid or the specified tag') | ||
parser.add_argument('-D', '--delete-all', action='store_true', help='Delete all saved stats') | ||
parser.add_argument('-j', '--json', action='store_true', help='Display in JSON format') | ||
parser.add_argument('-r', '--raw', action='store_true', help='Raw stats (unmodified output of netstat)') | ||
parser.add_argument('-t', '--tag', type=str, help='Save stats with name TAG', default=None) | ||
parser.add_argument('-p', '--period', type=int, help='Get the portstat within Period seconds', default=0) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make the help message clearer. Something like, "Display stats over a specified period (in seconds)." |
||
args = parser.parse_args() | ||
|
||
save_fresh_stats = args.clear | ||
|
@@ -277,6 +350,7 @@ Examples: | |
raw_stats = args.raw | ||
tag_name = args.tag | ||
uid = str(os.getuid()) | ||
wait_time_in_seconds = args.period | ||
|
||
if not os.geteuid() == 0: | ||
raise RuntimeError("must be root to run") | ||
|
@@ -311,69 +385,8 @@ Examples: | |
if os.listdir(cnstat_dir) == []: | ||
os.rmdir(cnstat_dir) | ||
sys.exit(0) | ||
|
||
try: | ||
bcmcmd_output = subprocess.Popen(([BCMCMD_PATH, | ||
'show counters changed same nz']), | ||
stdout=subprocess.PIPE, | ||
shell=False).communicate()[0] | ||
except EnvironmentError as e: | ||
print e, e.errno | ||
sys.exit(e.errno) | ||
|
||
bcm_dict = parse_bcmcmd_output(bcmcmd_output) | ||
|
||
try: | ||
netstat_out = subprocess.Popen(([NETSTAT_PATH, '-i']), | ||
stdout=subprocess.PIPE, | ||
shell=False).communicate()[0] | ||
except EnvironmentError as e: | ||
print e, e.errno | ||
sys.exit(e.errno) | ||
|
||
netstat_lines = netstat_out.split("\n") | ||
|
||
# Since netstat -i returns some stats as 32-bits, get full 64-bit | ||
# stats from /prov/net/dev and display only the 64-bit stats. | ||
try: | ||
proc_out = subprocess.Popen(([CAT_PATH, '/proc/net/dev']), | ||
stdout=subprocess.PIPE, | ||
shell=False).communicate()[0] | ||
except EnvironmentError as e: | ||
print e, e.errno | ||
sys.exit(e.errno) | ||
|
||
proc = {} | ||
for line in proc_out.split("\n"): | ||
parsed = re.findall("\s*([^ ]+):(.*)", line) | ||
if not parsed: | ||
continue | ||
iface, stats = parsed[0] | ||
proc[iface] = stats.split() | ||
|
||
# At this point, either we'll create a file or open an existing one. | ||
if not os.path.exists(cnstat_dir): | ||
try: | ||
os.makedirs(cnstat_dir) | ||
except IOError as e: | ||
print e.errno, e | ||
sys.exit(1) | ||
|
||
# Build a dictionary of the stats | ||
cnstat_dict = OrderedDict() | ||
|
||
cnstat_dict['time'] = datetime.datetime.now() | ||
|
||
# We skip the first 2 lines since they contain no interface information | ||
for i in range(2, len(netstat_lines) - 1): | ||
netstats = netstat_lines[i].split() | ||
if ":" in netstats[0]: | ||
continue # Skip aliased interfaces | ||
if ("eth" in netstats[0] or "lo" in netstats[0] or "docker" in netstats[0] or | ||
"Vlan" in netstats[0] or "PortChannel" in netstats[0]): | ||
continue # Skip these types of interfaces | ||
else: | ||
cnstat_dict.update(cnstat_create_bcm_element(i, netstats, bcm_dict[netstats[0]])) | ||
|
||
cnstat_dict = get_cnstat(cnstat_dir) | ||
|
||
# Now decide what information to display | ||
if raw_stats: | ||
|
@@ -388,20 +401,25 @@ Examples: | |
else: | ||
print "Cleared counters" | ||
sys.exit(0) | ||
|
||
cnstat_cached_dict = OrderedDict() | ||
|
||
if os.path.isfile(cnstat_fqn_file): | ||
try: | ||
cnstat_cached_dict = pickle.load(open(cnstat_fqn_file, 'r')) | ||
print "Last cached time was " + str(cnstat_cached_dict.get('time')) | ||
cnstat_diff_print(cnstat_dict, cnstat_cached_dict, use_json) | ||
except IOError as e: | ||
print e.errno, e | ||
else: | ||
if tag_name: | ||
print "\nFile '%s' does not exist" % cnstat_fqn_file | ||
print "Did you run 'portstat -c -t %s' to record the counters via tag %s?\n" % (tag_name, tag_name) | ||
|
||
if wait_time_in_seconds == 0: | ||
cnstat_cached_dict = OrderedDict() | ||
if os.path.isfile(cnstat_fqn_file): | ||
try: | ||
cnstat_cached_dict = pickle.load(open(cnstat_fqn_file, 'r')) | ||
print "Last cached time was " + str(cnstat_cached_dict.get('time')) | ||
cnstat_diff_print(cnstat_dict, cnstat_cached_dict, use_json) | ||
except IOError as e: | ||
print e.errno, e | ||
else: | ||
cnstat_print(cnstat_dict, use_json) | ||
if tag_name: | ||
print "\nFile '%s' does not exist" % cnstat_fqn_file | ||
print "Did you run 'portstat -c -t %s' to record the counters via tag %s?\n" % (tag_name, tag_name) | ||
else: | ||
cnstat_print(cnstat_dict, use_json) | ||
else: | ||
#wait for sometime and output the result | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "# Wait for the specified duration then gather new stats and output the difference" |
||
time.sleep(wait_time_in_seconds) | ||
cnstat_new_dict = get_cnstat(cnstat_dir) | ||
cnstat_diff_print(cnstat_new_dict, cnstat_dict, use_json) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it does not look the cnstat_dir is really used in this function, can you remove this argument?