Begin upgrading `sample` script.

This will ultimately let it run a remote sample script to collect data
on TV Boxes and a controlling laptop at the same time. But there's some
prep work to do before we get there.

Change-Id: I792bd5bd6987725276316b3b033e285d6f017d3e
diff --git a/wifitables/sample.py b/wifitables/sample.py
index 53a3c62..6ff88cf 100755
--- a/wifitables/sample.py
+++ b/wifitables/sample.py
@@ -25,19 +25,27 @@
 m,monitor=      wireless monitor interface to use [{1}]
 """
 
+DEVNULL = open(os.devnull, 'wb')
 
-def Iperf(host, udp=False, bandwidth=20, bind=None):
+
+def Ping(host):
+  code = subprocess.call(['ping', '-c', '1', host], stdout=DEVNULL,
+                         stderr=DEVNULL)
+  return code
+
+
+def Iperf(host, path, udp=False, bandwidth=20, bind=None):
   """Run iperf against host and report results."""
   line = ['iperf', '-c', host]
-  prefix = 'iperf'
+  name = 'iperf'
 
   if udp:
     line += ['-u', '-b', str(bandwidth * 1000000)]
-    prefix += 'u'
+    name += 'u'
   if bind:
     line += ['-B', bind]
 
-  out = tempfile.NamedTemporaryFile(prefix=prefix)
+  out = open(os.path.join(path, name), 'w+')
   subprocess.check_call(line, stdout=out)
   return out
 
@@ -68,13 +76,13 @@
       print >> out
 
 
-def MCS(bssid, interface):
+def MCS(bssid, interface, path):
   """Runs tcpdump in the background to gather wireless MCS."""
   print 'Please enter password for `sudo` if prompted.'
   subprocess.call(['sudo', '-v'])
 
-  out = tempfile.NamedTemporaryFile(prefix='mcs')
-  err = tempfile.NamedTemporaryFile(prefix='mcserr')
+  out = open(os.path.join(path, 'mcs'), 'w+')
+  err = open(os.path.join(path, 'mcserr'), 'w+')
 
   filt = ('(not subtype beacon and not subtype ack) and '
           '(wlan addr1 {0} or wlan addr2 {0} or wlan addr3 {0})'.format(
@@ -89,14 +97,14 @@
   return sudo_tcpdump, out, err
 
 
-def IwLink(devname):
-  out = tempfile.NamedTemporaryFile(prefix='iwlink')
+def IwLink(devname, path):
+  out = open(os.path.join(path, 'iwlink'), 'w+')
   subprocess.check_call(['iw', 'dev', devname, 'link'], stdout=out)
   return out
 
 
-def IwScan(devname):
-  out = tempfile.NamedTemporaryFile(prefix='iwlink')
+def IwScan(devname, path):
+  out = open(os.path.join(path, 'iwscan'), 'w+')
   subprocess.check_call(['iw', 'dev', devname, 'scan', 'dump'], stdout=out)
   if os.fstat(out.file.fileno()).st_size: return out
 
@@ -104,22 +112,22 @@
   return out
 
 
-def IpAddr():
-  out = tempfile.NamedTemporaryFile(prefix='ipaddr')
+def IpAddr(path):
+  out = open(os.path.join(path, 'ipaddr'), 'w+')
   subprocess.check_call(['ip', '-o', '-f', 'inet', 'addr'], stdout=out)
   return out
 
 
-def AirportI():
+def AirportI(path):
   """Gather information about the current wireless network from `airport`."""
-  out = tempfile.NamedTemporaryFile(prefix='airport')
+  out = open(os.path.join(path, 'airport'), 'w+')
   subprocess.check_call(['airport', '-I'], stdout=out)
   return out
 
 
-def AirportScan():
+def AirportScan(path):
   """Gather information about other observable networks from `airport`."""
-  out = tempfile.NamedTemporaryFile(prefix='airportscan')
+  out = open(os.path.join(path, 'airportscan'), 'w+')
   subprocess.check_call(['airport', '-s'], stdout=out)
   return out
 
@@ -144,20 +152,25 @@
   if extra:
     o.fatal('did not understand supplied extra arguments.')
 
+  # Pick the report name before we run it, so it can be consistent across
+  # multiple systems.
+  report_name = 'wifi-{}-{:04}'.format(time.time(), opt.steps)
+  report_dir = tempfile.mkdtemp(prefix='wifi')
+
   # we run diagnostics, write their output to files, and gather the files into
   # a report that we present at the end of the run.
   outputs = []
   addr = ''
 
   if system == 'Darwin':
-    ai = AirportI()
+    ai = AirportI(report_dir)
     ai.seek(0)
     bssid = report.ParseAirportI(ai.read())['BSSID']
-    outputs += [ai, AirportScan()]
+    outputs += [ai, AirportScan(report_dir)]
   elif system == 'Linux':
     # It's really likely we're running on a device with more than one interface.
     # Be sure we're using the one that we're trying to test.
-    ip = IpAddr()
+    ip = IpAddr(report_dir)
     ip.seek(0)
     addrmap = report.ParseIpAddr(ip.read())
     addr = addrmap.get(opt.interface)
@@ -171,48 +184,51 @@
     if mask > -1:
       addr = addr[:mask]
 
-    il = IwLink(opt.interface)
+    il = IwLink(opt.interface, report_dir)
     il.seek(0)
     bssid = report.ParseIwLink(il.read())['BSSID']
 
-    ic = IwScan(opt.interface)
+    ic = IwScan(opt.interface, report_dir)
     outputs += [ip, il, ic]
   else:
     raise OSError('This script requires Mac OS X or Linux.')
 
   if opt.monitor:
-    sudo_tcpdump, mcs_out, mcs_err = MCS(bssid, opt.monitor)
+    sudo_tcpdump, mcs_out, mcs_err = MCS(bssid, opt.monitor, report_dir)
     print 'Gathering tcpdump in background as', sudo_tcpdump.pid
     outputs += [mcs_out, mcs_err]
 
-  it = Iperf(opt.destination, bind=addr)
+  status = Ping(opt.destination)
+  if not status:
+    it = Iperf(opt.destination, report_dir, bind=addr)
 
-  # Empirically about 1.25x more packets make it through in UDP than TCP.
-  # Try to saturate the channel by sending a bit more than that over UDP.
-  it.seek(0)
-  it_iperf = report.ParseIperfTCP(it.read())
+    # Empirically about 1.25x more packets make it through in UDP than TCP.
+    # Try to saturate the channel by sending a bit more than that over UDP.
+    it.seek(0)
+    it_iperf = report.ParseIperfTCP(it.read())
 
-  bandwidth = it_iperf.get('bandwidth', 0.01)
-  outputs += [it, Iperf(opt.destination, udp=True, bandwidth=bandwidth * 1.5,
-                        bind=addr)]
+    bandwidth = it_iperf.get('bandwidth', 0.01)
+    outputs += [it, Iperf(opt.destination, report_dir, udp=True,
+                          bandwidth=bandwidth * 1.5,
+                          bind=addr)]
+  else:
+    print >> sys.stderr, ('Could not ping destination host {0}; '
+                          'skipping performance tests').format(opt.destination)
 
   if opt.monitor:
     subprocess.check_call(['sudo', 'kill', str(sudo_tcpdump.pid)])
 
-  report_name = 'wifi-{}-{:04}'.format(time.time(), opt.steps)
   if opt.journal:
     with open(opt.journal, 'a') as journal:
       print >> journal, report_name
-    report_dir = os.path.join(os.path.dirname(opt.journal), report_name)
+    dest_dir = os.path.join(os.path.dirname(opt.journal), report_name)
   else:
-    report_dir = report_name
+    dest_dir = report_name
 
-  os.mkdir(report_dir)
-  for page in outputs:
-    shutil.copy(page.name,
-                os.path.join(report_dir, os.path.basename(page.name[:-6])))
-
-  print 'Report written to', report_dir
+  shutil.move(report_dir, dest_dir)
+  print 'Report written to', dest_dir
+  for name in (o.name for o in outputs):
+    print '*', os.path.basename(name)
 
 
 if __name__ == '__main__':