Dummy Testbed Driver update and bug fix
Mohamed Larabi [Fri, 19 Oct 2012 14:37:51 +0000 (16:37 +0200)]
13 files changed:
config/default_config.xml
config/sfa-config-tty
setup.py
sfa.spec
sfa/dummy/README.txt [new file with mode: 0644]
sfa/dummy/__init__.py [new file with mode: 0644]
sfa/dummy/dummy_testbed_api.py
sfa/dummy/dummy_testbed_api_client.py [new file with mode: 0644]
sfa/dummy/dummyaggregate.py
sfa/dummy/dummydriver.py
sfa/dummy/dummyshell.py
sfa/generic/dummy.py
sfa/importer/dummyimporter.py

index 6aa3df9..f1bf784 100644 (file)
@@ -342,6 +342,20 @@ Thierry Parmentelat
     </category>
 
     <!-- ======================================== -->
+    <category id="sfa_dummy">
+      <name></name>
+      <description>The settings for using SFA with a demmy testbed.</description>
+
+      <variablelist>
+        <variable id="url" type="string">
+          <name>XMLRPC URL</name>
+          <value>http://127.0.0.1:8080</value>
+          <description>URL for the Dummy Testbed xmlrpc API</description>
+        </variable>
+      </variablelist>
+    </category>
+
+    <!-- ======================================== -->
 
   </variables>
 
