summaryrefslogtreecommitdiff
path: root/bin
diff options
authorZygmunt Krynicki <zygmunt.krynicki@canonical.com>2014-06-11 15:56:18 +0000
committerDaniel Manrique <>2014-06-11 15:56:18 +0000
commit5df6c2ab2290ee2677cfc3e9b6bba1f345fd4379 (patch)
tree99ea1978469786522bbd303e45cc6218025140df /bin
parentd57fbb4c78a304c34ba29bd1cd814970a1de9e3e (diff)
parent33878db476bb613a5f5bf5e16526d329bd6c5966 (diff)
"automatic merge by tarmac [r=roadmr][bug=][author=zkrynicki]"
Diffstat (limited to 'bin')
-rwxr-xr-xbin/gateway_ping_test263
1 files changed, 134 insertions, 129 deletions
diff --git a/bin/gateway_ping_test b/bin/gateway_ping_test
index da7ed2d..87af5d3 100755
--- a/bin/gateway_ping_test
+++ b/bin/gateway_ping_test
@@ -1,45 +1,64 @@
#!/usr/bin/python3
+# This file is part of Checkbox.
+#
+# Copyright 2007-2014 Canonical Ltd.
+# Written by:
+# Brendan Donegan <brendan.donegan@canonical.com>
+# Daniel Manrique <daniel.manrique@canonical.com>
+# David Murphy <david.murphy@canonical.com>
+# Javier Collado <javier.collado@canonical.com>
+# Jeff Lane <jeffrey.lane@canonical.com>
+# Marc Tardif <marc.tardif@canonical.com>
+# Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
+# Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
+#
+# Checkbox is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 3,
+# as published by the Free Software Foundation.
+#
+# Checkbox is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.
+from gettext import gettext as _
+import argparse
+import errno
+import gettext
+import logging
import os
import re
-import sys
-
-import logging
import socket
import struct
import subprocess
-import gettext
+import sys
import time
-from gettext import gettext as _
-
-from argparse import ArgumentParser
-
-class Route(object):
- """Gets routing information from the system.
+class Route:
+ """
+ Gets routing information from the system.
"""
-
- # auxiliary functions
- def _hex_to_dec(self, string):
- """Returns the integer value of a hexadecimal string s
- """
- return int(string, 16)
def _num_to_dotted_quad(self, number):
- """Convert long int to dotted quad string
+ """
+ Convert long int to dotted quad string
"""
return socket.inet_ntoa(struct.pack("<L", number))
def _get_default_gateway_from_proc(self):
- """"Returns the current default gateway, reading that from /proc
"""
- logging.debug("Reading default gateway information from /proc")
+ Returns the current default gateway, reading that from /proc
+ """
+ logging.debug(_("Reading default gateway information from /proc"))
try:
- file = open("/proc/net/route")
- route = file.read()
+ with open("/proc/net/route", "rt") as stream:
+ route = stream.read()
except:
- logging.error("Failed to read def gateway from /proc")
+ logging.error(_("Failed to read def gateway from /proc"))
return None
else:
h = re.compile("\n(?P<interface>\w+)\s+00000000\s+"
@@ -47,24 +66,26 @@ class Route(object):
w = h.search(route)
if w:
if w.group("def_gateway"):
- return (self._num_to_dotted_quad(
- self._hex_to_dec(w.group("def_gateway"))))
+ return self._num_to_dotted_quad(
+ int(w.group("def_gateway"), 16))
else:
- logging.error("Could not find def gateway info in /proc")
+ logging.error(
+ _("Could not find def gateway info in /proc"))
return None
else:
- logging.error("Could not find def gateway info in /proc")
+ logging.error(_("Could not find def gateway info in /proc"))
return None
def _get_default_gateway_from_bin_route(self):
- """Get default gateway from /sbin/route -n
+ """
+ Get default gateway from /sbin/route -n
Called by get_default_gateway
and is only used if could not get that from /proc
"""
- logging.debug("Reading default gateway information from route binary")
- routebin = subprocess.getstatusoutput("export LANGUAGE=C; "
- "/usr/bin/env route -n")
-
+ logging.debug(
+ _("Reading default gateway information from route binary"))
+ routebin = subprocess.getstatusoutput(
+ "export LANGUAGE=C; " "/usr/bin/env route -n")
if routebin[0] == 0:
h = re.compile("\n0.0.0.0\s+(?P<def_gateway>[\w.]+)\s+")
w = h.search(routebin[1])
@@ -72,8 +93,7 @@ class Route(object):
def_gateway = w.group("def_gateway")
if def_gateway:
return def_gateway
-
- logging.error("Could not find default gateway by running route")
+ logging.error(_("Could not find default gateway by running route"))
return None
def get_hostname(self):
@@ -83,29 +103,25 @@ class Route(object):
t1 = self._get_default_gateway_from_proc()
if not t1:
t1 = self._get_default_gateway_from_bin_route()
-
return t1
def get_host_to_ping(interface=None, verbose=False, default=None):
- #Get list of all IPs from all my interfaces,
+ # Get list of all IPs from all my interfaces,
interface_list = subprocess.check_output(["ip", "-o", 'addr', 'show'])
-
reg = re.compile('\d: (?P<iface>\w+) +inet (?P<address>[\d\.]+)/'
'(?P<netmask>[\d]+) brd (?P<broadcast>[\d\.]+)')
# Will magically exclude lo because it lacks brd field
interfaces = reg.findall(interface_list.decode())
-
# ping -b the network on each one (one ping only)
# exclude the ones not specified in iface
for iface in interfaces:
if not interface or iface[0] == interface:
- #Use check_output even if I'll discard the output
- #looks cleaner than using .call and redirecting stdout to null
+ # Use check_output even if I'll discard the output
+ # looks cleaner than using .call and redirecting stdout to null
try:
- (subprocess
- .check_output(["ping", "-q", "-c", "1", "-b", iface[3]],
- stderr=subprocess.STDOUT))
+ subprocess.check_output(["ping", "-q", "-c", "1", "-b",
+ iface[3]], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError:
pass
# If default host given, ping it as well,
@@ -117,165 +133,154 @@ def get_host_to_ping(interface=None, verbose=False, default=None):
stderr=subprocess.STDOUT)
except subprocess.CalledProcessError:
pass
-
ARP_POPULATE_TRIES = 10
num_tries = 0
-
while num_tries < ARP_POPULATE_TRIES:
- #Get output from arp -a -n to get known IPs
+ # Get output from arp -a -n to get known IPs
known_ips = subprocess.check_output(["arp", "-a", "-n"])
reg = re.compile('\? \((?P<ip>[\d.]+)\) at (?P<mac>[a-f0-9\:]+) '
'\[ether\] on (?P<iface>[\w\d]+)')
-
- #Filter (if needed) IPs not on the specified interface
+ # Filter (if needed) IPs not on the specified interface
pingable_ips = [pingable[0] for pingable in reg.findall(
known_ips.decode()) if not interface
or pingable[2] == interface]
-
# If the default given ip is among the remaining ones,
# ping that.
if default and default in pingable_ips:
if verbose:
- print("Desired ip address %s is reachable, using it" % default)
+ print(_(
+ "Desired ip address {0} is reachable, using it"
+ ).format(default))
return default
-
- #If not, choose another IP.
+ # If not, choose another IP.
address_to_ping = pingable_ips[0] if len(pingable_ips) else None
if verbose:
- print("Desired ip address %s is not reachable from %s. "
- % (default, interface))
- print("using %s instead." % address_to_ping)
-
+ print(_(
+ "Desired ip address {0} is not reachable from {1},"
+ " using {2} instead"
+ ).format(default, interface, address_to_ping))
if address_to_ping:
return address_to_ping
-
time.sleep(2)
num_tries += 1
-
# Wait time expired
return None
def ping(host, interface, count, deadline, verbose=False):
-
command = ["ping", str(host), "-c", str(count), "-w", str(deadline)]
if interface:
command.append("-I{}".format(interface))
-
- reg = re.compile(r"(\d+) packets transmitted, (\d+) received, (\d+)% packet loss")
+ reg = re.compile(
+ r"(\d+) packets transmitted, (\d+) received, (\d+)% packet loss")
ping_summary = {'transmitted': 0, 'received': 0, 'pct_loss': 0}
-
try:
output = subprocess.check_output(command, universal_newlines=True)
- except FileNotFoundError as excp:
- # No ping command present; default exception message is
- # informative enough.
- print(excp)
+ except OSError as exc:
+ if exc.errno == errno.ENOENT:
+ # No ping command present;
+ # default exception message is informative enough.
+ print(exc)
+ else:
+ raise
except subprocess.CalledProcessError as excp:
# Ping returned fail exit code
- print("ERROR: ping result: {}".format(excp))
+ print(_("ERROR: ping result: {0}").format(excp))
else:
if verbose:
print(output)
-
received = re.findall(reg, output)
if received:
ping_summary = received[0]
-
- ping_summary={'transmitted': int(ping_summary[0]),
- 'received': int(ping_summary[1]),
- 'pct_loss': int(ping_summary[2])}
+ ping_summary = {
+ 'transmitted': int(ping_summary[0]),
+ 'received': int(ping_summary[1]),
+ 'pct_loss': int(ping_summary[2])}
return ping_summary
def main(args):
-
- gettext.textdomain("checkbox")
-
+ gettext.textdomain("2013.com.canonical.certification.checkbox")
+ gettext.bindtextdomain("2013.com.canonical.certification.checkbox",
+ os.getenv("CHECKBOX_PROVIDER_LOCALE_DIR", None))
default_count = 2
default_delay = 4
-
route = Route()
-
- parser = ArgumentParser()
- parser.add_argument("host",
- nargs='?',
- default=route.get_default_gateway(),
- help="Host to ping")
- parser.add_argument("-c", "--count",
- default=default_count,
- type=int,
- help="Number of packets to send.")
- parser.add_argument("-d", "--deadline",
- default=default_delay,
- type=int,
- help="Timeouts in seconds.")
- parser.add_argument("-t", "--threshold",
- default=0,
- type=int,
- help="Percentage of allowed packet loss before "
- "considering test failed. Defaults to 0 "
- "(meaning any packet loss will fail the test)")
- parser.add_argument("-v", "--verbose",
- action='store_true',
- help="Be verbose.")
- parser.add_argument("-I", "--interface",
- help="Interface to ping from.")
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ "host", nargs='?', default=route.get_default_gateway(),
+ help=_("host to ping"))
+ parser.add_argument(
+ "-c", "--count", default=default_count, type=int,
+ help=_("number of packets to send"))
+ parser.add_argument(
+ "-d", "--deadline", default=default_delay, type=int,
+ help=_("timeout in seconds"))
+ parser.add_argument(
+ "-t", "--threshold", default=0, type=int,
+ help=_("allowed packet loss percentage (default: %(default)s)"))
+ parser.add_argument(
+ "-v", "--verbose", action='store_true', help=_("be verbose"))
+ parser.add_argument(
+ "-I", "--interface", help=_("use specified interface to send packets"))
args = parser.parse_args()
-
- #Ensure count and deadline make sense. Adjust them if not.
-
+ # Ensure count and deadline make sense. Adjust them if not.
if args.deadline != default_delay and args.count != default_count:
- #Ensure they're both consistent, and exit with a warning if
- #not, rather than modifying what the user explicitly set.
+ # Ensure they're both consistent, and exit with a warning if not,
+ # rather than modifying what the user explicitly set.
if args.deadline <= args.count:
- print("ERROR: not enough time for %s pings in %s seconds" %
- (args.count, args.deadline))
- return(1)
+ # FIXME: this cannot ever be translated correctly
+ print(_(
+ "ERROR: not enough time for {0} pings in {1} seconds"
+ ).format(args.count, args.deadline))
+ return 1
elif args.deadline != default_delay:
- #Adjust count according to delay.
+ # Adjust count according to delay.
args.count = args.deadline - 1
if args.count < 1:
args.count = 1
if args.verbose:
- print("Adjusting ping count to %s to fit in %s-second deadline" %
- (args.count, args.deadline))
+ # FIXME: this cannot ever be translated correctly
+ print(_(
+ "Adjusting ping count to {0} to fit in {1}-second deadline"
+ ).format(args.count, args.deadline))
else:
- #Adjust delay according to count
+ # Adjust delay according to count
args.deadline = args.count + 1
if args.verbose:
- print("Adjusting deadline to %s seconds to fit %s pings" %
- (args.deadline, args.count))
-
- #If given host is not pingable, override with something pingable.
- host = get_host_to_ping(interface=args.interface,
- verbose=args.verbose, default=args.host)
-
+ # FIXME: this cannot ever be translated correctly
+ print(_(
+ "Adjusting deadline to {0} seconds to fit {1} pings"
+ ).format(args.deadline, args.count))
+ # If given host is not pingable, override with something pingable.
+ host = get_host_to_ping(
+ interface=args.interface, verbose=args.verbose, default=args.host)
if args.verbose:
- print("Checking connectivity to %s" % host)
+ print(_("Checking connectivity to {0}").format(host))
ping_summary = None
if host:
ping_summary = ping(host, args.interface, args.count,
args.deadline, args.verbose)
-
- if ping_summary == None or ping_summary['received'] == 0:
+ if ping_summary is None or ping_summary['received'] == 0:
print(_("No Internet connection"))
return 1
elif ping_summary['transmitted'] != ping_summary['received']:
- print(_("Connection established, but lost {}% of packets".format(
- ping_summary['pct_loss'])))
+ print(_("Connection established, but lost {0}% of packets").format(
+ ping_summary['pct_loss']))
if ping_summary['pct_loss'] > args.threshold:
- print(_("FAIL: {}% packet loss is higher"
- "than {}% threshold").format(ping_summary['pct_loss'],
- args.threshold))
+ print(_(
+ "FAIL: {0}% packet loss is higher than {1}% threshold"
+ ).format(ping_summary['pct_loss'], args.threshold))
return 1
else:
- print(_("PASS: {}% packet loss is within {}% threshold").format(
- ping_summary['pct_loss'], args.threshold))
+ print(_(
+ "PASS: {0}% packet loss is within {1}% threshold"
+ ).format(ping_summary['pct_loss'], args.threshold))
return 0
else:
print(_("Internet connection fully established"))
return 0
+
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))