Merge branch 'tmp-pdf'
authorThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Fri, 29 Jun 2012 08:58:54 +0000 (10:58 +0200)
committerThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Fri, 29 Jun 2012 08:58:54 +0000 (10:58 +0200)
18 files changed:
sfa/client/sfi.py
sfa/generic/fd.py
sfa/managers/slice_manager.py
sfa/methods/RenewSliver.py
sfa/openstack/nova_driver.py
sfa/openstack/osaggregate.py
sfa/openstack/osxrn.py [new file with mode: 0644]
sfa/planetlab/plaggregate.py
sfa/planetlab/pldriver.py
sfa/planetlab/plslices.py
sfa/rspecs/elements/lease.py
sfa/rspecs/elements/versions/pgv2Interface.py [new file with mode: 0644]
sfa/rspecs/elements/versions/pgv2Node.py
sfa/rspecs/elements/versions/sfav1Lease.py
sfa/storage/migrations/versions/002_authority_pis.py
sfa/storage/model.py
sfatables/runtime.py
sfatables/xmlrule.py

index c8082dc..a8a012c 100644 (file)
@@ -356,6 +356,9 @@ class Sfi:
                             help="type filter ([all]|user|slice|authority|node|aggregate)",
                             choices=("all", "user", "slice", "authority", "node", "aggregate"),
                             default="all")