index fe3aab3..4de43ee 100755 (executable)
@@ -35,7 +35,8 @@ flavour_xml_section_hash = { \
     'pl':'sfa_plc',
     'openstack':'sfa_nova',
     'fd':'sfa_federica',
-    'nitos':'sfa_nitos'
+    'nitos':'sfa_nitos',
+    'dummy':'sfa_dummy',
     }
 configuration={ \
     'name':'sfa',
index 041904c..575dfd6 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -38,6 +38,7 @@ packages = [
     'sfa/client',
     'sfa/planetlab',
     'sfa/nitos',
+    'sfa/dummy',
     'sfa/openstack',
     'sfa/federica',
     'sfatables',
index 8d393e6..51efbbd 100644 (file)
--- a/sfa.spec
+++ b/sfa.spec
@@ -93,6 +93,11 @@ Summary: the SFA layer around NITOS
 Group: Applications/System
 Requires: sfa
 
+%package dummy
+Summary: the SFA layer around a Dummy Testbed 
+Group: Applications/System
+Requires: sfa
+
 %package sfatables
 Summary: sfatables policy tool for SFA
 Group: Applications/System
@@ -221,6 +226,9 @@ rm -rf $RPM_BUILD_ROOT
 %files nitos
 %{python_sitelib}/sfa/nitos
 
+%files dummy
+%{python_sitelib}/sfa/dummy
+
 %files sfatables
 /etc/sfatables/*
 %{_bindir}/sfatables
diff --git a/sfa/dummy/README.txt b/sfa/dummy/README.txt
new file mode 100644 (file)
index 0000000..c205e4b
--- /dev/null
@@ -0,0 +1,66 @@
+######################################  DUMMY TESTBED DRIVER FOR SFA ############################################
+
+In order to make easy the adoption of SFA by the testbed owners, we decided to implement this DUMMY TESTBED DRIVER FOR SFA which represent one flavour of SFA (dummy).
+
+Testbed owners deciding to wrap their testbed with SFA, can follow this small step-by-step guide to know how SFA works, how it interact with the testbed and what are the needed pieces to glue SFA and the testbed.
+
+
+STEP-BY-STEP GUIDE :
+
+1. Install SFA (http://svn.planet-lab.org/wiki/SFATutorialInstall#InstallingSFA) 
+(On RPM based OS, the SFA sources go here : /usr/lib/python2.7/site-packages/sfa )
+
+2. Launch the Dummy testbed XML-RPC API:
+
+# python /usr/lib/python2.7/site-packages/sfa/dummy/dummy_testbed_api.py
+
+3. Configure SFA to the "dummy" flavour as follow :
+
+# sfa-config-tty
+Enter command (u for usual changes, w to save, ? for help) u
+== sfa_generic_flavour : [dummy] dummy ("dummy" flavour)
+== sfa_interface_hrn : [pla] pla   (Choose your Authority name)           
+== sfa_registry_root_auth : [pla] pla (Choose your Authority name)
+== sfa_registry_host : [localhost] localhost
+== sfa_aggregate_host : [localhost] localhost
+== sfa_sm_host : [localhost] localhost
+== sfa_db_host : [localhost] localhost
+== sfa_dummy_url : [http://127.0.0.1:8080] 
+Enter command (u for usual changes, w to save, ? for help) w
+Wrote /etc/sfa/configs/site_config
+Merged
+       /etc/sfa/default_config.xml
+and    /etc/sfa/configs/site_config
+into   /etc/sfa/sfa_config
+You might want to type 'r' (restart sfa), 'R' (reload sfa) or 'q' (quit)
+Enter command (u for usual changes, w to save, ? for help) r
+==================== Stopping sfa
+Shutting down SFA                                          [  OK  ]
+==================== Starting sfa
+SFA: Checking for PostgreSQL server                        [  OK  ]
+SFA: installing peer certs                                 [  OK  ]
+SFA: Registry                                              [  OK  ]
+SFA: Aggregate                                             [  OK  ]
+SFA: SliceMgr                                              [  OK  ]
+Enter command (u for usual changes, w to save, ? for help) q
+
+4. Add your user to the dummy testbed and attach it to a slice:
+
+Edit /usr/lib/python2.7/site-packages/sfa/dummy/dummy_testbed_api_client.py with your user info and run:
+# python /usr/lib/python2.7/site-packages/sfa/dummy/dummy_testbed_api_client.py 
+
+5. Import Dummy testbed data to SFA (users, slices, nodes):
+
+# sfaadmin.py reg import_registry
+
+6. Configure you SFI client (http://svn.planet-lab.org/wiki/SFATutorialConfigureSFA#ConfigureSFAClientSFI)
+
+7. Make a test: 
+update the following command with your already configured Authority name. 
+
+# sfi.py list pla.dummy 
+
+8. Now continue testing SFA, have a look at the dummy driver code and write your testbed driver for SFA... Enjoy.
+
+
diff --git a/sfa/dummy/__init__.py b/sfa/dummy/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
index 9a3b52d..f40a853 100644 (file)
@@ -38,7 +38,7 @@ def FilterList(myfilter, mylist):
 # RPC functions definition
 #GET
 def GetTestbedInfo():
-    return {'name': 'Dummy', 'longitude': 123456, 'latitude': 654321, 'domain':'dummy-testbed.org'}
+    return {'name': 'dummy', 'longitude': 123456, 'latitude': 654321, 'domain':'dummy-testbed.org'}
 
 def GetNodes(filter={}):
     global DB
diff --git a/sfa/dummy/dummy_testbed_api_client.py b/sfa/dummy/dummy_testbed_api_client.py
new file mode 100644 (file)
index 0000000..e32c15b
--- /dev/null
@@ -0,0 +1,15 @@
+import xmlrpclib
+from datetime import datetime
+import time
+
+dummy_url = "http://localhost:8080"
+dummy_api = xmlrpclib.ServerProxy(dummy_url)
+
+# Edit the parameters with your user info:
+my_user_id = dummy_api.AddUser({'email': 'john.doe@test.net', 'user_name': 'john.doe', 'keys': ['copy here your ssh-rsa public key']})
+# Your user will be attached with the slice named : slice2 :
+dummy_api.AddUserToSlice({'slice_id': 2, 'user_id': my_user_id})
+
+
+print dummy_api.GetUsers()[-1]
+print dummy_api.GetSlices()[-1]
index e89d88e..53f3de9 100644 (file)
@@ -70,7 +70,7 @@ class DummyAggregate:
             rspec_node['component_id'] = hostname_to_urn(self.driver.hrn, site['name'], node['hostname'])
             rspec_node['component_name'] = node['hostname']
             rspec_node['component_manager_id'] = Xrn(self.driver.hrn, 'authority+cm').get_urn()
-            rspec_node['authority_id'] = hrn_to_urn(PlXrn.site_hrn(self.driver.hrn, site['name']), 'authority+sa')
+            rspec_node['authority_id'] = hrn_to_urn(DummyXrn.site_hrn(self.driver.hrn, site['name']), 'authority+sa')
             rspec_node['exclusive'] = 'false'
             rspec_node['hardware_types'] = [HardwareType({'name': 'plab-pc'}),
                                             HardwareType({'name': 'pc'})]
@@ -111,7 +111,6 @@ class DummyAggregate:
 
         nodes = self.get_nodes(slice_xrn, slice, slivers, options)
         rspec.version.add_nodes(nodes)
-        rspec.version.add_links(links)
         # add sliver defaults
         default_sliver = slivers.get(None, [])
         if default_sliver:
index 227ceba..1fd0843 100644 (file)
@@ -126,11 +126,11 @@ class DummyDriver (Driver):
         type=sfa_record['type']
         pointer=sfa_record['pointer']
         if type == 'user':
-            self.shell.DeleteUser{'user_id': pointer})
+            self.shell.DeleteUser({'user_id': pointer})
         elif type == 'slice':
-            self.shell.DeleteSlice('slice_id': pointer)
+            self.shell.DeleteSlice({'slice_id': pointer})
         elif type == 'node':
-            self.shell.DeleteNode('node_id': pointer)
+            self.shell.DeleteNode({'node_id': pointer})
 
         return True
 
@@ -513,7 +513,7 @@ class DummyDriver (Driver):
         slice = slices[0]
         
         try:
-            self.shell.DeleteSliceFromNodes({'slice_id': slice['slice_id'], 'node_ids': slice['node_ids'])
+            self.shell.DeleteSliceFromNodes({'slice_id': slice['slice_id'], 'node_ids': slice['node_ids']})
             return True
         except:
             return False
index e89d56f..c6cc833 100644 (file)
@@ -15,7 +15,7 @@ class DummyShell:
                     'GetTestbedInfo', 'GetNodes', 'GetSlices', 'GetUsers',
                     'DeleteNode', 'DeleteSlice', 'DeleteUser', 'DeleteKey', 'DeleteUserFromSlice', 
                     'DeleteSliceFromNodes',
-                    'UpdateNode', 'UpdateSlice', 'UpdateUser'
+                    'UpdateNode', 'UpdateSlice', 'UpdateUser',
                    ]
 
 
@@ -25,9 +25,9 @@ class DummyShell:
 
     def __getattr__(self, name):
         def func(*args, **kwds):
-            if not name in direct_calls:
+            if not name in DummyShell.direct_calls:
                 raise Exception, "Illegal method call %s for DUMMY driver"%(name)
-            result=getattr(self.proxy, actual_name)(*args, **kwds)
+            result=getattr(self.proxy, name)(*args, **kwds)
             logger.debug('DummyShell %s returned ... '%(name))
             return result
         return func
index 466b473..63fa25e 100644 (file)
@@ -5,7 +5,7 @@ class dummy (Generic):
     # the importer class
     def importer_class (self): 
         import sfa.importer.dummyimporter
-        return sfa.importer.dummyimporter.PlImporter
+        return sfa.importer.dummyimporter.DummyImporter
         
     # use the standard api class
     def api_class (self):
index d091142..5001849 100644 (file)
@@ -26,7 +26,7 @@ from sfa.trust.certificate import convert_public_key, Keypair
 from sfa.storage.alchemy import dbsession
 from sfa.storage.model import RegRecord, RegAuthority, RegSlice, RegNode, RegUser, RegKey
 
-from sfa.dummy.dummyshell import PlShell    
+from sfa.dummy.dummyshell import DummyShell    
 from sfa.dummy.dummyxrn import hostname_to_hrn, slicename_to_hrn, email_to_hrn, hrn_to_dummy_slicename
 
 def _get_site_hrn(interface_hrn, site):
@@ -126,11 +126,13 @@ class DummyImporter:
         # Get all dummy TB public keys
         keys = []
         for user in users:
-            keys.extend(user['keys'])
+            if 'keys' in user:
+                keys.extend(user['keys'])
         # create a dict user_id -> [ keys ]
         keys_by_person_id = {} 
         for user in users:
-              keys_by_person_id[user['user_id']] = user['keys']
+             if 'keys' in user:
+                 keys_by_person_id[user['user_id']] = user['keys']
         # Get all dummy TB nodes  
         nodes = shell.GetNodes()
         # create hash by node_id
@@ -204,7 +206,7 @@ class DummyImporter:
             for user in users:
                 user_hrn = email_to_hrn(site_hrn, user['email'])
                 # xxx suspicious again
-                if len(person_hrn) > 64: person_hrn = person_hrn[:64]
+                if len(user_hrn) > 64: user_hrn = user_hrn[:64]
                 user_urn = hrn_to_urn(user_hrn, 'user')
 
                 user_record = self.locate_by_type_hrn ( 'user', user_hrn)
@@ -274,7 +276,7 @@ class DummyImporter:
                             else:
                                 user_record.reg_keys=[ RegKey (pubkey)]
                             self.logger.info("DummyImporter: updated person: %s" % user_record)
-                    user_record.email = person['email']
+                    user_record.email = user['email']
                     dbsession.commit()
                     user_record.stale=False
                 except:
@@ -283,7 +285,7 @@ class DummyImporter:
 
             # import slices
             for slice in slices:
-                slice_hrn = slicename_to_hrn(interface_hrn, slice['slice_ame'])
+                slice_hrn = slicename_to_hrn(site_hrn, slice['slice_name'])
                 slice_record = self.locate_by_type_hrn ('slice', slice_hrn)
                 if not slice_record:
                     try: