Browse code

add ping utility

Joseph Weston authored on 09/09/2017 22:22:46
Showing 1 changed files
... ...
@@ -23,6 +23,7 @@ import functools as ft
23 23
 import asyncio
24 24
 from asyncio.subprocess import PIPE, DEVNULL
25 25
 from asyncio import create_subprocess_exec as subprocess
26
+from subprocess import SubprocessError
26 27
 from collections import OrderedDict
27 28
 from pathlib import Path
28 29
 
... ...
@@ -304,3 +305,37 @@ async def lock_subprocess(*args, lockfile, **kwargs):
304 305
         when_dead.add_done_callback(unlock)
305 306
 
306 307
     return proc
308
+
309
+
310
+async def ping(host, timeout):
311
+    """Return the round-trip time to a host using ICMP ECHO.
312
+
313
+    Parameters
314
+    ----------
315
+    host : str
316
+        The host to ping. May be a hostname, ip address, or anything else
317
+        recognized by 'ping'.
318
+    timeout : int
319
+        Time in seconds after which to stop waiting for a response.
320
+
321
+    Returns
322
+    -------
323
+    rtt : float
324
+        The average round trip time in milliseconds.
325
+
326
+    Raises
327
+    ------
328
+    SubprocessError if 'ping' returns a non-zero exit code.
329
+    """
330
+    cmd = f"/bin/ping -w{int(timeout)} {host}"
331
+    proc = await asyncio.create_subprocess_exec(*cmd.split(),
332
+                                                stdout=PIPE, stderr=DEVNULL)
333
+    stdout, _ = await proc.communicate()
334
+    if proc.returncode != 0:
335
+        raise SubprocessError(proc.returncode)
336
+
337
+    *_, rtt_line, _ = stdout.decode().split('\n')
338
+    assert _ == ''  # sanity check
339
+    *_, data, _ = rtt_line.split()
340
+    _, avg, *_ = data.split('/')
341
+    return float(avg)