+        if command in ("show"):
+            parser.add_option("-k","--key",dest="keys",action="append",default=[],
+                              help="specify specific keys to be displayed from record")
         if command in ("resources"):
             # rspec version
             parser.add_option("-r", "--rspec-version", dest="rspec_version", default="SFA 1",
@@ -454,7 +457,9 @@ class Sfi:
         
 
     def print_help (self):
+        print "==================== Generic sfi usage"
         self.sfi_parser.print_help()
+        print "==================== Specific command usage"
         self.command_parser.print_help()
 
     #
@@ -491,9 +496,8 @@ class Sfi:
             self.dispatch(command, command_options, command_args)
         except KeyError:
             self.logger.critical ("Unknown command %s"%command)
-            raise
             sys.exit(1)
-    
+
         return
     
     ####################
@@ -824,6 +828,16 @@ or version information about sfi itself
         record_dicts = filter_records(options.type, record_dicts)
         if not record_dicts:
             self.logger.error("No record of type %s"% options.type)
+            return
+        # user has required to focus on some keys
+        if options.keys:
+            def project (record):
+                projected={}
+                for key in options.keys:
+                    try: projected[key]=record[key]
+                    except: pass
+                return projected
+            record_dicts = [ project (record) for record in record_dicts ]
         records = [ Record(dict=record_dict) for record_dict in record_dicts ]
         for record in records:
             if (options.format == "text"):      record.dump(sort=True)  
@@ -1185,21 +1199,23 @@ or with an slice hrn, shows currently provisioned resources
         renew slice (RenewSliver)
         """
         server = self.sliceapi()
+        if len(args) != 2:
+            self.print_help()
+            sys.exit(1)
+        [ slice_hrn, input_time ] = args
         # slice urn    
-        slice_hrn = args[0]
         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
+        # time: don't try to be smart on the time format, server-side will
         # creds
         slice_cred = self.slice_credential_string(args[0])
         creds = [slice_cred]
         if options.delegate:
             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
             creds.append(delegated_cred)
-        # time
-        time = args[1]
         # options and call_id when supported
         api_options = {}
        api_options['call_id']=unique_call_id()
-        result =  server.RenewSliver(slice_urn, creds, time, *self.ois(server,api_options))
+        result =  server.RenewSliver(slice_urn, creds, input_time, *self.ois(server,api_options))
         value = ReturnValue.get_value(result)
         if self.options.raw:
             save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
index 2ba52fd..1001d5b 100644 (file)
@@ -3,9 +3,10 @@ from sfa.generic.pl import pl
 
 import sfa.federica.fddriver
 
+# the federica flavour behaves like pl, except for 
+# the driver
+
 class fd (pl):
 
-# the max flavour behaves like pl, except for 
-# the aggregate
     def driver_class (self) :
         return sfa.federica.fddriver.FdDriver
index b261fe2..02729b0 100644 (file)
@@ -265,12 +265,14 @@ class SliceManager:
             try:
                 result=server.RenewSliver(xrn, creds, expiration_time, options)
                 if type(result)!=dict:
-                    result = {"code": {"geni_code": 0}, value: result}
-                result["aggregate"] = aggregate
+                    result = {'code': {'geni_code': 0}, 'value': result}
+                result['aggregate'] = aggregate
                 return result
             except:
                 logger.log_exc('Something wrong in _RenewSliver with URL %s'%server.url)
-                return {"aggregate": aggregate, "exc_info": traceback.format_exc(), "code": {"geni_code": -1}, "value": False, "output": ""}
+                return {'aggregate': aggregate, 'exc_info': traceback.format_exc(),
+                        'code': {'geni_code': -1},
+                        'value': False, 'output': ""}
 
         (hrn, urn_type) = urn_to_hrn(xrn)
         # get the callers hrn
@@ -294,14 +296,14 @@ class SliceManager:
         results = threads.get_results()
 
         geni_code = 0
-        geni_output = ",".join([x.get("output","") for x in results])
-        geni_value = reduce (lambda x,y: x and y, [result.get("value",False) for result in results], True)
+        geni_output = ",".join([x.get('output',"") for x in results])
+        geni_value = reduce (lambda x,y: x and y, [result.get('value',False) for result in results], True)
         for agg_result in results:
-            agg_geni_code = agg_result["code"].get("geni_code",0)
+            agg_geni_code = agg_result['code'].get('geni_code',0)
             if agg_geni_code:
                 geni_code = agg_geni_code
 
-        results = {"aggregates": results, "code": {"geni_code": geni_code}, "value": geni_value, "output": geni_output}
+        results = {'aggregates': results, 'code': {'geni_code': geni_code}, 'value': geni_value, 'output': geni_output}
 
         return results
 
@@ -363,7 +365,14 @@ class SliceManager:
     
         # mmh, it is expected that all results carry the same urn
         overall['geni_urn'] = results[0]['geni_urn']
-        overall['pl_login'] = results[0]['pl_login']
+        overall['pl_login'] = None
+        for result in results:
+            if result.get('pl_login'):
+                overall['pl_login'] = result['pl_login']
+                break
+            elif isinstance(result.get('value'), dict) and result['value'].get('pl_login'):
+                overall['pl_login'] = result['value']['pl_login']
+                break
         # append all geni_resources
         overall['geni_resources'] = \
             reduce (lambda x,y: x+y, [ result['geni_resources'] for result in results] , [])
index c503b55..c64b884 100644 (file)
@@ -42,5 +42,5 @@ class RenewSliver(Method):
             raise InsufficientRights('Renewsliver: Credential expires before requested expiration time')
         if requested_time > datetime.datetime.utcnow() + datetime.timedelta(days=max_renew_days):
             raise Exception('Cannot renew > %s days from now' % max_renew_days)
-        return self.api.manager.RenewSliver(self.api, slice_xrn, valid_creds, expiration_time, options)    
+        return self.api.manager.RenewSliver(self.api, slice_xrn, valid_creds, expiration_time, options)
     
index e4b95b0..48c0511 100644 (file)
@@ -9,6 +9,8 @@ from sfa.util.sfalogging import logger
 from sfa.util.defaultdict import defaultdict
 from sfa.util.sfatime import utcparse, datetime_to_string, datetime_to_epoch
 from sfa.util.xrn import Xrn, hrn_to_urn, get_leaf, urn_to_sliver_id
+from sfa.planetlab.plxrn import PlXrn
+from sfa.openstack.osxrn import hrn_to_os_slicename
 from sfa.util.cache import Cache
 from sfa.trust.credential import Credential
 # used to be used in get_ticket
@@ -73,7 +75,7 @@ class NovaDriver (Driver):
            
         if type == 'slice':
             # add slice description, name, researchers, PI 
-            name = Xrn(hrn).get_leaf()
+            name = hrn_to_os_slicename(hrn)
             researchers = sfa_record.get('researchers', [])
             pis = sfa_record.get('pis', [])
             project_manager = None
@@ -122,7 +124,7 @@ class NovaDriver (Driver):
 
         elif type == "slice":
             # can update project manager and description
-            name = Xrn(hrn).get_leaf()
+            name = hrn_to_os_slicename(hrn)
             researchers = sfa_record.get('researchers', [])
             pis = sfa_record.get('pis', [])
             project_manager = None
@@ -143,11 +145,12 @@ class NovaDriver (Driver):
     ##########
     def remove (self, sfa_record):
         type=sfa_record['type']
-        name = Xrn(sfa_record['hrn']).get_leaf()     
         if type == 'user':
+            name = Xrn(sfa_record['hrn']).get_leaf()     
             if self.shell.auth_manager.get_user(name):
                 self.shell.auth_manager.delete_user(name)
         elif type == 'slice':
+            name = hrn_to_os_slicename(sfa_record['hrn'])     
             if self.shell.auth_manager.get_project(name):
                 self.shell.auth_manager.delete_project(name)
         return True
@@ -163,9 +166,9 @@ class NovaDriver (Driver):
             records = [records]
 
         for record in records:
-            name = Xrn(record['hrn']).get_leaf()
             os_record = None
             if record['type'] == 'user':
+                name = Xrn(record['hrn']).get_leaf()
                 os_record = self.shell.auth_manager.get_user(name)
                 projects = self.shell.db.project_get_by_user(name)
                 record['slices'] = [self.hrn + "." + proj.name for \
@@ -173,7 +176,8 @@ class NovaDriver (Driver):
                 record['roles'] = self.shell.db.user_get_roles(name)
                 keys = self.shell.db.key_pair_get_all_by_user(name)
                 record['keys'] = [key.public_key for key in keys]     
-            elif record['type'] == 'slice': 
+            elif record['type'] == 'slice':
+                name = hrn_to_os_slicename(record['hrn']) 
                 os_record = self.shell.auth_manager.get_project(name)
                 record['description'] = os_record.description
                 record['PI'] = [self.hrn + "." + os_record.project_manager.name]
@@ -289,7 +293,7 @@ class NovaDriver (Driver):
     
     def sliver_status (self, slice_urn, slice_hrn):
         # find out where this slice is currently running
-        project_name = Xrn(slice_urn).get_leaf()
+        project_name = hrn_to_os_slicename(slice_hrn)
         project = self.shell.auth_manager.get_project(project_name)
         instances = self.shell.db.instance_get_all_by_project(project_name)
         if len(instances) == 0:
@@ -328,7 +332,7 @@ class NovaDriver (Driver):
 
     def create_sliver (self, slice_urn, slice_hrn, creds, rspec_string, users, options):
 
-        project_name = get_leaf(slice_hrn)
+        project_name = hrn_to_os_slicename(slice_hrn)
         aggregate = OSAggregate(self)
         # parse rspec
         rspec = RSpec(rspec_string)
@@ -358,14 +362,13 @@ class NovaDriver (Driver):
 
     def delete_sliver (self, slice_urn, slice_hrn, creds, options):
         # we need to do this using the context of one of the slice users
-        project_name = Xrn(slice_urn).get_leaf()
+        project_name = hrn_to_os_slicename(slice_hrn)
         self.euca_shell.init_context(project_name) 
-        name = OSXrn(xrn=slice_urn).name
         aggregate = OSAggregate(self)
-        return aggregate.delete_instances(name)   
+        return aggregate.delete_instances(project_name)   
 
     def update_sliver(self, slice_urn, slice_hrn, rspec, creds, options):
-        name = OSXrn(xrn=slice_urn).name
+        name = hrn_to_os_slicename(slice_hrn)
         aggregate = OSAggregate(self)
         return aggregate.update_instances(name)
     
index 65bbc9e..70d3cf2 100644 (file)
@@ -15,13 +15,25 @@ from sfa.rspecs.elements.sliver import Sliver
 from sfa.rspecs.elements.login import Login
 from sfa.rspecs.elements.disk_image import DiskImage
 from sfa.rspecs.elements.services import Services
+from sfa.rspecs.elements.interface import Interface
 from sfa.util.xrn import Xrn
-from sfa.util.osxrn import OSXrn
+from sfa.planetlab.plxrn import PlXrn 
+from sfa.openstack.osxrn import OSXrn, hrn_to_os_slicename
 from sfa.rspecs.version_manager import VersionManager
 from sfa.openstack.image import ImageManager
 from sfa.openstack.security_group import SecurityGroup
 from sfa.util.sfalogging import logger
 
+def pubkeys_to_user_data(pubkeys):
+    user_data = "#!/bin/bash\n\n"
+    for pubkey in pubkeys:
+        pubkey = pubkey.replace('\n', '')
+        user_data += "echo %s >> /root/.ssh/authorized_keys" % pubkey
+        user_data += "\n"
+        user_data += "echo >> /root/.ssh/authorized_keys"
+        user_data += "\n"
+    return user_data
+
 def instance_to_sliver(instance, slice_xrn=None):
     # should include?
     # * instance.image_ref
@@ -80,34 +92,73 @@ class OSAggregate:
         rspec.version.add_nodes(nodes)
         return rspec.toxml()
 
+    def get_availability_zones(self):
+        try:
+            # pre essex releases 
+            zones = self.driver.shell.db.zone_get_all()
+        except:
+            # essex release
+            zones = self.driver.shell.db.dnsdomain_list()
+
+        if not zones:
+            zones = ['cloud']
+        else:
+            zones = [zone.name for zone in zones]
+        return zones
+
     def get_slice_nodes(self, slice_xrn):
         image_manager = ImageManager(self.driver)
-        name = OSXrn(xrn = slice_xrn).name
+
+        zones = self.get_availability_zones()
+        name = hrn_to_os_slicename(slice_xrn)
         instances = self.driver.shell.db.instance_get_all_by_project(name)
         rspec_nodes = []
         for instance in instances:
             rspec_node = Node()
-            xrn = OSXrn(instance.hostname, 'node')
-            rspec_node['component_id'] = xrn.urn
-            rspec_node['component_name'] = xrn.name
+            interfaces = []
+            for fixed_ip in instance.fixed_ips:
+                if_xrn = PlXrn(auth=self.driver.hrn, 
+                               interface='node%s:eth0' % (instance.hostname)) 
+                interface = Interface({'component_id': if_xrn.urn})
+                interface['ips'] =  [{'address': fixed_ip['address'],
+                                     'netmask': fixed_ip['network'].netmask,
+                                     'type': 'ipv4'}]
+                interface['floating_ips'] = []
+                for floating_ip in fixed_ip.floating_ips:
+                    interface['floating_ips'].append(floating_ip.address)
+                interfaces.append(interface)
+            if instance.availability_zone:
+                node_xrn = OSXrn(instance.availability_zone, 'node')
+            else:
+                node_xrn = OSXrn('cloud', 'node')
+
+            rspec_node['component_id'] = node_xrn.urn
+            rspec_node['component_name'] = node_xrn.name
             rspec_node['component_manager_id'] = Xrn(self.driver.hrn, 'authority+cm').get_urn()   
             sliver = instance_to_sliver(instance)
             disk_image = image_manager.get_disk_image(instance.image_ref)
             sliver['disk_image'] = [disk_image.to_rspec_object()]
             rspec_node['slivers'] = [sliver]
+            rspec_node['interfaces'] = interfaces
+            # slivers always provide the ssh service
+            rspec_node['services'] = []
+            for interface in interfaces:
+                if 'floating_ips' in interface:
+                    for hostname in interface['floating_ips']:
+                        login = Login({'authentication': 'ssh-keys', 
+                                       'hostname': hostname, 
+                                       'port':'22', 'username': 'root'})
+                        service = Services({'login': login})
+                        rspec_node['services'].append(service)
             rspec_nodes.append(rspec_node)
         return rspec_nodes
 
     def get_aggregate_nodes(self):
-                
-        zones = self.driver.shell.db.zone_get_all()
-        if not zones:
-            zones = ['cloud']
-        else:
-            zones = [zone.name for zone in zones]
-
+        zones = self.get_availability_zones()
         # available sliver/instance/vm types
-        instances = self.driver.shell.db.instance_type_get_all().values()
+        instances = self.driver.shell.db.instance_type_get_all()
+        if isinstance(instances, dict):
+            instances = instances.values()
         # available images
         image_manager = ImageManager(self.driver)
         disk_images = image_manager.get_available_disk_images()
@@ -145,7 +196,7 @@ class OSAggregate:
             username = Xrn(user['urn']).get_leaf()
             try:
                 self.driver.shell.auth_manager.get_user(username)
-            except nova.exception.UserNotFound:
+            except UserNotFound:
                 self.driver.shell.auth_manager.create_user(username)
             self.verify_user_keys(username, user['keys'], options)
 
@@ -251,7 +302,7 @@ class OSAggregate:
 
         # get requested slivers
         rspec = RSpec(rspec)
-        user_data = "\n".join(pubkeys)
+        user_data = pubkeys_to_user_data(pubkeys)
         requested_instances = defaultdict(list)
         # iterate over clouds/zones/nodes
         for node in rspec.version.get_nodes_with_slivers():
diff --git a/sfa/openstack/osxrn.py b/sfa/openstack/osxrn.py
new file mode 100644 (file)
index 0000000..ad82f22
--- /dev/null
@@ -0,0 +1,38 @@
+import re
+from sfa.util.xrn import Xrn
+from sfa.util.config import Config
+
+def hrn_to_os_slicename(hrn):
+    return OSXrn(xrn=hrn, type='slice').get_slicename()        
+
+class OSXrn(Xrn):
+
+    def __init__(self, name=None, type=None, **kwds):
+        
+        config = Config()
+        if name is not None:
+            self.type = type
+            self.hrn = config.SFA_INTERFACE_HRN + "." + name
+            self.hrn_to_urn()
+        else:
+            Xrn.__init__(self, **kwds)   
+         
+        self.name = self.get_name() 
+    
+    def get_name(self):
+        self._normalize()
+        leaf = self.leaf
+        sliver_id_parts = leaf.split(':')
+        name = sliver_id_parts[0]
+        name = re.sub('[^a-zA-Z0-9_]', '', name)
+        return name
+
+
+    def get_slicename(self):
+        self._normalize()
+        slicename = self.hrn
+        slicename = slicename.split(':')[0]
+        slicename = re.sub('[\.]', '_', slicename)
+        return slicename
+        
+            
index e2ff3f9..d232cc5 100644 (file)
@@ -254,6 +254,7 @@ class PlAggregate:
            filter.update({'name':slice['name']})
         return_fields = ['lease_id', 'hostname', 'site_id', 'name', 't_from', 't_until']
         leases = self.driver.shell.GetLeases(filter)
+        grain = self.driver.shell.GetLeaseGranularity()
 
         site_ids = []
         for lease in leases:
@@ -276,8 +277,8 @@ class PlAggregate:
             slice_hrn = slicename_to_hrn(self.driver.hrn, lease['name'])
             slice_urn = hrn_to_urn(slice_hrn, 'slice')
             rspec_lease['slice_id'] = slice_urn
-            rspec_lease['t_from'] = lease['t_from']
-            rspec_lease['t_until'] = lease['t_until']          
+            rspec_lease['start_time'] = lease['t_from']
+            rspec_lease['duration'] = (lease['t_until'] - lease['t_from']) / grain
             rspec_leases.append(rspec_lease)
         return rspec_leases
 
index 7835a1d..d72f2e6 100644 (file)
@@ -749,8 +749,8 @@ class PlDriver (Driver):
             requested_lease = {}
             if not lease.get('lease_id'):
                requested_lease['hostname'] = xrn_to_hostname(lease.get('component_id').strip())
-               requested_lease['t_from'] = lease.get('t_from')
-               requested_lease['t_until'] = lease.get('t_until')
+               requested_lease['start_time'] = lease.get('start_time')
+               requested_lease['duration'] = lease.get('duration')
             else:
                kept_leases.append(int(lease['lease_id']))
             if requested_lease.get('hostname'):
index 54cfaa1..eb60066 100644 (file)
@@ -162,6 +162,7 @@ class PlSlices:
     def verify_slice_leases(self, slice, requested_leases, kept_leases, peer):
         
         leases = self.driver.shell.GetLeases({'name':slice['name']}, ['lease_id'])
+        grain = self.driver.shell.GetLeaseGranularity()
         current_leases = [lease['lease_id'] for lease in leases]
         deleted_leases = list(set(current_leases).difference(kept_leases))
 
@@ -170,7 +171,7 @@ class PlSlices:
                 self.driver.shell.UnBindObjectFromPeer('slice', slice['slice_id'], peer['shortname'])
             deleted=self.driver.shell.DeleteLeases(deleted_leases)
             for lease in requested_leases:
-                added=self.driver.shell.AddLeases(lease['hostname'], slice['name'], int(lease['t_from']), int(lease['t_until']))
+                added=self.driver.shell.AddLeases(lease['hostname'], slice['name'], int(lease['start_time']), int(lease['duration']) * grain + int(lease['start_time']))
 
         except: 
             logger.log_exc('Failed to add/remove slice leases')
index d329a8c..3327407 100644 (file)
@@ -6,6 +6,6 @@ class Lease(Element):
         'lease_id',
         'component_id',
         'slice_id'
-        't_from',
-        't_until',    
+        'start_time',
+        'duration',    
     ]
diff --git a/sfa/rspecs/elements/versions/pgv2Interface.py b/sfa/rspecs/elements/versions/pgv2Interface.py
new file mode 100644 (file)
index 0000000..2984591
--- /dev/null
@@ -0,0 +1,20 @@
+from sfa.util.xrn import Xrn
+from sfa.util.xml import XpathFilter
+from sfa.rspecs.elements.interface import Interface
+
+class PGv2Interface:
+
+    @staticmethod
+    def add_interfaces(xml, interfaces):
+        if isinstance(interfaces, list):
+            for interface in interfaces:
+                if_elem = xml.add_instance('interface', interface, ['component_id', 'client_id'])
+                ips = interface.get('ips', [])
+                for ip in ips:
+                    if_elem.add_instance('ip', {'address': ip.get('address'),
+                                                'netmask': ip.get('netmask'),
+                                                'type': ip.get('type')}) 
+    
+    @staticmethod
+    def get_interfaces(xml):
+        pass
index 9892d8c..88787b5 100644 (file)
@@ -11,6 +11,7 @@ from sfa.rspecs.elements.bwlimit import BWlimit
 from sfa.rspecs.elements.pltag import PLTag
 from sfa.rspecs.elements.versions.pgv2Services import PGv2Services     
 from sfa.rspecs.elements.versions.pgv2SliverType import PGv2SliverType     
+from sfa.rspecs.elements.versions.pgv2Interface import PGv2Interface     
 
 from sfa.planetlab.plxrn import xrn_to_hostname
 
@@ -34,9 +35,10 @@ class PGv2Node:
             if node.get('location'):
                 node_elem.add_instance('location', node['location'], Location.fields)       
             # set interfaces
-            if node.get('interfaces'):
-                for interface in  node.get('interfaces', []):
-                    node_elem.add_instance('interface', interface, ['component_id', 'client_id'])
+            PGv2Interface.add_interfaces(node_elem, node.get('interfaces'))
+            #if node.get('interfaces'):
+            #    for interface in  node.get('interfaces', []):
+            #        node_elem.add_instance('interface', interface, ['component_id', 'client_id'])
             # set available element
             if node.get('boot_state'):
                 if node.get('boot_state').lower() == 'boot':
index 7a2320e..8dffdfd 100644 (file)
@@ -34,7 +34,7 @@ class SFAv1Lease:
          
         lease_elems = []       
         for lease in leases:
-            lease_fields = ['lease_id', 'component_id', 'slice_id', 't_from', 't_until']
+            lease_fields = ['lease_id', 'component_id', 'slice_id', 'start_time', 'duration']
             lease_elem = network_elem.add_instance('lease', lease, lease_fields)
             lease_elems.append(lease_elem)
 
@@ -54,8 +54,8 @@ class SFAv1Lease:
                lease['lease_id'] = lease_elem.attrib['lease_id']
             lease['component_id'] = lease_elem.attrib['component_id']
             lease['slice_id'] = lease_elem.attrib['slice_id']
-            lease['t_from'] = lease_elem.attrib['t_from']
-            lease['t_until'] = lease_elem.attrib['t_until']
+            lease['start_time'] = lease_elem.attrib['start_time']
+            lease['duration'] = lease_elem.attrib['duration']
 
             leases.append(lease)
         return leases            
index e234a2f..b0dbe55 100644 (file)
@@ -6,7 +6,7 @@ from sqlalchemy import Integer, String
 
 metadata=MetaData()
 
-# this is needed my migrate so it can locate 'records.record_id'
+# this is needed by migrate so it can locate 'records.record_id'
 records = \
     Table ( 'records', metadata,
             Column ('record_id', Integer, primary_key=True),
index c187dcc..64da316 100644 (file)
@@ -127,6 +127,8 @@ class RegRecord (Base,AlchemyObj):
     def validate_datetime (self, key, incoming):
         if isinstance (incoming, datetime):     return incoming
         elif isinstance (incoming, (int,float)):return datetime.fromtimestamp (incoming)
+        else: logger.info("Cannot validate datetime for key %s with input %s"%\
+                              (key,incoming))
 
     @validates ('date_created')
     def validate_date_created (self, key, incoming): return self.validate_datetime (key, incoming)
@@ -237,6 +239,8 @@ class RegSlice (RegRecord):
         auth_record = dbsession.query(RegAuthority).filter_by(hrn=authority_hrn).first()
         return auth_record.reg_pis
         
+    @validates ('expires')
+    def validate_expires (self, key, incoming): return self.validate_datetime (key, incoming)
 
 ####################
 class RegNode (RegRecord):
index e22967c..b7c3444 100644 (file)
@@ -56,8 +56,8 @@ class SFATablesRules:
                 
     def add_request_context_to_rspec(self, doc):
         p = doc.xpathNewContext()
-        context = p.xpathEval("//RSpec")
-        if (not context):
+        context = p.xpathEval("//*")
+        if not context or context[0].name not in ['RSpec', 'rspec']:
             raise Exception('Request is not an rspec')
         else:
             # Add the request context
index 46f3601..ff3b3ef 100644 (file)
@@ -61,8 +61,8 @@ class XMLRule:
 
     def add_rule_context_to_rspec(self, doc):
         p = doc.xpathNewContext()
-        context = p.xpathEval("//RSpec")
-        if (not context):
+        context = p.xpathEval("//*")
+        if not context or context[0].name not in ['RSpec', 'rspec']:
             raise Exception('Request is not an rspec')
         else:
             # Add the request context