the germ for a tool that scans the federation given entry points
authorThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Sat, 18 Dec 2010 15:15:07 +0000 (16:15 +0100)
committerThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Sat, 18 Dec 2010 15:15:07 +0000 (16:15 +0100)
goal is to draw a picture about how the various parts are configured

sfa/client/sfascan.py [new file with mode: 0755]

diff --git a/sfa/client/sfascan.py b/sfa/client/sfascan.py
new file mode 100755 (executable)
index 0000000..0adca4e
--- /dev/null
@@ -0,0 +1,119 @@
+#!/usr/bin/python
+
+import socket
+import re
+
+from sfa.client.sfi import Sfi
+from sfa.util.sfalogging import sfa_logger,sfa_logger_goes_to_console
+import sfa.util.xmlrpcprotocol as xmlrpcprotocol
+
+m_url_with_proto=re.compile("\w+://(?P<hostname>[\w\-\.]+):(?P<port>[0-9]+)/.*")
+m_url_without_proto=re.compile("(?P<hostname>[\w\-\.]+):(?P<port>[0-9]+).*")
+def url_to_hostname_port (url):
+    print 'url',url
+    match=m_url_with_proto.match(url)
+    if match:
+        return (match.group('hostname'),match.group('port'))
+    match=m_url_without_proto.match(url)
+    if match:
+        return (match.group('hostname'),match.group('port'))
+    return ('undefined','???')
+
+###
+class Interface:
+    def __init__ (self,url,name=None):
+        self.names=[]
+        self.set_name(name)
+        try:
+            (self.hostname,self.port)=url_to_hostname_port(url)
+            self.ip=socket.gethostbyname(self.hostname)
+            self.probed=False
+        except:
+            import traceback
+            traceback.print_exc()
+            self.hostname="undefined"
+            self.port="???"
+            self.probed=True
+            self._version={}
+
+    def equal (self,against):
+        return (self.ip == against.ip) and (self.port == against.port)
+
+    def set_name (self,name):
+        if name and name not in self.names: 
+            self.names.append(name)
+
+    def url(self):
+        return "http://%s:%s"%(self.hostname,self.port)
+
+    # connect to server and trigger GetVersion
+    def get_version(self):
+        if self.probed:
+            return self._version
+        # dummy to meet Sfi's expectations for its 'options' field
+        class DummyOptions:
+            pass
+        options=DummyOptions()
+        options.verbose=False
+        try:
+            client=Sfi(options)
+            client.read_config()
+            key_file = client.get_key_file()
+            cert_file = client.get_cert_file(key_file)
+            url="http://%s:%s/"%(self.hostname,self.port)
+            sfa_logger().info('issuing get version at %s'%url)
+            server=xmlrpcprotocol.get_server(url, key_file, cert_file, options)
+            self._version=server.GetVersion()
+#            pdb.set_trace()
+        except:
+            self._version={}
+        self.probed=True
+        return self._version
+
+class SfaScan:
+
+    # provide the entry points (a list of interfaces)
+    def __init__ (self):
+        pass
+
+    # scan from the given interfaces as entry points
+    def scan(self,interfaces):
+        import pdb
+#        pdb.set_trace()
+        if not isinstance(interfaces,list):
+            interfaces=[interfaces]
+        # should add nodes, but with what name ?
+        to_scan=interfaces
+        scanned=[]
+        def was_scanned (interface):
+            for i in scanned:
+                if interface.equal(i): return i
+            return False
+        # keep on looping until we reach a fixed point
+        while to_scan:
+            for interface in to_scan:
+                version=interface.get_version()
+                if 'peers' in version: 
+                    for (next_name,next_url) in version['peers'].items():
+                        # should add edge
+                        next_interface=Interface(next_url)
+                        seen_interface=was_scanned(next_interface)
+                        if seen_interface:
+                            # record name
+                            seen_interface.set_name(next_name)
+                        else:
+                            sfa_logger().info('adding %s'%next_interface.url())
+                            to_scan.append(next_interface)
+                            
+                scanned.append(interface)
+                to_scan.remove(interface)
+    
+
+def main():
+    sfa_logger_goes_to_console()
+    scanner=SfaScan()
+    entry=Interface("http://www.planet-lab.eu:12345/")
+    scanner.scan(entry)
+
+if __name__ == '__main__':
+    main()