commit 6f8ee232576dc3a983dcafcdd42a71c0c1cfc0c2
Author: Arturo Filastò <art(a)fuffa.org>
Date: Wed Apr 24 21:14:59 2013 +0200
Implement starting and stopping of tests via the HTTP API
---
ooni/api/spec.py | 66 +++++++++++++++++++++++++++++++++++++++++---
ooni/director.py | 7 ++---
ooni/nettest.py | 5 ++--
ooni/oonicli.py | 4 ++-
ooni/settings.py | 6 ++++
ooni/tests/test_nettest.py | 2 +-
6 files changed, 78 insertions(+), 12 deletions(-)
diff --git a/ooni/api/spec.py b/ooni/api/spec.py
index 5b538b2..ec4cf4b 100644
--- a/ooni/api/spec.py
+++ b/ooni/api/spec.py
@@ -1,10 +1,15 @@
import os
import re
+import copy
import json
import types
+from twisted.python import usage
from cyclone import web, escape
+from ooni.reporter import YAMLReporter, OONIBReporter
+from ooni import errors
+from ooni.nettest import NetTestLoader, MissingRequiredOption
from ooni.settings import config
class InvalidInputFilename(Exception):
@@ -39,6 +44,7 @@ def list_inputs():
class Inputs(ORequestHandler):
def get(self):
+ input_list = list_inputs()
self.write(input_list)
def post(self):
@@ -59,23 +65,75 @@ class Inputs(ORequestHandler):
class ListTests(ORequestHandler):
def get(self):
- self.write(oonidApplication.director.netTests)
+ test_list = copy.deepcopy(oonidApplication.director.netTests)
+ for test_id in test_list.keys():
+ test_list[test_id].pop('path')
+ self.write(test_list)
+
+def get_net_test_loader(test_options, test_file):
+ options = []
+ for k, v in test_options.items():
+ options.append('--'+k)
+ options.append(v)
+
+ net_test_loader = NetTestLoader(options,
+ test_file=test_file)
+ return net_test_loader
+
+def get_reporters(net_test_loader):
+ test_details = net_test_loader.testDetails
+ yaml_reporter = YAMLReporter(test_details, config.reports_directory)
+ #oonib_reporter = OONIBReporter(test_details, collector)
+ return [yaml_reporter]
class StartTest(ORequestHandler):
def post(self, test_name):
"""
Starts a test with the specified options.
"""
- json.decode(self.request.body)
+ test_file = oonidApplication.director.netTests[test_name]['path']
+ test_options = json.loads(self.request.body)
+ net_test_loader = get_net_test_loader(test_options, test_file)
+ try:
+ net_test_loader.checkOptions()
+ oonidApplication.director.startNetTest(net_test_loader,
+ get_reporters(net_test_loader))
+ except MissingRequiredOption, option_name:
+ self.write({'error':
+ 'Missing required option: "%s"' % option_name})
+ except usage.UsageError, e:
+ self.write({'error':
+ 'Error in parsing options'})
+ except errors.InsufficientPrivileges:
+ self.write({'error':
+ 'Insufficient priviledges'})
class StopTest(ORequestHandler):
def delete(self, test_name):
pass
+def get_test_results(test_id):
+ test_results = []
+ for test_result in os.listdir(config.reports_directory):
+ if test_result.startswith('report-'+test_id):
+ with open(os.path.join(config.reports_directory, test_result)) as f:
+ test_content = ''.join(f.readlines())
+ test_results.append({'name': test_result,
+ 'content': test_content})
+ return test_results
+
class TestStatus(ORequestHandler):
def get(self, test_id):
- pass
-
+ try:
+ test = copy.deepcopy(oonidApplication.director.netTests[test_id])
+ test.pop('path')
+ test['results'] = get_test_results(test_id)
+ self.write(test)
+ except KeyError:
+ self.write({'error':
+ 'Test with such ID not found!'})
+
+config.read_config_file()
oonidAPI = [
(r"/status", Status),
(r"/inputs", Inputs),
diff --git a/ooni/director.py b/ooni/director.py
index 1ef878c..bb02201 100644
--- a/ooni/director.py
+++ b/ooni/director.py
@@ -65,7 +65,6 @@ class Director(object):
def __init__(self):
self.activeNetTests = []
- self.netTests = self.getNetTests()
self.measurementManager = MeasurementManager()
self.measurementManager.director = self
@@ -114,6 +113,8 @@ class Director(object):
@defer.inlineCallbacks
def start(self):
+ self.netTests = self.getNetTests()
+
if config.privacy.includepcap:
log.msg("Starting")
if not config.reports.pcap:
@@ -207,15 +208,13 @@ class Director(object):
self.allTestsDone = defer.Deferred()
@defer.inlineCallbacks
- def startNetTest(self, _, net_test_loader, reporters):
+ def startNetTest(self, net_test_loader, reporters):
"""
Create the Report for the NetTest and start the report NetTest.
Args:
net_test_loader:
an instance of :class:ooni.nettest.NetTestLoader
-
- _: #XXX very dirty hack
"""
report = Report(reporters, self.reportEntryManager)
diff --git a/ooni/nettest.py b/ooni/nettest.py
index 0d0e889..964bee3 100644
--- a/ooni/nettest.py
+++ b/ooni/nettest.py
@@ -115,7 +115,7 @@ def getOption(opt_parameter, required_options, type='text'):
required = False
return {'description': description,
- 'default': default, 'required': required,
+ 'value': default, 'required': required,
'type': type
}
@@ -157,7 +157,8 @@ def getNetTestInformation(net_test_file):
'name': test_class.name,
'description': test_class.description,
'version': test_class.version,
- 'arguments': getArguments(test_class)
+ 'arguments': getArguments(test_class),
+ 'path': net_test_file
}
return information
diff --git a/ooni/oonicli.py b/ooni/oonicli.py
index 40453b1..16c02e8 100644
--- a/ooni/oonicli.py
+++ b/ooni/oonicli.py
@@ -178,7 +178,9 @@ def runWithDirector():
raise e
log.debug("adding callback for startNetTest")
- d.addCallback(director.startNetTest, net_test_loader, reporters)
+ @d.addCallback
+ def cb(res):
+ director.startNetTest(net_test_loader, reporters)
director.allTestsDone.addBoth(shutdown)
def start():
diff --git a/ooni/settings.py b/ooni/settings.py
index acb7502..846fc10 100644
--- a/ooni/settings.py
+++ b/ooni/settings.py
@@ -29,12 +29,15 @@ class OConfig(object):
def set_paths(self):
if self.global_options.get('datadir'):
self.data_directory = abspath(expanduser(self.global_options['datadir']))
+ elif self.advanced.get('data_dir'):
+ self.data_directory = self.advanced['data_dir']
else:
self.data_directory = '/usr/share/ooni/'
self.nettest_directory = os.path.join(self.data_directory, 'nettests')
self.ooni_home = os.path.join(expanduser('~'), '.ooni')
self.inputs_directory = os.path.join(self.ooni_home, 'inputs')
+ self.reports_directory = os.path.join(self.ooni_home, 'reports')
if self.global_options.get('configfile'):
config_file = global_options['configfile']
@@ -48,6 +51,8 @@ class OConfig(object):
print "Creating it in '%s'." % self.ooni_home
os.mkdir(self.ooni_home)
os.mkdir(self.inputs_directory)
+ if not os.path.isdir(self.reports_directory):
+ os.mkdir(self.reports_directory)
def _create_config_file(self):
sample_config_file = os.path.join(self.data_directory,
@@ -75,6 +80,7 @@ class OConfig(object):
getattr(self, setting)[k] = v
except AttributeError:
pass
+ self.set_paths()
def generate_pcap_filename():
if self.global_options.get('pcapfile'):
diff --git a/ooni/tests/test_nettest.py b/ooni/tests/test_nettest.py
index 77b8a1c..eb909d9 100644
--- a/ooni/tests/test_nettest.py
+++ b/ooni/tests/test_nettest.py
@@ -224,7 +224,7 @@ class TestNetTest(unittest.TestCase):
ntl.checkOptions()
director = Director()
- d = director.startNetTest('', ntl, [MockReporter()])
+ d = director.startNetTest(ntl, [MockReporter()])
@d.addCallback
def complete(result):