Some application execution boilerplate
authorClaudio-Daniel Freire <claudio-daniel.freire@inria.fr>
Thu, 21 Apr 2011 13:35:25 +0000 (15:35 +0200)
committerClaudio-Daniel Freire <claudio-daniel.freire@inria.fr>
Thu, 21 Apr 2011 13:35:25 +0000 (15:35 +0200)
src/nepi/testbeds/planetlab/application.py
src/nepi/testbeds/planetlab/execute.py
src/nepi/testbeds/planetlab/metadata_v01.py
test/testbeds/planetlab/execute.py

index 471fd44..38c40a7 100644 (file)
@@ -4,6 +4,10 @@
 from constants import TESTBED_ID
 import plcapi
 import operator
+import os
+
+from nepi.util.constants import STATUS_NOT_STARTED, STATUS_RUNNING, \
+        STATUS_FINISHED
 
 class Application(object):
     def __init__(self, api=None):
@@ -20,6 +24,14 @@ class Application(object):
         
         # Those are filled when an actual node is connected
         self.node = None
+        
+        # Those are filled when the app is started
+        #   Having both pid and ppid makes it harder
+        #   for pid rollover to induce tracking mistakes
+        self._pid = None
+        self._ppid = None
+        self._stdout_path = None
+        self._stderr_path = None
     
     def __str__(self):
         return "%s<command:%s%s>" % (
@@ -31,3 +43,40 @@ class Application(object):
     def validate(self):
         pass
 
+    def start(self):
+        pass
+    
+    def status(self):
+        return STATUS_FINISHED
+    
+    def kill(self):
+        status = self.status()
+        if status == STATUS_RUNNING:
+            # TODO: kill by pid & ppid
+            pass
+    
+    def remote_trace_path(self, whichtrace):
+        if whichtrace == 'stdout':
+            tracefile = self._stdout_path
+        elif whichtrace == 'stderr':
+            tracefile = self._stderr_path
+        else:
+            tracefile = None
+        
+        return tracefile
+    
+    def sync_trace(self, local_dir, whichtrace):
+        tracefile = self.remote_trace_path(whichtrace)
+        if not tracefile:
+            return None
+        
+        local_path = os.join(local_dir, tracefile)
+        
+        # TODO: sync files
+        f = open(local_path, "w")
+        f.write("BLURP!")
+        f.close()
+        
+        return local_path
+    
+
index a86785b..a358aaf 100644 (file)
@@ -137,10 +137,23 @@ class TestbedController(testbed_impl.TestbedController):
         for element in self._elements.values():
             element.destroy()
 
-    def trace_filename(self, guid, trace_id):
-        # TODO: Need to be defined inside a home!!!! with and experiment id_code
-        return os.path.join(self.home_directory, "%d_%s" % (guid, trace_id))
-
+    def trace(self, guid, trace_id, attribute='value'):
+        app = self._elements[guid]
+        
+        if attribute == 'value':
+            path = app.sync_trace(self.home_directory, trace_id)
+            if path:
+                fd = open(path, "r")
+                content = fd.read()
+                fd.close()
+            else:
+                content = None
+        elif attribute == 'path':
+            content = app.remote_trace_path(trace_id)
+        else:
+            content = None
+        return content
+        
     def follow_trace(self, trace_id, trace):
         self._traces[trace_id] = trace
 
index 2142da6..9110029 100644 (file)
@@ -75,20 +75,23 @@ def start_application(testbed_instance, guid):
     traces = testbed_instance._get_traces(guid)
     app = testbed_instance.elements[guid]
     
-    app.stdout = testbed_instance.trace_filename(guid, "stdout")
-    app.stderr = testbed_instance.trace_filename(guid, "stderr")
+    app.stdout = "stdout" in traces
+    app.stderr = "stderr" in traces
     
-    # TODO
-    pass
+    app.start()
+
+def stop_application(testbed_instance, guid):
+    app = testbed_instance.elements[guid]
+    app.stop()
 
 ### Status functions ###
 
 def status_application(testbed_instance, guid):
     if guid not in testbed_instance.elements.keys():
         return STATUS_NOT_STARTED
+    
     app = testbed_instance.elements[guid]
-    # TODO
-    return STATUS_FINISHED
+    return app.status()
 
 ### Configure functions ###
 
@@ -120,7 +123,7 @@ def configure_tuniface(testbed_instance, guid):
     addresses = testbed_instance._add_address[guid]
     for address in addresses:
         (address, netprefix, broadcast) = address
-        # TODO
+        raise NotImplementedError, "C'mon... TUNs are hard..."
     
     # Do some validations
     element.validate()
@@ -409,6 +412,7 @@ factories_info = dict({
             "create_function": create_application,
             "start_function": start_application,
             "status_function": status_application,
+            "stop_function": stop_application,
             "box_attributes": ["command", "sudo"],
             "connector_types": ["node"],
             "traces": ["stdout", "stderr"]
index 0e98122..3830f09 100755 (executable)
@@ -58,13 +58,14 @@ class NetnsExecuteTestCase(unittest.TestCase):
         instance.start()
         while instance.status(7) != STATUS_FINISHED:
             time.sleep(0.5)
-        ping_result = instance.trace(7, "stdout")
-        comp_result = r"""PING .* \(.*) \d*\(\d*\) bytes of data.
+        ping_result = instance.trace(7, "stdout") or ""
+        comp_result = r"""PING .* \(.*\) \d*\(\d*\) bytes of data.
 
 --- .* ping statistics ---
 1 packets transmitted, 1 received, 0% packet loss, time \d*ms.*
 """
-        self.assertTrue(re.match(comp_result, ping_result, re.MULTILINE))
+        self.assertTrue(re.match(comp_result, ping_result, re.MULTILINE),
+            "Unexpected trace:\n" + ping_result)
         instance.stop()
         instance.shutdown()