Merge bootstack-ops:mtu-scripts into bootstack-ops:master

Proposed by James Hebden
Status: Merged
Merged at revision: 4f48eca242b1981ab352f04c4a36b545878a6d3a
Proposed branch: bootstack-ops:mtu-scripts
Merge into: bootstack-ops:master
Diff against target: 183 lines (+171/-0)
2 files modified
ops-bundle/scripts/check-mtus.py (+94/-0)
ops-bundle/scripts/fix-mtus.py (+77/-0)
Reviewer Review Type Date Requested Status
Peter Sabaini (community) Approve
Review via email: mp+320014@code.launchpad.net

Description of the change

Add scripts for fixing/changing and verifying MTU on BootStack clouds

To post a comment you must log in.
Revision history for this message
Peter Sabaini (peter-sabaini) wrote :

Thanks, see some inline comments

Revision history for this message
James Hebden (ec0) wrote :

Thanks for checking this out Peter - I've added capture of return code and stdout and stderr for failed pings, and print a summary at the end of the check-mtus script, for better feedback when diagnosing MTU issues.

I stuck with standard ping though, as I'd like to avoid needing to install fping to run this script. I also found some inconsistencies in it's output when pinging hosts with incorrect MTUs that made it a lot harder to get good status information out of it. It was dumping a failure for every host, whilst simultaneously dumping success messages to stdout for the OK hosts.

Revision history for this message
Peter Sabaini (peter-sabaini) wrote :

Ack, thanks. I'm still a fping fan but if it works with ping I'm all +1 :-)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/ops-bundle/scripts/check-mtus.py b/ops-bundle/scripts/check-mtus.py
2new file mode 100755
3index 0000000..9c4710f
4--- /dev/null
5+++ b/ops-bundle/scripts/check-mtus.py
6@@ -0,0 +1,94 @@
7+#!/usr/bin/python
8+import sys
9+import yaml
10+import subprocess
11+
12+mtu = sys.argv[1] if len(sys.argv) > 1 else 8900
13+print("Checking hosts reachable at MTU of %s" % mtu)
14+
15+global ping_errors, statistics
16+
17+ping_size = int(mtu) - 28
18+statistics = {'hosts': 0,
19+ 'containers': 0,
20+ 'ok': 0.0,
21+ 'error': 0.0,
22+ 'total': 0.0}
23+ping_errors = []
24+
25+juju_status = yaml.load(subprocess.check_output(['juju', 'status', '--format=yaml']))
26+
27+
28+def summary():
29+
30+ global statistics, ping_errors
31+
32+ print('Test Summary:')
33+ print(" Number of metals: %s" % statistics['hosts'])
34+ print(" Number of containers: %s" % statistics['containers'])
35+ print(' Ping success: %d%% (\033[92m%d\033[0m,\033[91m%d\033[0m)' %
36+ ((statistics['ok'] / statistics['total']) * 100,
37+ statistics['ok'], statistics['error']))
38+
39+ for ping_error in ping_errors:
40+ print('')
41+ print('\033[91mPing failure:\033[0m %s (%s) rc %d' % (ping_error['host'],
42+ ping_error['ip'],
43+ ping_error['rc']))
44+ print(ping_error['stderr'])
45+ print(ping_error['stdout'])
46+
47+
48+def green_pass():
49+ print('\033[92m' + "OK" + '\033[0m')
50+
51+
52+def red_fail():
53+ print('\033[91m' + "FAIL" + '\033[0m')
54+
55+
56+def ping(ip):
57+ ping_command = 'ping'
58+ if ':' in ip:
59+ ping_command = 'ping6'
60+ ping_proc = subprocess.Popen([ping_command, "-c", "1", "-W", "1", "-s", str(ping_size), ip],
61+ stdout=subprocess.PIPE, stderr=subprocess.PIPE,
62+ close_fds=True)
63+ out, err = ping_proc.communicate()
64+ return [ping_proc.returncode, out, err]
65+
66+
67+def ping_result(host, ip):
68+
69+ global statistics, ping_errors
70+
71+ print("Checking %s (%s)" % (host, ip)),
72+ ping_res = ping(ip)
73+ statistics['total'] += 1
74+
75+ if ping_res[0] == 0:
76+ statistics['ok'] += 1
77+ green_pass()
78+ else:
79+ statistics['error'] += 1
80+ ping_errors.append({'host': host, 'ip': ip,
81+ 'rc': ping_res[0],
82+ 'stdout': ping_res[1],
83+ 'stderr': ping_res[2]})
84+ red_fail()
85+
86+
87+for key, machine in juju_status['machines'].iteritems():
88+
89+ host = machine['instance-id']
90+ statistics['hosts'] += 1
91+ for ip in machine['ip-addresses']:
92+ ping_result(host, ip)
93+ if 'containers' in machine:
94+ for key, container in machine['containers'].iteritems():
95+ host = container['instance-id']
96+ statistics['containers'] += 1
97+ for ip in container['ip-addresses']:
98+ ping_result(host, ip)
99+
100+summary()
101diff --git a/ops-bundle/scripts/fix-mtus.py b/ops-bundle/scripts/fix-mtus.py
102new file mode 100755
103index 0000000..693eca2
104--- /dev/null
105+++ b/ops-bundle/scripts/fix-mtus.py
106@@ -0,0 +1,77 @@
107+#!/usr/bin/python
108+import sys
109+import yaml
110+import subprocess
111+import base64
112+
113+mtu = int(sys.argv[1]) if len(sys.argv) > 1 else 8900
114+print("Setting MTU of %s" % mtu)
115+
116+ping_size = mtu - 28
117+
118+udev_rules = """
119+SUBSYSTEM=="net", ACTION=="add", KERNEL=="veth*", ATTR{mtu}=="1500", ATTR{mtu}="%d"
120+SUBSYSTEM=="net", ACTION=="add", KERNEL=="br-*", ATTR{mtu}=="1500", ATTR{mtu}="%d"
121+SUBSYSTEM=="net", ACTION=="add", KERNEL=="gre_system", ATTR{mtu}=="1462", ATTR{mtu}="%d"
122+SUBSYSTEM=="net", ACTION=="add", KERNEL=="gre_sys", ATTR{mtu}=="1462", ATTR{mtu}="%d"
123+""" % (mtu, mtu, mtu - 38, mtu - 38)
124+
125+rules_file = '/etc/udev/rules.d/90-bootstack-mtu.rules'
126+
127+script = """shopt -s nullglob
128+ cd /sys/class/net
129+ for i in eth? bond? br? en* veth*;do
130+ ifconfig $i mtu '%d'
131+ done
132+ cp -f /etc/network/interfaces /etc/network/interfaces.mtu-bak
133+ sed -i\"\" -e\"s/mtu\s*[0-9]*/mtu %d/g\" /etc/network/interfaces
134+ echo '%s' |base64 -d > '%s' && udevadm control --reload
135+""" % (mtu, mtu, base64.b64encode(udev_rules), rules_file)
136+
137+juju_status = yaml.load(subprocess.check_output(['juju', 'status', '--format=yaml']))
138+
139+
140+def green_pass():
141+ print('\033[92m' + "OK" + '\033[0m')
142+
143+
144+def red_fail():
145+ print('\033[91m' + "FAIL" + '\033[0m')
146+
147+
148+def ping(ip):
149+ ping_command = 'ping'
150+ if ':' in ip:
151+ ping_command = 'ping6'
152+ return subprocess.call([ping_command, "-c", "1", "-W", "1", "-s", str(ping_size),
153+ ip], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
154+ close_fds=True) == 0
155+
156+
157+def ping_result(host, ip):
158+ print("Pinging %s (%s) with size %s: " % (host, ip, ping_size)),
159+ if ping(ip):
160+ green_pass()
161+ else:
162+ red_fail()
163+
164+
165+def adjust_interfaces(host):
166+ print("Setting MTUs on host: %s " % host),
167+ if subprocess.call(['juju', 'ssh', host, 'sudo', 'bash', '-c', """'%s'""" % script]) == 0:
168+ green_pass()
169+ else:
170+ red_fail()
171+
172+
173+for key, machine in juju_status['machines'].iteritems():
174+ host = key
175+ adjust_interfaces(host)
176+ for ip in machine['ip-addresses']:
177+ ping_result(host, ip)
178+ if 'containers' in machine:
179+ for key, container in machine['containers'].iteritems():
180+ host = key
181+ adjust_interfaces(host)
182+ for ip in container['ip-addresses']:
183+ ping_result(host, ip)

Subscribers

People subscribed via source and target branches

to all changes: