Merge branch 'geni-v3' of ssh://git.onelab.eu/git/sfa into geni-v3
authorLoic Baron <sandrine.avakian@inria.fr>
Wed, 30 Jul 2014 08:15:32 +0000 (10:15 +0200)
committerLoic Baron <sandrine.avakian@inria.fr>
Wed, 30 Jul 2014 08:15:32 +0000 (10:15 +0200)
Conflicts:
sfa/iotlab/iotlabaggregate.py
sfa/iotlab/iotlabslices.py

69 files changed:
sfa.spec
sfa/client/sfaadmin.py
sfa/client/sfi.py
sfa/cortexlab/cortexlabaggregate.py
sfa/cortexlab/cortexlabdriver.py
sfa/cortexlab/cortexlabslices.py
sfa/dummy/dummy_testbed_api.py
sfa/dummy/dummyaggregate.py
sfa/dummy/dummydriver.py
sfa/dummy/dummyslices.py
sfa/iotlab/iotlabaggregate.py
sfa/iotlab/iotlabdriver.py
sfa/iotlab/iotlabslices.py
sfa/managers/aggregate_manager.py
sfa/managers/driver.py
sfa/managers/registry_manager.py
sfa/managers/slice_manager.py
sfa/methods/Allocate.py
sfa/methods/GetVersion.py
sfa/methods/List.py
sfa/methods/Resolve.py
sfa/nitos/nitosaggregate.py
sfa/nitos/nitosslices.py
sfa/openstack/image.py
sfa/openstack/nova_driver.py
sfa/openstack/osaggregate.py
sfa/planetlab/plaggregate.py
sfa/planetlab/pldriver.py
sfa/planetlab/plslices.py
sfa/rspecs/elements/element.py
sfa/rspecs/elements/versions/iotlabv1Lease.py
sfa/rspecs/elements/versions/iotlabv1Node.py
sfa/rspecs/elements/versions/iotlabv1Sliver.py
sfa/rspecs/elements/versions/nitosv1Channel.py
sfa/rspecs/elements/versions/nitosv1Lease.py
sfa/rspecs/elements/versions/nitosv1Node.py
sfa/rspecs/elements/versions/nitosv1PLTag.py
sfa/rspecs/elements/versions/nitosv1Sliver.py
sfa/rspecs/elements/versions/ofeliav1Port.py
sfa/rspecs/elements/versions/ofeliav1datapath.py
sfa/rspecs/elements/versions/ofeliav1link.py
sfa/rspecs/elements/versions/pgv2DiskImage.py
sfa/rspecs/elements/versions/pgv2Lease.py
sfa/rspecs/elements/versions/pgv2Node.py
sfa/rspecs/elements/versions/pgv2SliverType.py
sfa/rspecs/elements/versions/sfav1Lease.py
sfa/rspecs/elements/versions/sfav1Node.py
sfa/rspecs/elements/versions/sfav1PLTag.py
sfa/rspecs/elements/versions/sfav1Sliver.py
sfa/rspecs/rspec.py
sfa/rspecs/versions/iotlabv1.py
sfa/rspecs/versions/nitosv1.py
sfa/rspecs/versions/ofeliav1.py
sfa/rspecs/versions/pgv2.py
sfa/rspecs/versions/sfav1.py
sfa/storage/model.py
sfa/storage/record.py
sfa/trust/abac_credential.py
sfa/trust/auth.py
sfa/trust/credential.py
sfa/trust/credential_legacy.py [deleted file]
sfa/trust/speaksfor_util.py
sfa/util/config.py
sfa/util/sfatime.py
sfa/util/storage.py
sfa/util/version.py.in
sfa/util/xml.py
sfa/util/xrn.py
testbeds/iotlab/tests/tests_rspecs/iotlab_avakian_slice_iotlab.rspec

index bedcb2c..fcce983 100644 (file)
--- a/sfa.spec
+++ b/sfa.spec
@@ -1,6 +1,6 @@
 %define name sfa
 %define version 3.1
-%define taglevel 5
+%define taglevel 9
 
 %define release %{taglevel}%{?pldistro:.%{pldistro}}%{?date:.%{date}}
 %global python_sitearch        %( python -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)" )
@@ -264,6 +264,27 @@ fi
 #[ "$1" -ge "1" ] && service sfa-cm restart || :
 
 %changelog
+* Mon Jul 21 2014 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - sfa-3.1-9
+- Register can change the user keys using 'reg-keys' as well as 'keys'
+- also accept a single string rather than a list of keys
+- remove 'geni_api' from the registry GetVersion (which is not based on geni anymore)
+- bump the 'sfa' tag in the same registry GetVersion to 3
+- remove all mutable used as default arguments
+
+* Thu Jun 05 2014 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - sfa-3.1-8
+- bugfix, sfi remove was broken
+
+* Wed Jun 04 2014 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - sfa-3.1-7
+- sfi return code should be more meaningful - not yet for all commands though
+- DEFAULT_CREDENTIAL_LIFETIME now 28 days (was 31)
+- dropped support for legacy credentials
+- bugfix: short-lived credentials triggered a bug with UTC translated into localtime
+- further minor cleanup of timestamp formats
+
+* Mon Jun 02 2014 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - sfa-3.1-6
+- iotlab driver: Allocate uses OAR
+- iotlab driver: using actual_caller_hrn
+
 * Thu May 29 2014 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - sfa-3.1-5
 - Slice Manager is down by default
 - sfi renew -l/--as-long-as-possible and e.g. sfi renew <> +2[d|w|m]
index 15004ce..a21cb5f 100755 (executable)
@@ -102,7 +102,7 @@ class RegistryCommands(Commands):
                 pubkey = open(key, 'r').read()
             except IOError:
                 pubkey = key
-            record_dict['keys'] = [pubkey]
+            record_dict['reg-keys'] = [pubkey]
         if slices:
             record_dict['slices'] = slices
         if researchers:
index 4cceb51..dcad9da 100644 (file)
@@ -201,7 +201,7 @@ def load_record_from_opts(options):
             pubkey = options.key
         if not check_ssh_key (pubkey):
             raise SfaInvalidArgument(name='key',msg="Could not find file, or wrong key format")
-        record_dict['keys'] = [pubkey]
+        record_dict['reg-keys'] = [pubkey]
     if hasattr(options, 'slices') and options.slices:
         record_dict['slices'] = options.slices
     if hasattr(options, 'reg_researchers') and options.reg_researchers is not None:
@@ -575,14 +575,13 @@ use this if you mean an authority instead""")
         self.logger.debug("Command=%s" % self.command)
 
         try:
-            self.dispatch(command, command_options, command_args)
+            retcod = self.dispatch(command, command_options, command_args)
         except SystemExit:
             return 1
         except:
             self.logger.log_exc ("sfi command %s failed"%command)
             return 1
-
-        return 0
+        return retcod
     
     ####################
     def read_config(self):
@@ -870,6 +869,18 @@ use this if you mean an authority instead""")
           sys.exit(1)
 
 
+    # helper function to analyze raw output
+    # for main : return 0 if everything is fine, something else otherwise (mostly 1 for now)
+    def success (self, raw):
+        return_value=ReturnValue (raw)
+        output=ReturnValue.get_output(return_value)
+        # means everything is fine
+        if not output: 
+            return 0
+        # something went wrong
+        print 'ERROR:',output
+        return 1
+
     #==========================================================================
     # Following functions implement the commands
     #
@@ -899,6 +910,8 @@ use this if you mean an authority instead""")
                     varname="%s_%s"%(section.upper(),name.upper())
                     value=getattr(self.config_instance,varname)
                     print "%-20s = %s"%(name,value)
+        # xxx should analyze result
+        return 0
 
     @declare_command("","")
     def version(self, options, args):
@@ -920,6 +933,8 @@ use this if you mean an authority instead""")
         else:
             pprinter = PrettyPrinter(indent=4)
             pprinter.pprint(version)
+        # xxx should analyze result
+        return 0
 
     @declare_command("authority","")
     def list(self, options, args):
@@ -947,7 +962,8 @@ use this if you mean an authority instead""")
         terminal_render (list, options)
         if options.file:
             save_records_to_file(options.file, list, options.fileformat)
-        return
+        # xxx should analyze result
+        return 0
     
     @declare_command("name","")
     def show(self, options, args):
@@ -981,7 +997,8 @@ use this if you mean an authority instead""")
             else:                               print record.save_as_xml() 
         if options.file:
             save_records_to_file(options.file, record_dicts, options.fileformat)
-        return
+        # xxx should analyze result
+        return 0
     
     # this historically was named 'add', it is now 'register' with an alias for legacy
     @declare_command("[xml-filename]","",['add'])
@@ -1018,7 +1035,11 @@ use this if you mean an authority instead""")
                 record_dict['first_name'] = record_dict['hrn']
             if 'last_name' not in record_dict:
                 record_dict['last_name'] = record_dict['hrn'] 
-        return self.registry().Register(record_dict, auth_cred)
+        register = self.registry().Register(record_dict, auth_cred)
+        # xxx looks like the result here is not ReturnValue-compatible
+        #return self.success (register)
+        # xxx should analyze result
+        return 0
     
     @declare_command("[xml-filename]","")
     def update(self, options, args):
@@ -1062,7 +1083,11 @@ use this if you mean an authority instead""")
             raise "unknown record type" + record_dict['type']
         if options.show_credential:
             show_credentials(cred)
-        return self.registry().Update(record_dict, cred)
+        update = self.registry().Update(record_dict, cred)
+        # xxx looks like the result here is not ReturnValue-compatible
+        #return self.success(update)
+        # xxx should analyze result
+        return 0
   
     @declare_command("hrn","")
     def remove(self, options, args):
@@ -1077,7 +1102,11 @@ use this if you mean an authority instead""")
             type = '*'
         if options.show_credential:
             show_credentials(auth_cred)
-        return self.registry().Remove(hrn, auth_cred, type)
+        remove = self.registry().Remove(hrn, auth_cred, type)
+        # xxx looks like the result here is not ReturnValue-compatible
+        #return self.success (remove)
+        # xxx should analyze result
+        return 0
     
     # ==================================================================
     # Slice-related commands
@@ -1124,16 +1153,15 @@ use this if you mean an authority instead""")
                 api_options['geni_rspec_version'] = {'type': 'geni', 'version': '3'}
         else:
             api_options['geni_rspec_version'] = {'type': 'geni', 'version': '3'}
-        result = server.ListResources (creds, api_options)
-        value = ReturnValue.get_value(result)
+        list_resources = server.ListResources (creds, api_options)
+        value = ReturnValue.get_value(list_resources)
         if self.options.raw:
-            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+            save_raw_to_file(list_resources, self.options.raw, self.options.rawformat, self.options.rawbanner)
         if options.file is not None:
             save_rspec_to_file(value, options.file)
         if (self.options.raw is None) and (options.file is None):
             display_rspec(value, options.format)
-
-        return
+        return self.success(list_resources)
 
     @declare_command("slice_hrn","")
     def describe(self, options, args):
@@ -1169,16 +1197,15 @@ use this if you mean an authority instead""")
                 api_options['geni_rspec_version'] = {'type': 'geni', 'version': '3'}
         urn = Xrn(args[0], type='slice').get_urn()
         remove_none_fields(api_options) 
-        result = server.Describe([urn], creds, api_options)
-        value = ReturnValue.get_value(result)
+        describe = server.Describe([urn], creds, api_options)
+        value = ReturnValue.get_value(describe)
         if self.options.raw:
-            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+            save_raw_to_file(describe, self.options.raw, self.options.rawformat, self.options.rawbanner)
         if options.file is not None:
             save_rspec_to_file(value['geni_rspec'], options.file)
         if (self.options.raw is None) and (options.file is None):
             display_rspec(value['geni_rspec'], options.format)
-
-        return 
+        return self.success (describe)
 
     @declare_command("slice_hrn [<sliver_urn>...]","")
     def delete(self, options, args):
@@ -1207,13 +1234,13 @@ use this if you mean an authority instead""")
         api_options ['call_id'] = unique_call_id()
         if options.show_credential:
             show_credentials(creds)
-        result = server.Delete(sliver_urns, creds, *self.ois(server, api_options ) )
-        value = ReturnValue.get_value(result)
+        delete = server.Delete(sliver_urns, creds, *self.ois(server, api_options ) )
+        value = ReturnValue.get_value(delete)
         if self.options.raw:
-            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+            save_raw_to_file(delete, self.options.raw, self.options.rawformat, self.options.rawbanner)
         else:
             print value
-        return value
+        return self.success (delete)
 
     @declare_command("slice_hrn rspec","")
     def allocate(self, options, args):
@@ -1262,16 +1289,15 @@ use this if you mean an authority instead""")
         api_options['sfa_users'] = sfa_users
         api_options['geni_users'] = geni_users
 
-        result = server.Allocate(slice_urn, creds, rspec, api_options)
-        value = ReturnValue.get_value(result)
+        allocate = server.Allocate(slice_urn, creds, rspec, api_options)
+        value = ReturnValue.get_value(allocate)
         if self.options.raw:
-            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+            save_raw_to_file(allocate, self.options.raw, self.options.rawformat, self.options.rawbanner)
         if options.file is not None:
             save_rspec_to_file (value['geni_rspec'], options.file)
         if (self.options.raw is None) and (options.file is None):
             print value
-        return value
-        
+        return self.success(allocate)
 
     @declare_command("slice_hrn [<sliver_urn>...]","")
     def provision(self, options, args):
@@ -1328,15 +1354,15 @@ use this if you mean an authority instead""")
             users = pg_users_arg(user_records)
         
         api_options['geni_users'] = users
-        result = server.Provision(sliver_urns, creds, api_options)
-        value = ReturnValue.get_value(result)
+        provision = server.Provision(sliver_urns, creds, api_options)
+        value = ReturnValue.get_value(provision)
         if self.options.raw:
-            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+            save_raw_to_file(provision, self.options.raw, self.options.rawformat, self.options.rawbanner)
         if options.file is not None:
             save_rspec_to_file (value['geni_rspec'], options.file)
         if (self.options.raw is None) and (options.file is None):
             print value
-        return value     
+        return self.success(provision)
 
     @declare_command("slice_hrn","")
     def status(self, options, args):
@@ -1358,14 +1384,13 @@ use this if you mean an authority instead""")
         api_options['call_id']=unique_call_id()
         if options.show_credential:
             show_credentials(creds)
-        result = server.Status([slice_urn], creds, *self.ois(server,api_options))
-        value = ReturnValue.get_value(result)
+        status = server.Status([slice_urn], creds, *self.ois(server,api_options))
+        value = ReturnValue.get_value(status)
         if self.options.raw:
-            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+            save_raw_to_file(status, self.options.raw, self.options.rawformat, self.options.rawbanner)
         else:
             print value
-        # Thierry: seemed to be missing
-        return value
+        return self.success (status)
 
     @declare_command("slice_hrn [<sliver_urn>...] action","")
     def action(self, options, args):
@@ -1391,13 +1416,13 @@ use this if you mean an authority instead""")
             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
             creds.append(delegated_cred)
         
-        result = server.PerformOperationalAction(sliver_urns, creds, action , api_options)
-        value = ReturnValue.get_value(result)
+        perform_action = server.PerformOperationalAction(sliver_urns, creds, action , api_options)
+        value = ReturnValue.get_value(perform_action)
         if self.options.raw:
-            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+            save_raw_to_file(perform_action, self.options.raw, self.options.rawformat, self.options.rawbanner)
         else:
             print value
-        return value
+        return self.success (perform_action)
 
     @declare_command("slice_hrn [<sliver_urn>...] time",
                      "\n".join(["sfi renew onelab.ple.heartbeat 2015-04-31",
@@ -1435,14 +1460,13 @@ use this if you mean an authority instead""")
             api_options['geni_extend_alap']=True
         if options.show_credential:
             show_credentials(creds)
-        result =  server.Renew(sliver_urns, creds, input_time, *self.ois(server,api_options))
-        value = ReturnValue.get_value(result)
+        renew =  server.Renew(sliver_urns, creds, input_time, *self.ois(server,api_options))
+        value = ReturnValue.get_value(renew)
         if self.options.raw:
-            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+            save_raw_to_file(renew, self.options.raw, self.options.rawformat, self.options.rawbanner)
         else:
             print value
-        return value
-
+        return self.success(renew)
 
     @declare_command("slice_hrn","")
     def shutdown(self, options, args):
@@ -1456,14 +1480,13 @@ use this if you mean an authority instead""")
         # creds
         slice_cred = self.slice_credential(slice_hrn)
         creds = [slice_cred]
-        result = server.Shutdown(slice_urn, creds)
-        value = ReturnValue.get_value(result)
+        shutdown = server.Shutdown(slice_urn, creds)
+        value = ReturnValue.get_value(shutdown)
         if self.options.raw:
-            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+            save_raw_to_file(shutdown, self.options.raw, self.options.rawformat, self.options.rawbanner)
         else:
             print value
-        return value         
-    
+        return self.success (shutdown)
 
     @declare_command("[name]","")
     def gid(self, options, args):
@@ -1482,6 +1505,8 @@ use this if you mean an authority instead""")
             filename = os.sep.join([self.options.sfi_dir, '%s.gid' % target_hrn])
         self.logger.info("writing %s gid to %s" % (target_hrn, filename))
         GID(string=gid).save_to_file(filename)
+        # xxx should analyze result
+        return 0
          
     ####################
     @declare_command("to_hrn","""$ sfi delegate -u -p -s ple.inria.heartbeat -s ple.inria.omftest ple.upmc.slicebrowser
@@ -1682,7 +1707,8 @@ $ sfi m -b http://mymanifold.foo.com:7080/
         # it is probably not helpful as people would not
         # need to run 'sfi delegate' at all anymore
         if count_success != count_all: sys.exit(1)
-        return
+        # xxx should analyze result
+        return 0
 
     @declare_command("cred","")
     def trusted(self, options, args):
@@ -1705,5 +1731,5 @@ $ sfi m -b http://mymanifold.foo.com:7080/
             cert = Certificate(string=trusted_cert)
             self.logger.debug('Sfi.trusted -> %r'%cert.get_subject())
             print "Certificate:\n%s\n\n"%trusted_cert
-        return 
-
+        # xxx should analyze result
+        return 0
index d9cddf3..24a5310 100644 (file)
@@ -292,7 +292,7 @@ class CortexlabAggregate:
         return rspec_node
 
 
-    def rspec_node_to_geni_sliver(self, rspec_node, sliver_allocations = {}):
+    def rspec_node_to_geni_sliver(self, rspec_node, sliver_allocations=None):
         """Makes a geni sliver structure from all the nodes allocated
         to slivers in the sliver_allocations dictionary. Returns the states
         of the sliver.
@@ -312,6 +312,8 @@ class CortexlabAggregate:
         .. seealso:: node_to_rspec_node
 
         """
+        if sliver_allocations is None: sliver_allocations={}
+
         if rspec_node['sliver_id'] in sliver_allocations:
             # set sliver allocation and operational status
             sliver_allocation = sliver_allocations[rspec_node['sliver_id']]
@@ -555,7 +557,7 @@ class CortexlabAggregate:
 
 
 
-    def get_slivers(self, urns, options={}):
+    def get_slivers(self, urns, options=None):
         """Get slivers of the given slice urns. Slivers contains slice, node and
         user information.
 
@@ -569,7 +571,7 @@ class CortexlabAggregate:
 
         .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3/CommonConcepts#urns
         """
-
+        if options is None: options={}
 
         slice_ids = set()
         node_ids = []
@@ -667,7 +669,7 @@ class CortexlabAggregate:
         return slivers
 
 
-    def list_resources(self, version = None, options={}):
+    def list_resources(self, version = None, options=None):
         """
         Returns an advertisement Rspec of available resources at this
         aggregate. This Rspec contains a resource listing along with their
@@ -688,6 +690,8 @@ class CortexlabAggregate:
         .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3#ListResources
         """
 
+        if options is None: options={}
+
         version_manager = VersionManager()
         version = version_manager.get_version(version)
         rspec_version = version_manager._get_version(version.type,
@@ -722,7 +726,7 @@ class CortexlabAggregate:
         return rspec.toxml()
 
 
-    def describe(self, urns, version=None, options={}):
+    def describe(self, urns, version=None, options=None):
         """
         Retrieve a manifest RSpec describing the resources contained by the
         named entities, e.g. a single slice or a set of the slivers in a slice.
@@ -752,6 +756,7 @@ class CortexlabAggregate:
         .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3#Describe
         .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3/CommonConcepts#urns
         """
+        if options is None: options={}
         version_manager = VersionManager()
         version = version_manager.get_version(version)
         rspec_version = version_manager._get_version(
index bc674f7..c5ad4e6 100644 (file)
@@ -1081,7 +1081,7 @@ class CortexlabDriver(Driver):
 
 
 
-    def delete(self, slice_urns, options={}):
+    def delete(self, slice_urns, options=None):
         """
         Deletes the lease associated with the slice hrn and the credentials
             if the slice belongs to iotlab. Answer to DeleteSliver.
@@ -1099,6 +1099,7 @@ class CortexlabDriver(Driver):
         .. note:: creds are unused, and are not used either in the dummy driver
              delete_sliver .
         """
+        if options is None: options={}
         # collect sliver ids so we can update sliver allocation states after
         # we remove the slivers.
         aggregate = CortexlabAggregate(self)
@@ -1390,17 +1391,20 @@ class CortexlabDriver(Driver):
 
 
     # first 2 args are None in case of resource discovery
-    def list_resources (self, version=None, options={}):
+    def list_resources (self, version=None, options=None):
+        if options is None: options={}
         aggregate = CortexlabAggregate(self)
         rspec =  aggregate.list_resources(version=version, options=options)
         return rspec
 
 
-    def describe(self, urns, version, options={}):
+    def describe(self, urns, version, options=None):
+        if options is None: options={}
         aggregate = CortexlabAggregate(self)
         return aggregate.describe(urns, version=version, options=options)
 
-    def status (self, urns, options={}):
+    def status (self, urns, options=None):
+        if options is None: options={}
         aggregate = CortexlabAggregate(self)
         desc =  aggregate.describe(urns, version='GENI 3')
         status = {'geni_urn': desc['geni_urn'],
@@ -1408,7 +1412,8 @@ class CortexlabDriver(Driver):
         return status
 
 
-    def allocate (self, urn, rspec_string, expiration, options={}):
+    def allocate (self, urn, rspec_string, expiration, options=None):
+        if options is None: options={}
         xrn = Xrn(urn)
         aggregate = CortexlabAggregate(self)
 
@@ -1488,7 +1493,8 @@ class CortexlabDriver(Driver):
 
         return aggregate.describe([xrn.get_urn()], version=rspec.version)
 
-    def provision(self, urns, options={}):
+    def provision(self, urns, options=None):
+        if options is None: options={}
         # update users
         slices = CortexlabSlices(self)
         aggregate = CortexlabAggregate(self)
index ee160d4..888d7db 100644 (file)
@@ -351,7 +351,7 @@ class CortexlabSlices:
         return sfa_slice
 
 
-    def verify_persons(self, slice_hrn, slice_record, users, options={}):
+    def verify_persons(self, slice_hrn, slice_record, users, options=None):
         """Ensures the users in users list exist and are enabled in LDAP. Adds
         person if needed(AddPerson).
 
@@ -378,6 +378,7 @@ class CortexlabSlices:
 
         """
 
+        if options is None: options={}
 
         logger.debug("CortexlabSlices \tverify_persons \tslice_hrn  %s  \
                     \t slice_record %s\r\n users %s \t  "
@@ -525,10 +526,11 @@ class CortexlabSlices:
         return added_persons
 
 
-    def verify_keys(self, persons, users, peer, options={}):
+    def verify_keys(self, persons, users, peer, options=None):
         """
         .. warning:: unused
         """
+        if options is None: options={}
         # existing keys
         key_ids = []
         for person in persons:
index 2673166..f553e40 100644 (file)
@@ -12,7 +12,12 @@ for i in range(1,11):
 
 slices_list = []
 for i in range(1,3):
-    slice = {'slice_name': 'slice'+str(i), 'user_ids': range(i,4,2), 'slice_id': i, 'node_ids': range(i,10,2), 'enabled': True, 'expires': int(time.time())+60*60*24*30}
+    slice = {'slice_name': 'slice'+str(i), 
+             'user_ids': range(i,4,2), 
+             'slice_id': i, 
+             'node_ids': range(i,10,2),
+             'enabled': True,
+             'expires': int(time.time())+60*60*24*30}
     slices_list.append(slice)
 
 users_list = []
@@ -43,7 +48,8 @@ def FilterList(myfilter, mylist):
 def GetTestbedInfo():
     return {'name': 'dummy', 'longitude': 123456, 'latitude': 654321, 'domain':'dummy-testbed.org'}
 
-def GetNodes(filter={}):
+def GetNodes(filter=None):
+    if filter is None: filter={}
     global DB
     result = []
     result.extend(DB['nodes_list'])
@@ -55,7 +61,8 @@ def GetNodes(filter={}):
         result = FilterList(filter, result)
     return result
 
-def GetSlices(filter={}):
+def GetSlices(filter=None):
+    if filter is None: filter={}
     global DB
     result = []
     result.extend(DB['slices_list'])
@@ -69,7 +76,8 @@ def GetSlices(filter={}):
     return result
 
 
-def GetUsers(filter={}):
+def GetUsers(filter=None):
+    if filter is None: filter={}
     global DB
     result = []
     result.extend(DB['users_list'])
index 576ccd5..c5b4d10 100644 (file)
@@ -52,12 +52,14 @@ class DummyAggregate:
 
         return (slice, slivers)
 
-    def get_nodes(self, options={}):
+    def get_nodes(self, options=None):
+        if options is None: options={}
         filter = {}
         nodes = self.driver.shell.GetNodes(filter)
         return nodes
 
-    def get_slivers(self, urns, options={}):
+    def get_slivers(self, urns, options=None):
+        if options is None: options={}
         slice_names = set()
         slice_ids = set()
         node_ids = []
@@ -122,7 +124,8 @@ class DummyAggregate:
             slivers.append(node)
         return slivers
 
-    def node_to_rspec_node(self, node, options={}):
+    def node_to_rspec_node(self, node, options=None):
+        if options is None: options={}
         rspec_node = NodeElement()
         site=self.driver.testbedInfo
         rspec_node['component_id'] = hostname_to_urn(self.driver.hrn, site['name'], node['hostname'])
@@ -163,7 +166,8 @@ class DummyAggregate:
                       })
         return rspec_node
 
-    def get_slice_nodes(self, slice, options={}):
+    def get_slice_nodes(self, slice, options=None):
+        if options is None: options={}
         nodes_dict = {}
         filter = {}
         if slice and slice.get('node_ids'):
@@ -176,7 +180,8 @@ class DummyAggregate:
             nodes_dict[node['node_id']] = node
         return nodes_dict
 
-    def rspec_node_to_geni_sliver(self, rspec_node, sliver_allocations = {}):
+    def rspec_node_to_geni_sliver(self, rspec_node, sliver_allocations = None):
+        if sliver_allocations is None: sliver_allocations={}
         if rspec_node['sliver_id'] in sliver_allocations:
             # set sliver allocation and operational status
             sliver_allocation = sliver_allocations[rspec_node['sliver_id']]
@@ -202,7 +207,8 @@ class DummyAggregate:
                        }
         return geni_sliver
 
-    def list_resources(self, version = None, options={}):
+    def list_resources(self, version = None, options=None):
+        if options is None: options={}
 
         version_manager = VersionManager()
         version = version_manager.get_version(version)
@@ -224,7 +230,8 @@ class DummyAggregate:
 
         return rspec.toxml()
 
-    def describe(self, urns, version=None, options={}):
+    def describe(self, urns, version=None, options=None):
+        if options is None: options={}
         version_manager = VersionManager()
         version = version_manager.get_version(version)
         rspec_version = version_manager._get_version(version.type, version.version, 'manifest')
index 4d7f7a3..a69662e 100644 (file)
@@ -412,16 +412,19 @@ class DummyDriver (Driver):
     def aggregate_version (self):
         return {}
 
-    def list_resources (self, version=None, options={}):
+    def list_resources (self, version=None, options=None):
+        if options is None: options={}
         aggregate = DummyAggregate(self)
         rspec =  aggregate.list_resources(version=version, options=options)
         return rspec
 
-    def describe(self, urns, version, options={}):
+    def describe(self, urns, version, options=None):
+        if options is None: options={}
         aggregate = DummyAggregate(self)
         return aggregate.describe(urns, version=version, options=options)
     
-    def status (self, urns, options={}):
+    def status (self, urns, options=None):
+        if options is None: options={}
         aggregate = DummyAggregate(self)
         desc =  aggregate.describe(urns, version='GENI 3')
         status = {'geni_urn': desc['geni_urn'],
@@ -429,7 +432,8 @@ class DummyDriver (Driver):
         return status
 
         
-    def allocate (self, urn, rspec_string, expiration, options={}):
+    def allocate (self, urn, rspec_string, expiration, options=None):
+        if options is None: options={}
         xrn = Xrn(urn)
         aggregate = DummyAggregate(self)
         slices = DummySlices(self)
@@ -453,7 +457,8 @@ class DummyDriver (Driver):
 
         return aggregate.describe([xrn.get_urn()], version=rspec.version)
 
-    def provision(self, urns, options={}):
+    def provision(self, urns, options=None):
+        if options is None: options={}
         # update users
         slices = DummySlices(self)
         aggregate = DummyAggregate(self)
@@ -469,7 +474,8 @@ class DummyDriver (Driver):
         rspec_version = version_manager.get_version(options['geni_rspec_version'])
         return self.describe(urns, rspec_version, options=options)
 
-    def delete(self, urns, options={}):
+    def delete(self, urns, options=None):
+        if options is None: options={}
         # collect sliver ids so we can update sliver allocation states after
         # we remove the slivers.
         aggregate = DummyAggregate(self)
@@ -504,7 +510,8 @@ class DummyDriver (Driver):
                  'geni_expires': datetime_to_string(utcparse(sliver['expires']))})  
         return geni_slivers
 
-    def renew (self, urns, expiration_time, options={}):
+    def renew (self, urns, expiration_time, options=None):
+        if options is None: options={}
         aggregate = DummyAggregate(self)
         slivers = aggregate.get_slivers(urns)
         if not slivers:
@@ -516,7 +523,8 @@ class DummyDriver (Driver):
         description = self.describe(urns, 'GENI 3', options)
         return description['geni_slivers']
 
-    def perform_operational_action (self, urns, action, options={}):
+    def perform_operational_action (self, urns, action, options=None):
+        if options is None: options={}
         # Dummy doesn't support operational actions. Lets pretend like it
         # supports start, but reject everything else.
         action = action.lower()
@@ -535,7 +543,8 @@ class DummyDriver (Driver):
         geni_slivers = self.describe(urns, 'GENI 3', options)['geni_slivers']
         return geni_slivers
 
-    def shutdown (self, xrn, options={}):
+    def shutdown (self, xrn, options=None):
+        if options is None: options={}
         xrn = DummyXrn(xrn=xrn, type='slice')
         slicename = xrn.pl_slicename()
         slices = self.shell.GetSlices({'name': slicename}, ['slice_id'])
index cf5a6da..7ab94ba 100644 (file)
@@ -110,7 +110,8 @@ class DummySlices:
         return resulting_nodes
         
 
-    def verify_slice(self, slice_hrn, slice_record, expiration, options={}):
+    def verify_slice(self, slice_hrn, slice_record, expiration, options=None):
+        if options is None: options={}
         slicename = hrn_to_dummy_slicename(slice_hrn)
         parts = slicename.split("_")
         login_base = parts[0]
@@ -130,7 +131,8 @@ class DummySlices:
        
         return slice
 
-    def verify_users(self, slice_hrn, slice_record, users, options={}):
+    def verify_users(self, slice_hrn, slice_record, users, options=None):
+        if options is None: options={}
         slice_name = hrn_to_dummy_slicename(slice_hrn)
         users_by_email = {}
         for user in users:
@@ -162,7 +164,8 @@ class DummySlices:
             pass
             
 
-    def verify_keys(self, old_users, new_users, options={}):
+    def verify_keys(self, old_users, new_users, options=None):
+        if options is None: options={}
         # existing keys 
         existing_keys = []
         for user in old_users:
index 52acfad..7b456ee 100644 (file)
@@ -306,7 +306,7 @@ class IotlabAggregate:
         return rspec_node
 
 
-    def rspec_node_to_geni_sliver(self, rspec_node, sliver_allocations = {}):
+    def rspec_node_to_geni_sliver(self, rspec_node, sliver_allocations = None):
         """Makes a geni sliver structure from all the nodes allocated
         to slivers in the sliver_allocations dictionary. Returns the states
         of the sliver.
@@ -326,6 +326,7 @@ class IotlabAggregate:
         .. seealso:: node_to_rspec_node
 
         """
+        if sliver_allocations is None: sliver_allocations={}
         if rspec_node['sliver_id'] in sliver_allocations:
             # set sliver allocation and operational status
             sliver_allocation = sliver_allocations[rspec_node['sliver_id']]
@@ -400,7 +401,8 @@ class IotlabAggregate:
         return rspec_node
 
 
-    def get_leases(self, slice=None, options={}):
+    def get_leases(self, slice=None, options=None):
+        if options is None: options={}
         filter={}
         if slice:
            #filter.update({'name':slice['slice_name']}) # JORDAN: this is = "upmc" !!!
@@ -600,7 +602,7 @@ class IotlabAggregate:
                        FINAL RSPEC %s \r\n" % (rspec.toxml()))
         return rspec.toxml()
 
-    def get_slivers(self, urns, options={}):
+    def get_slivers(self, urns, options=None):
         """Get slivers of the given slice urns. Slivers contains slice, node and
         user information.
 
@@ -616,6 +618,7 @@ class IotlabAggregate:
         """
 
         SLICE_KEY = 'slice_hrn' # slice_hrn
+        if options is None: options={}
         slice_ids = set()
         node_ids = []
         for urn in urns:
@@ -729,7 +732,7 @@ class IotlabAggregate:
                 slivers.append(node)
         return slivers
 
-    def list_resources(self, version = None, options={}):
+    def list_resources(self, version = None, options=None):
         """
         Returns an advertisement Rspec of available resources at this
         aggregate. This Rspec contains a resource listing along with their
@@ -750,6 +753,7 @@ class IotlabAggregate:
         .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3#ListResources
         """
 
+        if options is None: options={}
         version_manager = VersionManager()
         version = version_manager.get_version(version)
         rspec_version = version_manager._get_version(version.type,
@@ -784,7 +788,7 @@ class IotlabAggregate:
         return rspec.toxml()
 
 
-    def describe(self, urns, version=None, options={}):
+    def describe(self, urns, version=None, options=None):
         """
         Retrieve a manifest RSpec describing the resources contained by the
         named entities, e.g. a single slice or a set of the slivers in a slice.
@@ -814,6 +818,7 @@ class IotlabAggregate:
         .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3#Describe
         .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3/CommonConcepts#urns
         """
+        if options is None: options={}
         version_manager = VersionManager()
         version = version_manager.get_version(version)
         rspec_version = version_manager._get_version(
index bbe362f..aaeb36b 100644 (file)
@@ -1102,7 +1102,7 @@ class IotlabDriver(Driver):
 
 
 
-    def delete(self, slice_urns, options={}):
+    def delete(self, slice_urns, options=None):
         """
         Deletes the lease associated with the slice hrn and the credentials
             if the slice belongs to iotlab. Answer to DeleteSliver.
@@ -1120,6 +1120,7 @@ class IotlabDriver(Driver):
         .. note:: creds are unused, and are not used either in the dummy driver
              delete_sliver .
         """
+        if options is None: options={}
         # collect sliver ids so we can update sliver allocation states after
         # we remove the slivers.
         aggregate = IotlabAggregate(self)
@@ -1412,16 +1413,19 @@ class IotlabDriver(Driver):
             'geni_ad_rspec_versions': ad_rspec_versions}
 
     # first 2 args are None in case of resource discovery
-    def list_resources (self, version=None, options={}):
+    def list_resources (self, version=None, options=None):
+        if options is None: options={}
         aggregate = IotlabAggregate(self)
         rspec =  aggregate.list_resources(version=version, options=options)
         return rspec
 
-    def describe(self, urns, version, options={}):
+    def describe(self, urns, version, options=None):
+        if options is None: options={}
         aggregate = IotlabAggregate(self)
         return aggregate.describe(urns, version=version, options=options)
 
-    def status (self, urns, options={}):
+    def status (self, urns, options=None):
+        if options is None: options={}
         aggregate = IotlabAggregate(self)
         desc =  aggregate.describe(urns, version='GENI 3')
         status = {'geni_urn': desc['geni_urn'],
@@ -1429,7 +1433,8 @@ class IotlabDriver(Driver):
         return status
 
 
-    def allocate (self, urn, rspec_string, expiration, options={}):
+    def allocate (self, urn, rspec_string, expiration, options=None):
+        if options is None: options={}
         xrn = Xrn(urn)
         aggregate = IotlabAggregate(self)
 
@@ -1598,7 +1603,8 @@ class IotlabDriver(Driver):
         }
         return aggregate.describe([xrn.get_urn()], version=rspec.version, options=describe_options)
 
-    def provision(self, urns, options={}):
+    def provision(self, urns, options=None):
+        if options is None: options={}
         # update users
         slices = IotlabSlices(self)
         aggregate = IotlabAggregate(self)
index 9449627..3b4258f 100644 (file)
@@ -403,7 +403,7 @@ class IotlabSlices:
         return sfa_slice
 
 
-    def verify_persons(self, slice_hrn, slice_record, users, options={}):
+    def verify_persons(self, slice_hrn, slice_record, users, options=None):
         """Ensures the users in users list exist and are enabled in LDAP. Adds
         person if needed (AddPerson).
 
@@ -429,6 +429,7 @@ class IotlabSlices:
 
 
         """
+        if options is None: options={}
         logger.debug("IOTLABSLICES \tverify_persons \tslice_hrn  %s  \
                     \t slice_record %s\r\n users %s \t  "
                      % (slice_hrn, slice_record, users))
@@ -639,10 +640,11 @@ class IotlabSlices:
         return added_persons
 
 
-    def verify_keys(self, persons, users, peer, options={}):
+    def verify_keys(self, persons, users, peer, options=None):
         """
         .. warning:: unused
         """
+        if options is None: options={}
         # existing keys
         key_ids = []
         for person in persons:
index 1521103..8b73644 100644 (file)
@@ -29,7 +29,8 @@ class AggregateManager:
             'geni_ad_rspec_versions': ad_rspec_versions,
             }
 
-    def get_rspec_version_string(self, rspec_version, options={}):
+    def get_rspec_version_string(self, rspec_version, options=None):
+        if options is None: options={}
         version_string = "rspec_%s" % (rspec_version)
 
         #panos adding the info option to the caching key (can be improved)
@@ -149,12 +150,14 @@ class AggregateManager:
 
         return api.driver.renew(xrns, expiration_time, options)
 
-    def PerformOperationalAction(self, api, xrns, creds, action, options={}):
+    def PerformOperationalAction(self, api, xrns, creds, action, options=None):
+        if options is None: options={}
         call_id = options.get('call_id')
         if Callids().already_handled(call_id): return True
         return api.driver.perform_operational_action(xrns, action, options) 
 
-    def Shutdown(self, api, xrn, creds, options={}):
+    def Shutdown(self, api, xrn, creds, options=None):
+        if options is None: options={}
         call_id = options.get('call_id')
         if Callids().already_handled(call_id): return True
         return api.driver.shutdown(xrn, options) 
index 0e8b71d..1985e0e 100644 (file)
@@ -78,7 +78,8 @@ class Driver:
 
     # answer to ListResources
     # returns : advertisment rspec (xml string)
-    def list_resources (self, version=None, options={}):
+    def list_resources (self, version=None, options=None):
+        if options is None: options={}
         return "dummy Driver.list_resources needs to be redefined"
 
     # the answer to Describe on a slice or a set of the slivers in a slice
@@ -97,40 +98,48 @@ class Driver:
     #              ...
     #                ]
     #}
-    def describe (self, urns, version, options={}):
+    def describe (self, urns, version, options=None):
+        if options is None: options={}
         return "dummy Driver.describe needs to be redefined"
 
     # the answer to Allocate on a given slicei or a set of the slivers in a slice
     # returns: same struct as for describe.
-    def allocate (self, urn, rspec_string, expiration, options={}):
+    def allocate (self, urn, rspec_string, expiration, options=None):
+        if options is None: options={}
         return "dummy Driver.allocate needs to be redefined"
 
     # the answer to Provision on a given slice or a set of the slivers in a slice
     # returns: same struct as for describe.
-    def provision(self, urns, options={}):
+    def provision(self, urns, options=None):
+        if options is None: options={}
         return "dummy Driver.provision needs to be redefined"
 
     # the answer to PerformOperationalAction on a given slice or a set of the slivers in a slice
     # returns: struct containing "geni_slivers" list of the struct returned by describe.
-    def perform_operational_action (self, urns, action, options={}):
+    def perform_operational_action (self, urns, action, options=None):
+        if options is None: options={}
         return "dummy Driver.perform_operational_action needs to be redefined"
 
     # the answer to Status on a given slice or a set of the slivers in a slice
     # returns: struct containing "geni_urn" and "geni_slivers" list of the struct returned by describe.
-    def status (self, urns, options={}): 
+    def status (self, urns, options=None): 
+        if options is None: options={}
         return "dummy Driver.status needs to be redefined"
 
     # the answer to Renew on a given slice or a set of the slivers in a slice
     # returns: struct containing "geni_slivers" list of the struct returned by describe.
-    def renew (self, urns, expiration_time, options={}):
+    def renew (self, urns, expiration_time, options=None):
+        if options is None: options={}
         return "dummy Driver.renew needs to be redefined"
 
     # the answer to Delete on a given slice
     # returns: struct containing "geni_slivers" list of the struct returned by describe.
-    def delete(self, urns, options={}):
+    def delete(self, urns, options=None):
+        if options is None: options={}
         return "dummy Driver.delete needs to be redefined"
 
     # the answer to Shutdown on a given slice
     # returns: boolean
-    def shutdown (self, xrn, options={}):
+    def shutdown (self, xrn, options=None):
+        if options is None: options={}
         return False
index 7306380..6d7bb6d 100644 (file)
@@ -33,7 +33,7 @@ from sqlalchemy.orm.collections import InstrumentedList
 # * write operations (register, update) need e.g. 
 #   'researcher' or 'pi' to be set - reg-* are just ignored
 #
-# the 'normalize' helper functions below aim at ironing this out
+# the '_normalize_input' helper functions below aim at ironing this out
 # however in order to break as few code as possible we essentially make sure that *both* fields are set
 # upon entering the write methods (so again register and update) for legacy, as some driver code
 # might depend on the presence of, say, 'researcher'
@@ -48,16 +48,21 @@ def _normalize_input (record, reg_key, driver_key):
         # and issue a warning if they were both set and different
         # as we're overwriting some user data here
         if driver_key in record:
-            logger.warning ("normalize_input_researcher: incoming record has both values, using reg-researchers")
+            logger.warning ("normalize_input: incoming record has both values, using %s"%reg_key)
         record[driver_key]=record[reg_key]
     # we only have one key set, duplicate for the other one
     elif driver_key in record:
-        logger.warning ("normalize_input_researcher: you should use '%s' instead ot '%s'"%(reg_key,driver_key))
+        logger.warning ("normalize_input: you should use '%s' instead of '%s'"%(reg_key,driver_key))
         record[reg_key]=record[driver_key]
 
 def normalize_input_record (record):
     _normalize_input (record, 'reg-researchers','researcher')
     _normalize_input (record, 'reg-pis','pi')
+    _normalize_input (record, 'reg-keys','keys')
+    # xxx the keys thing could use a little bit more attention:
+    # some parts of the code are using 'keys' while they should use 'reg-keys' 
+    # but I run out of time for now
+    if 'reg-keys' in record: record['keys']=record['reg-keys']
     return record
 
 class RegistryManager:
@@ -71,8 +76,7 @@ class RegistryManager:
                        if hrn != api.hrn])
         xrn=Xrn(api.hrn,type='authority')
         return version_core({'interface':'registry',
-                             'sfa': 2,
-                             'geni_api': 2,
+                             'sfa': 3,
                              'hrn':xrn.get_hrn(),
                              'urn':xrn.get_urn(),
                              'peers':peers})
@@ -237,7 +241,8 @@ class RegistryManager:
     
         return records
     
-    def List (self, api, xrn, origin_hrn=None, options={}):
+    def List (self, api, xrn, origin_hrn=None, options=None):
+        if options is None: options={}
         dbsession=api.dbsession()
         # load all know registry names into a prefix tree and attempt to find
         # the longest matching prefix
@@ -357,11 +362,10 @@ class RegistryManager:
         if not record.gid:
             uuid = create_uuid()
             pkey = Keypair(create=True)
-            if getattr(record,'keys',None):
-                pub_key=record.keys
+            pub_key=getattr(record,'reg-keys',None)
+            if pub_key is not None:
                 # use only first key in record
-                if isinstance(record.keys, types.ListType):
-                    pub_key = record.keys[0]
+                if pub_key and isinstance(pub_key, types.ListType): pub_key = pub_key[0]
                 pkey = convert_public_key(pub_key)
     
             gid_object = api.auth.hierarchy.create_gid(urn, uuid, pkey)
@@ -388,9 +392,12 @@ class RegistryManager:
         
         elif isinstance (record, RegUser):
             # create RegKey objects for incoming keys
-            if hasattr(record,'keys'): 
-                logger.debug ("creating %d keys for user %s"%(len(record.keys),record.hrn))
-                record.reg_keys = [ RegKey (key) for key in record.keys ]
+            if hasattr(record,'reg-keys'):
+                keys=getattr(record,'reg-keys')
+                # some people send the key as a string instead of a list of strings
+                if isinstance(keys,types.StringTypes): keys=[keys]
+                logger.debug ("creating %d keys for user %s"%(len(keys),record.hrn))
+                record.reg_keys = [ RegKey (key) for key in keys ]
             
         # update testbed-specific data if needed
         pointer = api.driver.register (record.__dict__, hrn, pub_key)
index 05b0f1e..2a99b6f 100644 (file)
@@ -508,7 +508,8 @@ class SliceManager:
         multiclient.get_results()    
         return 1
      
-    def Shutdown(self, api, xrn, creds, options={}):
+    def Shutdown(self, api, xrn, creds, options=None):
+        if options is None: options={}
         xrn = Xrn(xrn)  
         # get the callers hrn
         valid_cred = api.auth.checkCredentials(creds, 'stopslice', xrn.hrn)[0]
index 22dc13b..a7dc8f9 100644 (file)
@@ -45,6 +45,8 @@ class Allocate(Method):
         # the slivers should expire.
         expiration = datetime_to_string(the_credential.expiration)
         
+        self.api.logger.debug("Allocate, received expiration from credential: %s"%expiration)
+
         # make sure request is not empty
         slivers = RSpec(rspec).version.get_nodes_with_slivers()
         if not slivers:
index cb682e4..f043992 100644 (file)
@@ -15,6 +15,7 @@ class GetVersion(Method):
     returns = Parameter(dict, "Version information")
 
     # API v2 specifies options is optional, so..
-    def call(self, options={}):
+    def call(self, options=None):
+        if options is None: options={}
         self.api.logger.info("interface: %s\tmethod-name: %s" % (self.api.interface, self.name))
         return self.api.manager.GetVersion(self.api, options)
index d53a0a5..83d7a6e 100644 (file)
@@ -25,7 +25,8 @@ class List(Method):
     # xxx used to be [SfaRecord]
     returns = [Parameter(dict, "registry record")]
     
-    def call(self, xrn, creds, options={}):
+    def call(self, xrn, creds, options=None):
+        if options is None: options={}
         hrn, type = urn_to_hrn(xrn)
         valid_creds = self.api.auth.checkCredentials(creds, 'list')
 
index f3a6e67..dc34f75 100644 (file)
@@ -30,7 +30,8 @@ class Resolve(Method):
     # xxx used to be [SfaRecord]
     returns = [Parameter(dict, "registry record")]
     
-    def call(self, xrns, creds, options={}):
+    def call(self, xrns, creds, options=None):
+        if options is None: options={}
         # use details=False by default, only when explicitly specified do we want 
         # to mess with the testbed details
         if 'details' in options: details=options['details']
index bb7c56d..832a2c7 100644 (file)
@@ -68,7 +68,9 @@ class NitosAggregate:
        
 
 
-    def get_nodes(self, slice_xrn, slice=None,slivers={}, options={}):
+    def get_nodes(self, slice_xrn, slice=None,slivers=None, options=None):
+        if slivers is None: slivers={}
+        if options is None: options={}
         # if we are dealing with a slice that has no node just return 
         # and empty list    
         if slice_xrn:
@@ -126,8 +128,9 @@ class NitosAggregate:
             rspec_nodes.append(rspec_node)
         return rspec_nodes 
 
-    def get_leases_and_channels(self, slice=None, slice_xrn=None,  options={}):
-        
+    def get_leases_and_channels(self, slice=None, slice_xrn=None,  options=None):
+
+        if options is None: options={}
         slices = self.driver.shell.getSlices({}, [])
         nodes = self.driver.shell.getNodes({}, [])
         leases = self.driver.shell.getReservedNodes({}, [])
@@ -216,8 +219,9 @@ class NitosAggregate:
         return (rspec_leases, rspec_channels)
 
 
-    def get_channels(self, slice=None, options={}):
+    def get_channels(self, slice=None, options=None):
+        if options is None: options={}
+
         all_channels = self.driver.shell.getChannels({}, [])
         channels = []
         if slice:
@@ -245,7 +249,8 @@ class NitosAggregate:
 
 
     
-    def get_rspec(self, slice_xrn=None, version = None, options={}):
+    def get_rspec(self, slice_xrn=None, version = None, options=None):
+        if options is None: options={}
 
         version_manager = VersionManager()
         version = version_manager.get_version(version)
index 3eac8aa..875a5a9 100644 (file)
@@ -153,7 +153,8 @@ class NitosSlices:
 
                         
         
-    def verify_slice(self, slice_hrn, slice_record, sfa_peer, options={}):
+    def verify_slice(self, slice_hrn, slice_record, sfa_peer, options=None):
+        if options is None: options={}
         slicename = hrn_to_nitos_slicename(slice_hrn)
         slices = self.driver.shell.getSlices({}, []) 
         slices = self.driver.filter_nitos_results(slices, {'slice_name': slicename})
@@ -168,7 +169,8 @@ class NitosSlices:
        
         return slice
 
-    def verify_users(self, slice_hrn, slice_record, users, sfa_peer, options={}):
+    def verify_users(self, slice_hrn, slice_record, users, sfa_peer, options=None):
+        if options is None: options={}
         # get slice info
         slicename = hrn_to_nitos_slicename(slice_hrn)
         slices = self.driver.shell.getSlices({}, [])
@@ -204,7 +206,8 @@ class NitosSlices:
         return added_users
 
 
-    def verify_keys(self, persons, users, options={}):
+    def verify_keys(self, persons, users, options=None):
+        if options is None: options={}
         # existing keys 
         key_ids = []
         for person in persons:
index 54aaf50..555b1b9 100644 (file)
@@ -4,7 +4,8 @@ from sfa.rspecs.elements.disk_image import DiskImage
 
 class Image:
     
-    def __init__(self, image={}):
+    def __init__(self, image=None):
+        if image is None: image={}
         self.id = None
         self.container_format = None
         self.kernel_id = None
index e36946e..39ea2f9 100644 (file)
@@ -355,23 +355,27 @@ class NovaDriver(Driver):
         return {}
 
     # first 2 args are None in case of resource discovery
-    def list_resources (self, version=None, options={}):
+    def list_resources (self, version=None, options=None):
+        if options is None: options={}
         aggregate = OSAggregate(self)
         rspec =  aggregate.list_resources(version=version, options=options)
         return rspec
 
-    def describe(self, urns, version=None, options={}):
+    def describe(self, urns, version=None, options=None):
+        if options is None: options={}
         aggregate = OSAggregate(self)
         return aggregate.describe(urns, version=version, options=options)
     
-    def status (self, urns, options={}):
+    def status (self, urns, options=None):
+        if options is None: options={}
         aggregate = OSAggregate(self)
         desc =  aggregate.describe(urns)
         status = {'geni_urn': desc['geni_urn'],
                   'geni_slivers': desc['geni_slivers']}
         return status
 
-    def allocate (self, urn, rspec_string, expiration, options={}):
+    def allocate (self, urn, rspec_string, expiration, options=None):
+        if options is None: options={}
         xrn = Xrn(urn) 
         aggregate = OSAggregate(self)
 
@@ -401,7 +405,8 @@ class NovaDriver(Driver):
    
         return aggregate.describe(urns=[urn], version=rspec.version)
 
-    def provision(self, urns, options={}):
+    def provision(self, urns, options=None):
+        if options is None: options={}
         # update sliver allocation states and set them to geni_provisioned
         aggregate = OSAggregate(self)
         instances = aggregate.get_instances(urns)
@@ -415,7 +420,8 @@ class NovaDriver(Driver):
         rspec_version = version_manager.get_version(options['geni_rspec_version'])
         return self.describe(urns, rspec_version, options=options) 
 
-    def delete (self, urns, options={}):
+    def delete (self, urns, options=None):
+        if options is None: options={}
         # collect sliver ids so we can update sliver allocation states after
         # we remove the slivers.
         aggregate = OSAggregate(self)
@@ -441,11 +447,13 @@ class NovaDriver(Driver):
                  'geni_expires': None})        
         return geni_slivers
 
-    def renew (self, urns, expiration_time, options={}):
+    def renew (self, urns, expiration_time, options=None):
+        if options is None: options={}
         description = self.describe(urns, None, options)
         return description['geni_slivers']
 
-    def perform_operational_action  (self, urns, action, options={}):
+    def perform_operational_action  (self, urns, action, options=None):
+        if options is None: options={}
         aggregate = OSAggregate(self)
         action = action.lower() 
         if action == 'geni_start':
@@ -474,7 +482,8 @@ class NovaDriver(Driver):
         geni_slivers = self.describe(urns, None, options)['geni_slivers']
         return geni_slivers
 
-    def shutdown(self, xrn, options={}):
+    def shutdown(self, xrn, options=None):
+        if options is None: options={}
         xrn = OSXrn(xrn=xrn, type='slice')
         tenant_name = xrn.get_tenant_name()
         name = xrn.get_slicename()
index d6d7367..2b65399 100644 (file)
@@ -8,7 +8,7 @@ import time
 from collections import defaultdict
 from nova.exception import ImageNotFound
 from nova.api.ec2.cloud import CloudController
-from sfa.util.faults import SfaAPIError, SliverDoesNotExist
+from sfa.util.faults import SliverDoesNotExist
 from sfa.util.sfatime import utcparse, datetime_to_string, datetime_to_epoch
 from sfa.rspecs.rspec import RSpec
 from sfa.rspecs.elements.hardware_type import HardwareType
@@ -58,7 +58,8 @@ class OSAggregate:
             zones = [zone.name for zone in zones]
         return zones
 
-    def list_resources(self, version=None, options={}):
+    def list_resources(self, version=None, options=None):
+        if options is None: options={}
         version_manager = VersionManager()
         version = version_manager.get_version(version)
         rspec_version = version_manager._get_version(version.type, version.version, 'ad')
@@ -67,7 +68,8 @@ class OSAggregate:
         rspec.version.add_nodes(nodes)
         return rspec.toxml()
 
-    def describe(self, urns, version=None, options={}):
+    def describe(self, urns, version=None, options=None):
+        if options is None: options={}
         # update nova connection
         tenant_name = OSXrn(xrn=urns[0], type='slice').get_tenant_name()
         self.driver.shell.nova_manager.connect(tenant=tenant_name)
@@ -211,7 +213,8 @@ class OSAggregate:
                          'storage':  str(instance.disk)})
         return sliver   
 
-    def instance_to_geni_sliver(self, instance, sliver_allocations = {}):
+    def instance_to_geni_sliver(self, instance, sliver_allocations=None):
+        if sliver_allocations is None: sliver_allocations={}
         sliver_hrn = '%s.%s' % (self.driver.hrn, instance.id)
         sliver_id = Xrn(sliver_hrn, type='sliver').urn
  
@@ -302,7 +305,8 @@ class OSAggregate:
         return key_name       
         
 
-    def create_security_group(self, slicename, fw_rules=[]):
+    def create_security_group(self, slicename, fw_rules=None):
+        if fw_rules is None: fw_rules=[]
         # use default group by default
         group_name = 'default' 
         if isinstance(fw_rules, list) and fw_rules:
index cae6495..2876694 100644 (file)
@@ -31,7 +31,8 @@ class PlAggregate:
     def __init__(self, driver):
         self.driver = driver
 
-    def get_nodes(self, options={}):
+    def get_nodes(self, options=None):
+        if options is None: options={}
         filter = {'peer_id': None}
         geni_available = options.get('geni_available')    
         if geni_available == True:
@@ -40,13 +41,15 @@ class PlAggregate:
        
         return nodes  
  
-    def get_sites(self, filter={}):
+    def get_sites(self, filter=None):
+        if filter is None: filter={}
         sites = {}
         for site in self.driver.shell.GetSites(filter):
             sites[site['site_id']] = site
         return sites
 
-    def get_interfaces(self, filter={}):
+    def get_interfaces(self, filter=None):
+        if filter is None: filter={}
         interfaces = {}
         for interface in self.driver.shell.GetInterfaces(filter):
             iface = Interface()
@@ -98,20 +101,23 @@ class PlAggregate:
 
         return links
 
-    def get_node_tags(self, filter={}):
+    def get_node_tags(self, filter=None):
+        if filter is None: filter={}
         node_tags = {}
         for node_tag in self.driver.shell.GetNodeTags(filter):
             node_tags[node_tag['node_tag_id']] = node_tag
         return node_tags
 
-    def get_pl_initscripts(self, filter={}):
+    def get_pl_initscripts(self, filter=None):
+        if filter is None: filter={}
         pl_initscripts = {}
         filter.update({'enabled': True})
         for initscript in self.driver.shell.GetInitScripts(filter):
             pl_initscripts[initscript['initscript_id']] = initscript
         return pl_initscripts
 
-    def get_slivers(self, urns, options={}):
+    def get_slivers(self, urns, options=None):
+        if options is None: options={}
         names = set()
         slice_ids = set()
         node_ids = []
@@ -193,7 +199,9 @@ class PlAggregate:
             slivers.append(node)
         return slivers
 
-    def node_to_rspec_node(self, node, sites, interfaces, node_tags, pl_initscripts=[], grain=None, options={}):
+    def node_to_rspec_node(self, node, sites, interfaces, node_tags, pl_initscripts=None, grain=None, options=None):
+        if pl_initscripts is None: pl_initscripts=[]
+        if options is None: options={}
         rspec_node = NodeElement()
         # xxx how to retrieve site['login_base']
         site=sites[node['site_id']]
@@ -286,7 +294,8 @@ class PlAggregate:
             tags_dict[tag['node_id']] = tag
         return tags_dict
 
-    def get_slice_nodes(self, slice, options={}):
+    def get_slice_nodes(self, slice, options=None):
+        if options is None: options={}
         nodes_dict = {}
         filter = {'peer_id': None}
         tags_filter = {}
@@ -304,7 +313,8 @@ class PlAggregate:
             nodes_dict[node['node_id']] = node
         return nodes_dict
 
-    def rspec_node_to_geni_sliver(self, rspec_node, sliver_allocations = {}):
+    def rspec_node_to_geni_sliver(self, rspec_node, sliver_allocations=None):
+        if sliver_allocations is None: sliver_allocations={}
         if rspec_node['sliver_id'] in sliver_allocations:
             # set sliver allocation and operational status
             sliver_allocation = sliver_allocations[rspec_node['sliver_id']]
@@ -333,7 +343,8 @@ class PlAggregate:
                        }
         return geni_sliver        
 
-    def get_leases(self, slice=None, options={}):
+    def get_leases(self, slice=None, options=None):
+        if options is None: options={}
         
         now = int(time.time())
         filter={}
@@ -370,7 +381,8 @@ class PlAggregate:
         return rspec_leases
 
     
-    def list_resources(self, version = None, options={}):
+    def list_resources(self, version = None, options=None):
+        if options is None: options={}
 
         version_manager = VersionManager()
         version = version_manager.get_version(version)
@@ -410,7 +422,8 @@ class PlAggregate:
 
         return rspec.toxml()
 
-    def describe(self, urns, version=None, options={}):
+    def describe(self, urns, version=None, options=None):
+        if options is None: options={}
         version_manager = VersionManager()
         version = version_manager.get_version(version)
         rspec_version = version_manager._get_version(version.type, version.version, 'manifest')
index 1c59fc9..53f1256 100644 (file)
@@ -627,23 +627,27 @@ class PlDriver (Driver):
         return {}
 
     # first 2 args are None in case of resource discovery
-    def list_resources (self, version=None, options={}):
+    def list_resources (self, version=None, options=None):
+        if options is None: options={}
         aggregate = PlAggregate(self)
         rspec =  aggregate.list_resources(version=version, options=options)
         return rspec
 
-    def describe(self, urns, version, options={}):
+    def describe(self, urns, version, options=None):
+        if options is None: options={}
         aggregate = PlAggregate(self)
         return aggregate.describe(urns, version=version, options=options)
     
-    def status (self, urns, options={}):
+    def status (self, urns, options=None):
+        if options is None: options={}
         aggregate = PlAggregate(self)
         desc =  aggregate.describe(urns, version='GENI 3')
         status = {'geni_urn': desc['geni_urn'],
                   'geni_slivers': desc['geni_slivers']}
         return status
 
-    def allocate (self, urn, rspec_string, expiration, options={}):
+    def allocate (self, urn, rspec_string, expiration, options=None):
+        if options is None: options={}
         xrn = Xrn(urn)
         aggregate = PlAggregate(self)
         slices = PlSlices(self)
@@ -680,7 +684,8 @@ class PlDriver (Driver):
 
         return aggregate.describe([xrn.get_urn()], version=rspec.version)
 
-    def provision(self, urns, options={}):
+    def provision(self, urns, options=None):
+        if options is None: options={}
         # update users
         slices = PlSlices(self)
         aggregate = PlAggregate(self)
@@ -715,7 +720,8 @@ class PlDriver (Driver):
         rspec_version = version_manager.get_version(options['geni_rspec_version']) 
         return self.describe(urns, rspec_version, options=options)
 
-    def delete(self, urns, options={}):
+    def delete(self, urns, options=None):
+        if options is None: options={}
         # collect sliver ids so we can update sliver allocation states after
         # we remove the slivers.
         aggregate = PlAggregate(self)
@@ -754,7 +760,8 @@ class PlDriver (Driver):
                  'geni_expires': datetime_to_string(utcparse(sliver['expires']))})  
         return geni_slivers
 
-    def renew (self, urns, expiration_time, options={}):
+    def renew (self, urns, expiration_time, options=None):
+        if options is None: options={}
         aggregate = PlAggregate(self)
         slivers = aggregate.get_slivers(urns)
         if not slivers:
@@ -767,7 +774,8 @@ class PlDriver (Driver):
         return description['geni_slivers']
             
 
-    def perform_operational_action (self, urns, action, options={}):
+    def perform_operational_action (self, urns, action, options=None):
+        if options is None: options={}
         # MyPLC doesn't support operational actions. Lets pretend like it
         # supports start, but reject everything else.
         action = action.lower()
@@ -787,7 +795,8 @@ class PlDriver (Driver):
         return geni_slivers
 
     # set the 'enabled' tag to 0
-    def shutdown (self, xrn, options={}):
+    def shutdown (self, xrn, options=None):
+        if options is None: options={}
         hrn, _ = urn_to_hrn(xrn)
         top_auth_hrn = top_auth(hrn)
         site_hrn = '.'.join(hrn.split('.')[:-1])
index b6cec88..1226f12 100644 (file)
@@ -322,7 +322,9 @@ class PlSlices:
                         
         
 
-    def verify_site(self, slice_xrn, slice_record={}, sfa_peer=None, options={}):
+    def verify_site(self, slice_xrn, slice_record=None, sfa_peer=None, options=None):
+        if slice_record is None: slice_record={}
+        if options is None: options={}
         (slice_hrn, type) = urn_to_hrn(slice_xrn)
         top_auth_hrn = top_auth(slice_hrn)
         site_hrn = '.'.join(slice_hrn.split('.')[:-1])
@@ -367,7 +369,8 @@ class PlSlices:
         return site
 
 
-    def verify_slice(self, slice_hrn, slice_record, sfa_peer, expiration, options={}):
+    def verify_slice(self, slice_hrn, slice_record, sfa_peer, expiration, options=None):
+        if options is None: options={}
         top_auth_hrn = top_auth(slice_hrn)
         site_hrn = '.'.join(slice_hrn.split('.')[:-1])
         slice_part = slice_hrn.split('.')[-1]
@@ -416,7 +419,8 @@ class PlSlices:
         return self.driver.shell.GetSlices(int(slice['slice_id']))[0]
 
 
-    def verify_persons(self, slice_hrn, slice_record, users, sfa_peer, options={}):
+    def verify_persons(self, slice_hrn, slice_record, users, sfa_peer, options=None):
+        if options is None: options={}
         top_auth_hrn = top_auth(slice_hrn)
         site_hrn = '.'.join(slice_hrn.split('.')[:-1])
         slice_part = slice_hrn.split('.')[-1]
@@ -504,7 +508,8 @@ class PlSlices:
         return persons_to_add
 
 
-    def verify_keys(self, persons_to_verify_keys, options={}):
+    def verify_keys(self, persons_to_verify_keys, options=None):
+        if options is None: options={}
         # we only add keys that comes from sfa to persons in PL
         for person_id in persons_to_verify_keys:
              person_sfa_keys = persons_to_verify_keys[person_id].get('keys', [])
@@ -518,7 +523,8 @@ class PlSlices:
                   self.driver.shell.AddPersonKey(int(person_id), key)
 
 
-    def verify_slice_attributes(self, slice, requested_slice_attributes, options={}, admin=False):
+    def verify_slice_attributes(self, slice, requested_slice_attributes, options=None, admin=False):
+        if options is None: options={}
         append = options.get('append', True)
         # get list of attributes users ar able to manage
         filter = {'category': '*slice*'}
index 7f79e81..36ad12f 100644 (file)
@@ -2,7 +2,8 @@ class Element(dict):
 
     fields = {}
 
-    def __init__(self, fields={}, element=None, keys=None):
+    def __init__(self, fields=None, element=None, keys=None):
+        if fields is None: fields={}
         self.element = element
         dict.__init__(self, dict.fromkeys(self.fields))
         if not keys:
index eebb1ae..bfc503a 100644 (file)
@@ -29,7 +29,8 @@ class Iotlabv1Lease:
 
 
     @staticmethod
-    def get_leases(xml, filter={}):
+    def get_leases(xml, filter=None):
+        if filter is None: filter={}
         xpath = '//lease%s | //default:lease%s' % (XpathFilter.xpath(filter), XpathFilter.xpath(filter))
         lease_elems = xml.xpath(xpath)
         return Iotlabv1Lease.get_lease_objs(lease_elems)
index af6fe2a..49f7cfd 100644 (file)
@@ -160,14 +160,16 @@ class Iotlabv1Node:
         return node_elems
 
     @staticmethod
-    def get_nodes(xml, filter={}):
+    def get_nodes(xml, filter=None):
+        if filter is None: filter={}
         xpath = '//node%s | //default:node%s' % (XpathFilter.xpath(filter), \
                                                     XpathFilter.xpath(filter))
         node_elems = xml.xpath(xpath)
         return Iotlabv1Node.get_node_objs(node_elems)
 
     @staticmethod
-    def get_nodes_with_slivers(xml, sliver_filter={}):
+    def get_nodes_with_slivers(xml, sliver_filter=None):
+        if sliver_filter is None: sliver_filter={}
 
         xpath = '//node[count(sliver)>0] | \
                                 //default:node[count(default:sliver) > 0]'
index f26ace6..0f9fb01 100644 (file)
@@ -35,7 +35,8 @@ class Iotlabv1Sliver:
                     for (key, value) in attrib_dict.items():
                         attrib_elem.set(key, value)
     @staticmethod
-    def get_slivers(xml, filter={}):
+    def get_slivers(xml, filter=None):
+        if filter is None: filter={}
         xpath = './default:sliver | ./sliver'
 
         sliver_elems = xml.xpath(xpath)
@@ -54,5 +55,6 @@ class Iotlabv1Sliver:
         return slivers
 
     @staticmethod
-    def get_sliver_attributes(xml, filter={}):
-        return []
\ No newline at end of file
+    def get_sliver_attributes(xml, filter=None):
+        if filter is None: filter={}
+        return []
index 60582e3..cf4a5f6 100644 (file)
@@ -54,7 +54,8 @@ class NITOSv1Channel:
 
 
     @staticmethod
-    def get_channels(xml, filter={}):
+    def get_channels(xml, filter=None):
+        if filter is None: filter={}
         xpath = '//channel%s | //default:channel%s' % (XpathFilter.xpath(filter), XpathFilter.xpath(filter))
         channel_elems = xml.xpath(xpath)
         return NITOSv1Channel.get_channel_objs(channel_elems)
index 99e815a..dd3041c 100644 (file)
@@ -73,7 +73,8 @@ class NITOSv1Lease:
             
 
     @staticmethod
-    def get_leases(xml, filter={}):
+    def get_leases(xml, filter=None):
+        if filter is None: filter={}
         xpath = '//lease%s | //default:lease%s' % (XpathFilter.xpath(filter), XpathFilter.xpath(filter))
         lease_elems = xml.xpath(xpath)
         return NITOSv1Lease.get_lease_objs(lease_elems)
index 44b9b52..ea59b3d 100644 (file)
@@ -135,7 +135,8 @@ class NITOSv1Node:
                     node.element.remove(sliver.element)
         
     @staticmethod
-    def get_nodes(xml, filter={}):
+    def get_nodes(xml, filter=None):
+        if filter is None: filter={}
         xpath = '//node%s | //default:node%s' % (XpathFilter.xpath(filter), XpathFilter.xpath(filter))
         node_elems = xml.xpath(xpath)
         return NITOSv1Node.get_node_objs(node_elems)
index 7d03fe0..ea34ff4 100644 (file)
@@ -9,7 +9,8 @@ class NITOSv1PLTag:
             pl_tag_elem.set_text(value)
               
     @staticmethod
-    def get_pl_tags(xml, ignore=[]):
+    def get_pl_tags(xml, ignore=None):
+        if ignore is None: ignore=[]
         pl_tags = []
         for elem in xml.iterchildren():
             if elem.tag not in ignore:
index 0f40211..feac887 100644 (file)
@@ -43,7 +43,8 @@ class NITOSv1Sliver:
         return attribs 
                 
     @staticmethod
-    def get_slivers(xml, filter={}):
+    def get_slivers(xml, filter=None):
+        if filter is None: filter={}
         xpath = './default:sliver | ./sliver'
         sliver_elems = xml.xpath(xpath)
         slivers = []
index 07520ef..f4cf74d 100644 (file)
@@ -39,7 +39,8 @@ class Ofeliav1Port:
         return attribs 
                 
     @staticmethod
-    def get_ports(xml, filter={}):
+    def get_ports(xml, filter=None):
+        if filter is None: filter={}
         xpath = './openflow:port | ./port'
         port_elems = xml.xpath(xpath)
         ports = []
index 86a3800..a184973 100644 (file)
@@ -21,7 +21,8 @@ from sfa.rspecs.elements.versions.ofeliav1Port import Ofeliav1Port
 class Ofeliav1Datapath:
 
     @staticmethod
-    def get_datapaths(xml, filter={}):
+    def get_datapaths(xml, filter=None):
+        if filter is None: filter={}
         #xpath = '//datapath%s | //default:datapath%s' % (XpathFilter.xpath(filter), XpathFilter.xpath(filter))
         xpath = '//datapath%s | //openflow:datapath%s' % (XpathFilter.xpath(filter), XpathFilter.xpath(filter))
         datapath_elems = xml.xpath(xpath)
@@ -144,7 +145,8 @@ class Ofeliav1Datapath:
 #                    node.element.remove(sliver.element)
 #        
 #    @staticmethod
-#    def get_nodes(xml, filter={}):
+#    def get_nodes(xml, filter=None):
+#        if filter is None: filter={}
 #        xpath = '//node%s | //default:node%s' % (XpathFilter.xpath(filter), XpathFilter.xpath(filter))
 #        node_elems = xml.xpath(xpath)
 #        return SFAv1Node.get_node_objs(node_elems)
index 3fc2eb2..83a2096 100644 (file)
@@ -8,7 +8,8 @@ from sfa.rspecs.elements.link import Link
 class Ofeliav1Link:
 
     @staticmethod
-    def get_links(xml, filter={}):
+    def get_links(xml, filter=None):
+        if filter is None: filter={}
         xpath = '//link%s | //openflow:link%s' % (XpathFilter.xpath(filter), XpathFilter.xpath(filter))
         link_elems = xml.xpath(xpath)
         return Ofeliav1Link.get_link_objs(link_elems)
index 51363de..4a6df82 100644 (file)
@@ -13,7 +13,8 @@ class PGv2DiskImage:
             xml.add_instance('disk_image', image, DiskImage.fields)
     
     @staticmethod
-    def get_images(xml, filter={}):
+    def get_images(xml, filter=None):
+        if filter is None: filter={}
         xpath = './default:disk_image | ./disk_image'
         image_elems = xml.xpath(xpath)
         images = []
index 68c44f0..b04f7dc 100644 (file)
@@ -51,7 +51,8 @@ class PGv2Lease:
 
 
     @staticmethod
-    def get_leases(xml, filter={}):
+    def get_leases(xml, filter=None):
+        if filter is None: filter={}
         xpath = '//lease%s | //default:lease%s' % (XpathFilter.xpath(filter), XpathFilter.xpath(filter))
         lease_elems = xml.xpath(xpath)
         return PGv2Lease.get_lease_objs(lease_elems)
index d553d21..60447b0 100644 (file)
@@ -82,13 +82,15 @@ class PGv2Node:
 
 
     @staticmethod
-    def get_nodes(xml, filter={}):
+    def get_nodes(xml, filter=None):
+        if filter is None: filter={}
         xpath = '//node%s | //default:node%s' % (XpathFilter.xpath(filter), XpathFilter.xpath(filter))
         node_elems = xml.xpath(xpath)
         return PGv2Node.get_node_objs(node_elems)
 
     @staticmethod
-    def get_nodes_with_slivers(xml, filter={}):
+    def get_nodes_with_slivers(xml, filter=None):
+        if filter is None: filter={}
         xpath = '//node[count(sliver_type)>0] | //default:node[count(default:sliver_type) > 0]' 
         node_elems = xml.xpath(xpath)        
         return PGv2Node.get_node_objs(node_elems)
index 1f3ec0c..3ad687f 100644 (file)
@@ -40,7 +40,8 @@ class PGv2SliverType:
                     for (key, value) in attrib_dict.items():
                         attrib_elem.set(key, value)                
     @staticmethod
-    def get_slivers(xml, filter={}):
+    def get_slivers(xml, filter=None):
+        if filter is None: filter={}
         xpath = './default:sliver_type | ./sliver_type'
         sliver_elems = xml.xpath(xpath)
         slivers = []
@@ -56,5 +57,6 @@ class PGv2SliverType:
         return slivers
 
     @staticmethod
-    def get_sliver_attributes(xml, filter={}):
+    def get_sliver_attributes(xml, filter=None):
+        if filter is None: filter={}
         return []             
index 039d2d1..0c7cb26 100644 (file)
@@ -72,7 +72,8 @@ class SFAv1Lease:
 
 
     @staticmethod
-    def get_leases(xml, filter={}):
+    def get_leases(xml, filter=None):
+        if filter is None: filter={}
         xpath = '//lease%s | //default:lease%s' % (XpathFilter.xpath(filter), XpathFilter.xpath(filter))
         lease_elems = xml.xpath(xpath)
         return SFAv1Lease.get_lease_objs(lease_elems)
index 5107698..1931a58 100644 (file)
@@ -125,7 +125,8 @@ class SFAv1Node:
                     node.element.remove(sliver.element)
         
     @staticmethod
-    def get_nodes(xml, filter={}):
+    def get_nodes(xml, filter=None):
+        if filter is None: filter={}
         xpath = '//node%s | //default:node%s' % (XpathFilter.xpath(filter), XpathFilter.xpath(filter))
         node_elems = xml.xpath(xpath)
         return SFAv1Node.get_node_objs(node_elems)
index b523124..907c962 100644 (file)
@@ -9,7 +9,8 @@ class SFAv1PLTag:
             pl_tag_elem.set_text(value)
               
     @staticmethod
-    def get_pl_tags(xml, ignore=[]):
+    def get_pl_tags(xml, ignore=None):
+        if ignore is None: ignore=[]
         pl_tags = []
         for elem in xml.iterchildren():
             if elem.tag not in ignore:
index a2b07a1..7e9282f 100644 (file)
@@ -39,7 +39,8 @@ class SFAv1Sliver:
         return attribs 
                 
     @staticmethod
-    def get_slivers(xml, filter={}):
+    def get_slivers(xml, filter=None):
+        if filter is None: filter={}
         xpath = './default:sliver | ./sliver'
         sliver_elems = xml.xpath(xpath)
         slivers = []
index 8a66ff3..ce16a1d 100755 (executable)
@@ -10,13 +10,15 @@ from sfa.rspecs.version_manager import VersionManager
 
 class RSpec:
  
-    def __init__(self, rspec="", version=None, user_options={}):
+    def __init__(self, rspec="", version=None, user_options=None, ttl=60):
+        if user_options is None: user_options={}
         self.header = '<?xml version="1.0"?>\n'
         self.template = """<RSpec></RSpec>"""
         self.version = None
         self.xml = XML()
         self.version_manager = VersionManager()
         self.user_options = user_options
+        self.ttl = ttl
         self.elements = {}
         if rspec:
             if version:
@@ -29,16 +31,17 @@ class RSpec:
         else:
             raise InvalidRSpec("No RSpec or version specified. Must specify a valid rspec string or a valid version") 
 
-    def create(self, version=None):
+    def create(self, version=None, ttl=60):
         """
         Create root element
+        ttl: time to live in minutes, this will determine the expires tag of the RSpec
         """
         self.version = self.version_manager.get_version(version)
         self.namespaces = self.version.namespaces
         self.parse_xml(self.version.template, self.version) 
         now = datetime.utcnow()
         generated_ts = now.strftime(SFATIME_FORMAT)
-        expires_ts = (now + timedelta(hours=1)).strftime(SFATIME_FORMAT) 
+        expires_ts = (now + timedelta(minutes=self.ttl)).strftime(SFATIME_FORMAT) 
         self.xml.set('expires', expires_ts)
         self.xml.set('generated', generated_ts)
 
@@ -72,15 +75,17 @@ class RSpec:
             raise InvalidRSpecElement(element_type, extra=msg)
         return self.elements[element_type]
 
-    def get(self, element_type, filter={}, depth=0):
+    def get(self, element_type, filter=None, depth=0):
+        if filter is None: filter={}
         elements = self.get_elements(element_type, filter)
         elements = [self.xml.get_element_attributes(elem, depth=depth) for elem in elements]
         return elements
 
-    def get_elements(self, element_type, filter={}):
+    def get_elements(self, element_type, filter=None):
         """
         search for a registered element
         """
+        if filter is None: filter={}
         if element_type not in self.elements:
             msg = "Unable to search for element %s in rspec, expath expression not found." % \
                    element_type
index 9d8045f..ad49157 100644 (file)
@@ -139,7 +139,8 @@ class Iotlabv1(RSpecVersion):
     def add_default_sliver_attribute(self, name, value, network=None):
         pass
 
-    def add_slivers(self, hostnames, attributes=[], sliver_urn=None, append=False):
+    def add_slivers(self, hostnames, attributes=None, sliver_urn=None, append=False):
+        if attributes is None: attributes=[]
         # all nodes hould already be present in the rspec. Remove all
         # nodes that done have slivers
         print>>sys.stderr, "\r\n \r\n \r\n \t\t\t Iotlabv1.PY add_slivers  ----->get_node "
index af60d8e..3288b48 100644 (file)
@@ -60,7 +60,8 @@ class NITOSv1(RSpecVersion):
 
     # Slivers
    
-    def add_slivers(self, hostnames, attributes=[], sliver_urn=None, append=False):
+    def add_slivers(self, hostnames, attributes=None, sliver_urn=None, append=False):
+        if attributes is None: attributes=[]
         # add slice name to network tag
         network_tags = self.xml.xpath('//network')
         if network_tags:
index cd206ff..d074694 100755 (executable)
@@ -86,7 +86,8 @@ class Ofelia(RSpecVersion):
 
     # Slivers
    
-    def add_slivers(self, hostnames, attributes=[], sliver_urn=None, append=False):
+    def add_slivers(self, hostnames, attributes=None, sliver_urn=None, append=False):
+        if attributes is None: attributes=[]
         # add slice name to network tag
         network_tags = self.xml.xpath('//network')
         if network_tags:
index 80febc9..21183bf 100644 (file)
@@ -103,7 +103,8 @@ class PGv2(RSpecVersion):
     def add_default_sliver_attribute(self, name, value, network=None):
         pass
 
-    def add_slivers(self, hostnames, attributes=[], sliver_urn=None, append=False):
+    def add_slivers(self, hostnames, attributes=None, sliver_urn=None, append=False):
+        if attributes is None: attributes=[]
         # all nodes hould already be present in the rspec. Remove all
         # nodes that done have slivers
         for hostname in hostnames:
index 4ee8a4c..6e973e7 100644 (file)
@@ -59,7 +59,8 @@ class SFAv1(RSpecVersion):
 
     # Slivers
    
-    def add_slivers(self, hostnames, attributes=[], sliver_urn=None, append=False):
+    def add_slivers(self, hostnames, attributes=None, sliver_urn=None, append=False):
+        if attributes is None: attributes=[]
         # add slice name to network tag
         network_tags = self.xml.xpath('//network')
         if network_tags:
index d50d3b6..7c74977 100644 (file)
@@ -410,7 +410,8 @@ def drop_tables(engine):
 
 ##############################
 # create a record of the right type from either a dict or an xml string
-def make_record (dict={}, xml=""):
+def make_record (dict=None, xml=""):
+    if dict is None: dict={}
     if dict:    return make_record_dict (dict)
     elif xml:   return make_record_xml (xml)
     else:       raise Exception("make_record has no input")
index 812efde..9fcab19 100644 (file)
@@ -35,7 +35,8 @@ class Record:
     
     # it may be important to exclude relationships, which fortunately
     # 
-    def todict (self, exclude_types=[]):
+    def todict (self, exclude_types=None):
+        if exclude_types is None: exclude_types=[]
         d=self.__dict__
         def exclude (k,v):
             if k.startswith('_'): return True
index fdb6829..407f405 100644 (file)
@@ -21,8 +21,9 @@
 # IN THE WORK.
 #----------------------------------------------------------------------
 
-from sfa.trust.credential import Credential, append_sub
+from sfa.trust.credential import Credential, append_sub, DEFAULT_CREDENTIAL_LIFETIME
 from sfa.util.sfalogging import logger
+from sfa.util.sfatime import SFATIME_FORMAT
 
 from StringIO import StringIO
 from xml.dom.minidom import Document, parseString
@@ -161,7 +162,7 @@ class ABACCredential(Credential):
         filename=self.get_filename()
         if filename: result += "Filename %s\n"%filename
         if self.expiration:
-            result +=  "\texpiration: %s \n" % self.expiration.isoformat()
+            result +=  "\texpiration: %s \n" % self.expiration.strftime(SFATIME_FORMAT)
 
         result += "\tHead: %s\n" % self.get_head() 
         for tail in self.get_tails():
@@ -257,7 +258,7 @@ class ABACCredential(Credential):
         if self.expiration.tzinfo is not None and self.expiration.tzinfo.utcoffset(self.expiration) is not None:
             # TZ aware. Make sure it is UTC
             self.expiration = self.expiration.astimezone(tz.tzutc())
-        append_sub(doc, cred, "expires", self.expiration.strftime('%Y-%m-%dT%H:%M:%SZ')) # RFC3339
+        append_sub(doc, cred, "expires", self.expiration.strftime(SFATIME_FORMAT)) # RFC3339
 
         abac = doc.createElement("abac")
         rt0 = doc.createElement("rt0")
index 0b9f081..59ca4c2 100644 (file)
@@ -2,6 +2,7 @@
 # SfaAPI authentication 
 #
 import sys
+from types import StringTypes
 
 from sfa.util.faults import InsufficientRights, MissingCallerGID, MissingTrustedRoots, PermissionError, \
     BadRequestHash, ConnectionKeyGIDMismatch, SfaPermissionDenied, CredentialNotVerifiable, Forbidden, \
@@ -56,9 +57,13 @@ class Auth:
                          speaking_for_xrn=None):
         if xrns is None: xrns=[]
         def log_invalid_cred(cred):
-            cred_obj=Credential(string=cred)
-            logger.debug("failed to validate credential - dump=%s"%cred_obj.dump_string(dump_parents=True))
-            error = sys.exc_info()[:2]
+            if not isinstance (cred, StringTypes):
+                logger.info("cannot validate credential %s - expecting a string"%cred)
+                error="checkCredentials: expected a string, received %s"%(type(cred))
+            else:
+                cred_obj=Credential(string=cred)
+                logger.info("failed to validate credential - dump=%s"%cred_obj.dump_string(dump_parents=True))
+                error = sys.exc_info()[:2]
             return error
 
         # if xrns are specified they cannot be None or empty string
index 54334f2..9d0fd28 100644 (file)
@@ -44,14 +44,13 @@ from xml.parsers.expat import ExpatError
 
 from sfa.util.faults import CredentialNotVerifiable, ChildRightsNotSubsetOfParent
 from sfa.util.sfalogging import logger
-from sfa.util.sfatime import utcparse
-from sfa.trust.credential_legacy import CredentialLegacy
+from sfa.util.sfatime import utcparse, SFATIME_FORMAT
 from sfa.trust.rights import Right, Rights, determine_rights
 from sfa.trust.gid import GID
 from sfa.util.xrn import urn_to_hrn, hrn_authfor_hrn
 
-# 2 weeks, in seconds 
-DEFAULT_CREDENTIAL_LIFETIME = 86400 * 31
+# 31 days, in seconds 
+DEFAULT_CREDENTIAL_LIFETIME = 86400 * 28
 
 
 # TODO:
@@ -200,9 +199,9 @@ class Signature(object):
 # A credential provides a caller gid with privileges to an object gid.
 # A signed credential is signed by the object's authority.
 #
-# Credentials are encoded in one of two ways.  The legacy style places
-# it in the subjectAltName of an X509 certificate.  The new credentials
-# are placed in signed XML.
+# Credentials are encoded in one of two ways. 
+# The legacy style (now unsupported) places it in the subjectAltName of an X509 certificate.
+# The new credentials are placed in signed XML.
 #
 # WARNING:
 # In general, a signed credential obtained externally should
@@ -248,7 +247,6 @@ class Credential(object):
         self.signature = None
         self.xml = None
         self.refid = None
-        self.legacy = None
         self.type = None
         self.version = None
 
@@ -263,16 +261,16 @@ class Credential(object):
                 self.version = cred['geni_version']
                 
 
-        # Check if this is a legacy credential, translate it if so
         if string or filename:
             if string:                
                 str = string
             elif filename:
                 str = file(filename).read()
                 
-            if str.strip().startswith("-----"):
-                self.legacy = CredentialLegacy(False,string=str)
-                self.translate_legacy(str)
+            # if this is a legacy credential, write error and bail out
+            if isinstance (str, StringTypes) and str.strip().startswith("-----"):
+                logger.error("Legacy credentials not supported any more - giving up with %s..."%str[:10])
+                return
             else:
                 self.xml = str
                 self.decode()
@@ -312,24 +310,6 @@ class Credential(object):
         self.signature = sig
 
         
-    ##
-    # Translate a legacy credential into a new one
-    #
-    # @param String of the legacy credential
-
-    def translate_legacy(self, str):
-        legacy = CredentialLegacy(False,string=str)
-        self.gidCaller = legacy.get_gid_caller()
-        self.gidObject = legacy.get_gid_object()
-        lifetime = legacy.get_lifetime()
-        if not lifetime:
-            self.set_expiration(datetime.datetime.utcnow() + datetime.timedelta(seconds=DEFAULT_CREDENTIAL_LIFETIME))
-        else:
-            self.set_expiration(int(lifetime))
-        self.lifeTime = legacy.get_lifetime()
-        self.set_privileges(legacy.get_privileges())
-        self.get_privileges().delegate_all_privileges(legacy.get_delegate())
-
     ##
     # Need the issuer's private key and name
     # @param key Keypair object containing the private key of the issuer
@@ -384,15 +364,11 @@ class Credential(object):
     # Expiration: an absolute UTC time of expiration (as either an int or string or datetime)
     # 
     def set_expiration(self, expiration):
-        if isinstance(expiration, (int, float)):
-            self.expiration = datetime.datetime.fromtimestamp(expiration)
-        elif isinstance (expiration, datetime.datetime):
-            self.expiration = expiration
-        elif isinstance (expiration, StringTypes):
-            self.expiration = utcparse (expiration)
+        expiration_datetime = utcparse (expiration)
+        if expiration_datetime is not None:
+            self.expiration = expiration_datetime
         else:
-            logger.error ("unexpected input type in Credential.set_expiration")
-
+            logger.error ("unexpected input %s in Credential.set_expiration"%expiration)
 
     ##
     # get the lifetime of the credential (always in datetime format)
@@ -403,11 +379,6 @@ class Credential(object):
         # at this point self.expiration is normalized as a datetime - DON'T call utcparse again
         return self.expiration
 
-    ##
-    # For legacy sake
-    def get_lifetime(self):
-        return self.get_expiration()
     ##
     # set the privileges
     #
@@ -483,9 +454,10 @@ class Credential(object):
         append_sub(doc, cred, "target_urn", self.gidObject.get_urn())
         append_sub(doc, cred, "uuid", "")
         if not self.expiration:
+            logger.debug("Creating credential valid for %s s"%DEFAULT_CREDENTIAL_LIFETIME)
             self.set_expiration(datetime.datetime.utcnow() + datetime.timedelta(seconds=DEFAULT_CREDENTIAL_LIFETIME))
         self.expiration = self.expiration.replace(microsecond=0)
-        append_sub(doc, cred, "expires", self.expiration.isoformat())
+        append_sub(doc, cred, "expires", self.expiration.strftime(SFATIME_FORMAT))
         privileges = doc.createElement("privileges")
         cred.appendChild(privileges)
 
@@ -679,10 +651,6 @@ class Credential(object):
 
         self.xml = signed
 
-        # This is no longer a legacy credential
-        if self.legacy:
-            self.legacy = None
-
         # Update signatures
         self.decode()       
 
@@ -799,7 +767,7 @@ class Credential(object):
             self.decode()
 
         # validate against RelaxNG schema
-        if HAVELXML and not self.legacy:
+        if HAVELXML:
             if schema and os.path.exists(schema):
                 tree = etree.parse(StringIO(self.xml))
                 schema_doc = etree.parse(schema)
@@ -828,18 +796,9 @@ class Credential(object):
                     logger.error("Failed to load trusted cert from %s: %r"%( f, exc))
             trusted_certs = ok_trusted_certs
 
-        # Use legacy verification if this is a legacy credential
-        if self.legacy:
-            self.legacy.verify_chain(trusted_cert_objects)
-            if self.legacy.client_gid:
-                self.legacy.client_gid.verify_chain(trusted_cert_objects)
-            if self.legacy.object_gid:
-                self.legacy.object_gid.verify_chain(trusted_cert_objects)
-            return True
-        
         # make sure it is not expired
         if self.get_expiration() < datetime.datetime.utcnow():
-            raise CredentialNotVerifiable("Credential %s expired at %s" % (self.get_summary_tostring(), self.expiration.isoformat()))
+            raise CredentialNotVerifiable("Credential %s expired at %s" % (self.get_summary_tostring(), self.expiration.strftime(SFATIME_FORMAT)))
 
         # Verify the signatures
         filename = self.save_to_random_tmp_file()
@@ -1101,7 +1060,7 @@ class Credential(object):
             self.get_signature().get_issuer_gid().dump(8, dump_parents)
 
         if self.expiration:
-            print "  expiration:", self.expiration.isoformat()
+            print "  expiration:", self.expiration.strftime(SFATIME_FORMAT)
 
         gidObject = self.get_gid_object()
         if gidObject:
diff --git a/sfa/trust/credential_legacy.py b/sfa/trust/credential_legacy.py
deleted file mode 100644 (file)
index b5fc449..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-#----------------------------------------------------------------------
-# Copyright (c) 2008 Board of Trustees, Princeton University
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and/or hardware specification (the "Work") to
-# deal in the Work without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Work, and to permit persons to whom the Work
-# is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Work.
-#
-# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
-# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
-# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
-# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
-# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS 
-# IN THE WORK.
-#----------------------------------------------------------------------
-##
-# Implements SFA Credentials
-#
-# Credentials are layered on top of certificates, and are essentially a
-# certificate that stores a tuple of parameters.
-##
-
-
-import xmlrpclib
-
-from sfa.util.faults import MissingDelegateBit, ChildRightsNotSubsetOfParent
-from sfa.trust.certificate import Certificate
-from sfa.trust.gid import GID
-
-##
-# Credential is a tuple:
-#     (GIDCaller, GIDObject, LifeTime, Privileges, Delegate)
-#
-# These fields are encoded using xmlrpc into the subjectAltName field of the
-# x509 certificate. Note: Call encode() once the fields have been filled in
-# to perform this encoding.
-
-class CredentialLegacy(Certificate):
-    gidCaller = None
-    gidObject = None
-    lifeTime = None
-    privileges = None
-    delegate = False
-
-    ##
-    # Create a Credential object
-    #
-    # @param create If true, create a blank x509 certificate
-    # @param subject If subject!=None, create an x509 cert with the subject name
-    # @param string If string!=None, load the credential from the string
-    # @param filename If filename!=None, load the credential from the file
-
-    def __init__(self, create=False, subject=None, string=None, filename=None):
-        Certificate.__init__(self, create, subject, string, filename)
-
-    ##
-    # set the GID of the caller
-    #
-    # @param gid GID object of the caller
-
-    def set_gid_caller(self, gid):
-        self.gidCaller = gid
-        # gid origin caller is the caller's gid by default
-        self.gidOriginCaller = gid
-
-    ##
-    # get the GID of the object
-
-    def get_gid_caller(self):
-        if not self.gidCaller:
-            self.decode()
-        return self.gidCaller
-
-    ##
-    # set the GID of the object
-    #
-    # @param gid GID object of the object
-
-    def set_gid_object(self, gid):
-        self.gidObject = gid
-
-    ##
-    # get the GID of the object
-
-    def get_gid_object(self):
-        if not self.gidObject:
-            self.decode()
-        return self.gidObject
-
-    ##
-    # set the lifetime of this credential
-    #
-    # @param lifetime lifetime of credential
-
-    def set_lifetime(self, lifeTime):
-        self.lifeTime = lifeTime
-
-    ##
-    # get the lifetime of the credential
-
-    def get_lifetime(self):
-        if not self.lifeTime:
-            self.decode()
-        return self.lifeTime
-
-    ##
-    # set the delegate bit
-    #
-    # @param delegate boolean (True or False)
-
-    def set_delegate(self, delegate):
-        self.delegate = delegate
-
-    ##
-    # get the delegate bit
-
-    def get_delegate(self):
-        if not self.delegate:
-            self.decode()
-        return self.delegate
-
-    ##
-    # set the privileges
-    #
-    # @param privs either a comma-separated list of privileges of a Rights object
-
-    def set_privileges(self, privs):
-        if isinstance(privs, str):
-            self.privileges = Rights(string = privs)
-        else:
-            self.privileges = privs
-
-    ##
-    # return the privileges as a Rights object
-
-    def get_privileges(self):
-        if not self.privileges:
-            self.decode()
-        return self.privileges
-
-    ##
-    # determine whether the credential allows a particular operation to be
-    # performed
-    #
-    # @param op_name string specifying name of operation ("lookup", "update", etc)
-
-    def can_perform(self, op_name):
-        rights = self.get_privileges()
-        if not rights:
-            return False
-        return rights.can_perform(op_name)
-
-    ##
-    # Encode the attributes of the credential into a string and store that
-    # string in the alt-subject-name field of the X509 object. This should be
-    # done immediately before signing the credential.
-
-    def encode(self):
-        dict = {"gidCaller": None,
-                "gidObject": None,
-                "lifeTime": self.lifeTime,
-                "privileges": None,
-                "delegate": self.delegate}
-        if self.gidCaller:
-            dict["gidCaller"] = self.gidCaller.save_to_string(save_parents=True)
-        if self.gidObject:
-            dict["gidObject"] = self.gidObject.save_to_string(save_parents=True)
-        if self.privileges:
-            dict["privileges"] = self.privileges.save_to_string()
-        str = xmlrpclib.dumps((dict,), allow_none=True)
-        self.set_data('URI:http://' + str)
-
-    ##
-    # Retrieve the attributes of the credential from the alt-subject-name field
-    # of the X509 certificate. This is automatically done by the various
-    # get_* methods of this class and should not need to be called explicitly.
-
-    def decode(self):
-        data = self.get_data().lstrip('URI:http://')
-        
-        if data:
-            dict = xmlrpclib.loads(data)[0][0]
-        else:
-            dict = {}
-
-        self.lifeTime = dict.get("lifeTime", None)
-        self.delegate = dict.get("delegate", None)
-
-        privStr = dict.get("privileges", None)
-        if privStr:
-            self.privileges = Rights(string = privStr)
-        else:
-            self.privileges = None
-
-        gidCallerStr = dict.get("gidCaller", None)
-        if gidCallerStr:
-            self.gidCaller = GID(string=gidCallerStr)
-        else:
-            self.gidCaller = None
-
-        gidObjectStr = dict.get("gidObject", None)
-        if gidObjectStr:
-            self.gidObject = GID(string=gidObjectStr)
-        else:
-            self.gidObject = None
-
-    ##
-    # Verify that a chain of credentials is valid (see cert.py:verify). In
-    # addition to the checks for ordinary certificates, verification also
-    # ensures that the delegate bit was set by each parent in the chain. If
-    # a delegate bit was not set, then an exception is thrown.
-    #
-    # Each credential must be a subset of the rights of the parent.
-
-    def verify_chain(self, trusted_certs = None):
-        # do the normal certificate verification stuff
-        Certificate.verify_chain(self, trusted_certs)
-
-        if self.parent:
-            # make sure the parent delegated rights to the child
-            if not self.parent.get_delegate():
-                raise MissingDelegateBit(self.parent.get_subject())
-
-            # make sure the rights given to the child are a subset of the
-            # parents rights
-            if not self.parent.get_privileges().is_superset(self.get_privileges()):
-                raise ChildRightsNotSubsetOfParent(self.get_subject() 
-                                                   + " " + self.parent.get_privileges().save_to_string()
-                                                   + " " + self.get_privileges().save_to_string())
-
-        return
-
-    ##
-    # Dump the contents of a credential to stdout in human-readable format
-    #
-    # @param dump_parents If true, also dump the parent certificates
-
-    def dump(self, *args, **kwargs):
-        print self.dump_string(*args,**kwargs)
-
-    def dump_string(self, dump_parents=False):
-        result=""
-        result += "CREDENTIAL %s\n" % self.get_subject()
-
-        result += "      privs: %s\n" % self.get_privileges().save_to_string()
-
-        gidCaller = self.get_gid_caller()
-        if gidCaller:
-            result += "  gidCaller:\n"
-            gidCaller.dump(8, dump_parents)
-
-        gidObject = self.get_gid_object()
-        if gidObject:
-            result += "  gidObject:\n"
-            result += gidObject.dump_string(8, dump_parents)
-
-        result += "   delegate: %s" % self.get_delegate()
-
-        if self.parent and dump_parents:
-            result += "PARENT\n"
-            result += self.parent.dump_string(dump_parents)
-
-        return result
index 9a3b3c3..2c56a47 100644 (file)
@@ -31,6 +31,8 @@ import tempfile
 from xml.dom.minidom import *
 from StringIO import StringIO
 
+from sfa.util.sfatime import SFATIME_FORMAT
+
 from sfa.trust.certificate import Certificate
 from sfa.trust.credential import Credential, signature_template, HAVELXML
 from sfa.trust.abac_credential import ABACCredential, ABACElement
@@ -129,7 +131,7 @@ def verify_speaks_for(cred, tool_gid, speaking_for_urn,
 
     # Credential has not expired
     if cred.expiration and cred.expiration < datetime.datetime.utcnow():
-        return False, None, "ABAC Credential expired at %s (%s)" % (cred.expiration.isoformat(), cred.get_summary_tostring())
+        return False, None, "ABAC Credential expired at %s (%s)" % (cred.expiration.strftime(SFATIME_FORMAT), cred.get_summary_tostring())
 
     # Must be ABAC
     if cred.get_cred_type() != ABACCredential.ABAC_CREDENTIAL_TYPE:
@@ -349,7 +351,7 @@ def create_speaks_for(tool_gid, user_gid, ma_gid, \
 
     credential_duration = datetime.timedelta(days=dur_days)
     expiration = datetime.datetime.utcnow() + credential_duration
-    expiration_str = expiration.strftime('%Y-%m-%dT%H:%M:%SZ') # FIXME: libabac can't handle .isoformat()
+    expiration_str = expiration.strftime(SFATIME_FORMAT)
     version = "1.1"
 
     user_keyid = get_cert_keyid(user_gid)
index c25ec44..797bed7 100644 (file)
@@ -194,7 +194,8 @@ DO NOT EDIT. This file was automatically generated at
             return False
 
 
-    def dump(self, sections = []):
+    def dump(self, sections=None):
+        if sections is None: sections=[]
         sys.stdout.write(output_python())
 
     def output_python(self, encoding = "utf-8"):
index 27418b2..75a2e4a 100644 (file)
 # IN THE WORK.
 #----------------------------------------------------------------------
 from types import StringTypes
-import dateutil.parser
-import datetime
 import time
+import datetime
+import dateutil.parser
+import calendar
 import re
 
 from sfa.util.sfalogging import logger
@@ -77,14 +78,16 @@ For safety this can also handle inputs that are either timestamps, or datetimes
     else:
         logger.error("Unexpected type in utcparse [%s]"%type(input))
 
-def datetime_to_string(input):
-    return datetime.datetime.strftime(input, SFATIME_FORMAT)
+def datetime_to_string(dt):
+    return datetime.datetime.strftime(dt, SFATIME_FORMAT)
 
-def datetime_to_utc(input):
-    return time.gmtime(datetime_to_epoch(input))
+def datetime_to_utc(dt):
+    return time.gmtime(datetime_to_epoch(dt))
 
-def datetime_to_epoch(input):
-    return int(time.mktime(input.timetuple()))
+# see https://docs.python.org/2/library/time.html 
+# all timestamps are in UTC so time.mktime() would be *wrong*
+def datetime_to_epoch(dt):
+    return int(calendar.timegm(dt.timetuple()))
 
 def add_datetime(input, days=0, hours=0, minutes=0, seconds=0):
     """
@@ -94,6 +97,10 @@ def add_datetime(input, days=0, hours=0, minutes=0, seconds=0):
     return dt + datetime.timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds)
 
 if __name__ == '__main__':
+        # checking consistency
+    print 20*'X'
+    print ("Should be close to zero: %s"%(datetime_to_epoch(datetime.datetime.utcnow())-time.time()))
+    print 20*'X'
     for input in [
             '+2d',
             '+3w',
index 793a38e..89a2509 100644 (file)
@@ -9,8 +9,8 @@ class SimpleStorage(dict):
     db_filename = None
     type = 'dict'
     
-    def __init__(self, db_filename, db = {}):
-
+    def __init__(self, db_filename, db = None):
+        if db is None: db={}
         dict.__init__(self, db)
         self.db_filename = db_filename
     
index 46b31d3..97ae6c4 100644 (file)
@@ -3,7 +3,8 @@ version_tag="@VERSIONTAG@"
 scm_url="@SCMURL@"
 import socket
  
-def version_core (more={}):
+def version_core (more=None):
+    if more is None: more={}
     core = { 'code_tag' : version_tag,
              'code_url' : scm_url,
              'hostname' : socket.gethostname(),
index d6734e6..ba324c7 100755 (executable)
@@ -20,7 +20,8 @@ class XpathFilter:
         return xpath
 
     @staticmethod
-    def xpath(filter={}):
+    def xpath(filter=None):
+        if filter is None: filter={}
         xpath = ""
         if filter:
             filter_list = []
@@ -78,11 +79,12 @@ class XmlElement:
     def getparent(self):
         return XmlElement(self.element.getparent(), self.namespaces)
 
-    def get_instance(self, instance_class=None, fields=[]):
+    def get_instance(self, instance_class=None, fields=None):
         """
         Returns an instance (dict) of this xml element. The instance
         holds a reference to this xml element.   
         """
+        if fields is None: fields=[]
         if not instance_class:
             instance_class = Element
         if not fields and hasattr(instance_class, 'fields'):
@@ -97,11 +99,12 @@ class XmlElement:
                    instance[field] = self.attrib[field]  
         return instance             
 
-    def add_instance(self, name, instance, fields=[]):
+    def add_instance(self, name, instance, fields=None):
         """
         Adds the specifed instance(s) as a child element of this xml 
         element. 
         """
+        if fields is None: fields=[]
         if not fields and hasattr(instance, 'keys'):
             fields = instance.keys()
         elem = self.add_element(name)
index b0db4c1..b16ea51 100644 (file)
@@ -110,7 +110,8 @@ class Xrn:
         return Xrn.urn_meaningful(urn).split('+')
 
     @staticmethod
-    def filter_type(urns=[], type=None):
+    def filter_type(urns=None, type=None):
+        if urns is None: urns=[]
         urn_list = []
         if not type:
             return urns
index dd58205..72b1e80 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<RSpec type="SFA" expires="2013-02-27T15:14:10Z" generated="2013-02-27T14:14:10Z">
+<RSpec type="SFA" expires="2014-52-27T15:14:10Z" generated="2013-05-19T14:14:10Z">
   <network name="iotlab">
     <node component_manager_id="urn:publicid:IDN+iotlab+authority+sa" component_id="urn:publicid:IDN+iotlab+node+wsn430-12.devlille.iot-lab.info" boot_state="Alive" component_name="wsn430-12.devlille.iot-lab.info" site_id="urn:publicid:IDN+senslab+authority+sa">
       <hostname>wsn430-12.devlille.iot-lab.info</hostname>
@@ -16,7 +16,7 @@
       <sliver/>
     </node>
   </network>
- <lease slice_id="urn:publicid:IDN+iotlab+slice+sandrine_slice" start_time="1405078836" duration="20">
+ <lease slice_id="urn:publicid:IDN+ple:upmc+slice+myslicedemo" start_time="1400604923" duration="20">
        <node component_id="urn:publicid:IDN+iotlab+node+a8-11.devgrenoble.iot-lab.info"/>
        <node component_id="urn:publicid:IDN+iotlab+node+wsn430-12.devlille.iot-lab.info"/>
  </lease>