Merge branch 'master' into senslab2
Sandrine Avakian [Tue, 29 May 2012 09:18:37 +0000 (11:18 +0200)]
Conflicts:
setup.py

1  2 
setup.py
sfa/client/sfi.py
sfa/managers/driver.py
sfa/planetlab/plslices.py
sfa/trust/auth.py
tests/testXrn.py

diff --combined setup.py
+++ b/setup.py
@@@ -32,8 -32,7 +32,12 @@@ packages = 
      'sfa/generic',
      'sfa/managers',
      'sfa/importer',
-     'sfa/plc',
++
++
 +    'sfa/senslab',
++
+     'sfa/planetlab',
++
      'sfa/rspecs',
      'sfa/rspecs/elements',
      'sfa/rspecs/elements/versions',
diff --combined sfa/client/sfi.py
@@@ -219,6 -219,7 +219,7 @@@ class Sfi
          ("delegate", "name"),
          ("create_gid", "[name]"),
          ("get_trusted_certs", "cred"),
+         ("config", ""),
          ]
  
      def print_command_help (self, options):
             parser.add_option("-F", "--fileformat", dest="fileformat", type="choice",
                               help="output file format ([xml]|xmllist|hrnlist)", default="xml",
                               choices=("xml", "xmllist", "hrnlist"))
+         if command == 'list':
+            parser.add_option("-r", "--recursive", dest="recursive", action='store_true',
+                              help="list all child records", default=False)
          if command in ("delegate"):
             parser.add_option("-u", "--user",
                              action="store_true", dest="delegate_user", default=False,
             self.logger.error("You need to set e.g. SFI_AUTH='plc.princeton' in %s" % config_file)
             errors += 1 
  
+         self.config_file=config_file
          if errors:
             sys.exit(1)
  
+     def show_config (self):
+         print "From configuration file %s"%self.config_file
+         flags=[ 
+             ('SFI_USER','user'),
+             ('SFI_AUTH','authority'),
+             ('SFI_SM','sm_url'),
+             ('SFI_REGISTRY','reg_url'),
+             ]
+         for (external_name, internal_name) in flags:
+             print "%s='%s'"%(external_name,getattr(self,internal_name))
      #
      # Get various credential and spec files
      #
      
      # init self-signed cert, user credentials and gid
      def bootstrap (self):
-         bootstrap = SfaClientBootstrap (self.user, self.reg_url, self.options.sfi_dir)
+         client_bootstrap = SfaClientBootstrap (self.user, self.reg_url, self.options.sfi_dir)
          # if -k is provided, use this to initialize private key
          if self.options.user_private_key:
-             bootstrap.init_private_key_if_missing (self.options.user_private_key)
+             client_bootstrap.init_private_key_if_missing (self.options.user_private_key)
          else:
              # trigger legacy compat code if needed 
              # the name has changed from just <leaf>.pkey to <hrn>.pkey
-             if not os.path.isfile(bootstrap.private_key_filename()):
+             if not os.path.isfile(client_bootstrap.private_key_filename()):
                  self.logger.info ("private key not found, trying legacy name")
                  try:
                      legacy_private_key = os.path.join (self.options.sfi_dir, "%s.pkey"%get_leaf(self.user))
                      self.logger.debug("legacy_private_key=%s"%legacy_private_key)
-                     bootstrap.init_private_key_if_missing (legacy_private_key)
+                     client_bootstrap.init_private_key_if_missing (legacy_private_key)
                      self.logger.info("Copied private key from legacy location %s"%legacy_private_key)
                  except:
                      self.logger.log_exc("Can't find private key ")
                      sys.exit(1)
              
          # make it bootstrap
-         bootstrap.bootstrap_my_gid()
+         client_bootstrap.bootstrap_my_gid()
          # extract what's needed
-         self.private_key = bootstrap.private_key()
-         self.my_credential_string = bootstrap.my_credential_string ()
-         self.my_gid = bootstrap.my_gid ()
-         self.bootstrap = bootstrap
+         self.private_key = client_bootstrap.private_key()
+         self.my_credential_string = client_bootstrap.my_credential_string ()
+         self.my_gid = client_bootstrap.my_gid ()
+         self.client_bootstrap = client_bootstrap
  
  
      def my_authority_credential_string(self):
          if not self.authority:
              self.logger.critical("no authority specified. Use -a or set SF_AUTH")
              sys.exit(-1)
-         return self.bootstrap.authority_credential_string (self.authority)
+         return self.client_bootstrap.authority_credential_string (self.authority)
  
      def slice_credential_string(self, name):
-         return self.bootstrap.slice_credential_string (name)
+         return self.client_bootstrap.slice_credential_string (name)
  
      # xxx should be supported by sfaclientbootstrap as well
      def delegate_cred(self, object_cred, hrn, type='authority'):
          caller_gidfile = self.my_gid()
    
          # the gid of the user who will be delegated to
-         delegee_gid = self.bootstrap.gid(hrn,type)
+         delegee_gid = self.client_bootstrap.gid(hrn,type)
          delegee_hrn = delegee_gid.get_hrn()
          dcred = object_cred.delegate(delegee_gid, self.private_key, caller_gidfile)
          return dcred.save_to_string(save_parents=True)
@@@ -690,8 -705,12 +705,12 @@@ or version information about sfi itsel
              self.print_help()
              sys.exit(1)
          hrn = args[0]
+         opts = {}
+         if options.recursive:
+             opts['recursive'] = options.recursive
+         
          try:
-             list = self.registry().List(hrn, self.my_credential_string)
+             list = self.registry().List(hrn, self.my_credential_string, options)
          except IndexError:
              raise Exception, "Not enough parameters for the 'list' command"
  
@@@ -904,7 -923,6 +923,7 @@@ or with an slice hrn, shows currently p
                  rspec.filter({'component_manager_id': server_version['urn']})
                  rspec = RSpecConverter.to_pg_rspec(rspec.toxml(), content_type='request')
              else:
 +                print >>sys.stderr, "\r\n \r\n \r\n WOOOOOO"
                  users = sfa_users_arg(user_records, slice_record)
  
          # do not append users, keys, or slice tags. Anything
              self.print_help()
              sys.exit(1)
          target_hrn = args[0]
-         gid = self.registry().CreateGid(self.my_credential_string, target_hrn, self.bootstrap.my_gid_string())
+         gid = self.registry().CreateGid(self.my_credential_string, target_hrn, self.client_bootstrap.my_gid_string())
          if options.file:
              filename = options.file
          else:
              self.logger.debug('Sfi.get_trusted_certs -> %r'%cert.get_subject())
          return 
  
+     def config (self, options, args):
+         "Display contents of current config"
+         self.show_config()
diff --combined sfa/managers/driver.py
@@@ -2,7 -2,7 +2,7 @@@
  # an attempt to document what a driver class should provide, 
  # and implement reasonable defaults
  #
 -
 +import sys
  class Driver:
      
      def __init__ (self, config): 
      ########## registry oriented
      ########################################
  
-     # redefine this if you want to check again records 
-     # when running GetCredential
-     # This is to reflect the 'enabled' user field in planetlab testbeds
-     # expected retcod boolean
-     def is_enabled (self, record) : 
-         return True
+     # NOTE: the is_enabled method is deprecated
+     # it was only making things confusing, as the (PL) import mechanism would
+     # ignore not enabled users anyway..
  
      # the following is used in Resolve (registry) when run in full mode
      #     after looking up the sfa db, we wish to be able to display
@@@ -29,7 -26,6 +26,7 @@@
      # this constraint, based on the principle that SFA should not rely on the
      # testbed database to perform such a core operation (i.e. getting rights right)
      def augment_records_with_testbed_info (self, sfa_records):
 +        print >>sys.stderr, "  \r\n \r\n DRIVER.PY augment_records_with_testbed_info sfa_records ",sfa_records
          return sfa_records
  
      # incoming record, as provided by the client to the Register API call
      def update (self, old_sfa_record, new_sfa_record, hrn, new_key): 
          return True
  
+     # callack for register/update
+     # this allows to capture changes in the relations between objects
+     # the ids below are the ones found in the 'pointer' field
+     # this can get typically called with
+     # 'slice' 'user' 'researcher' slice_id user_ids 
+     # 'authority' 'user' 'pi' authority_id user_ids 
+     def update_relation (self, subject_type, target_type, relation_name, subject_id, link_ids):
+         pass
      ########################################
      ########## aggregate oriented
      ########################################
@@@ -1,15 -1,14 +1,15 @@@
  from types import StringTypes
  from collections import defaultdict
 +import sys
  
  from sfa.util.sfatime import utcparse, datetime_to_epoch
  from sfa.util.sfalogging import logger
  from sfa.util.xrn import Xrn, get_leaf, get_authority, urn_to_hrn
- #from sfa.util.policy import Policy
- from sfa.util.plxrn import PlXrn
  from sfa.rspecs.rspec import RSpec
- from sfa.plc.vlink import VLink
- from sfa.util.plxrn import hrn_to_pl_slicename
+ from sfa.planetlab.vlink import VLink
+ from sfa.planetlab.plxrn import PlXrn, hrn_to_pl_slicename
  
  MAXINT =  2L**31-1
  
@@@ -131,11 -130,13 +131,11 @@@ class PlSlices
          # slice belongs to out local plc or a myplc peer. We will assume it 
          # is a local site, unless we find out otherwise  
          peer = None
 -
          # get this slice's authority (site)
          slice_authority = get_authority(hrn)
  
          # get this site's authority (sfa root authority or sub authority)
          site_authority = get_authority(slice_authority).lower()
 -
          # check if we are already peered with this site_authority, if so
          peers = self.driver.shell.GetPeers({}, ['peer_id', 'peername', 'shortname', 'hrn_root'])
          for peer_record in peers:
diff --combined sfa/trust/auth.py
@@@ -68,6 -68,7 +68,6 @@@ class Auth
          self.client_cred = Credential(string = cred)
          self.client_gid = self.client_cred.get_gid_caller()
          self.object_gid = self.client_cred.get_gid_object()
 -        
          # make sure the client_gid is not blank
          if not self.client_gid:
              raise MissingCallerGID(self.client_cred.get_subject())
              self.verifyPeerCert(self.peer_cert, self.client_gid)                   
  
          # make sure the client is allowed to perform the operation
 -        if operation:
 +        if operation:    
              if not self.client_cred.can_perform(operation):
                  raise InsufficientRights(operation)
  
          if self.trusted_cert_list:
              self.client_cred.verify(self.trusted_cert_file_list, self.config.SFA_CREDENTIAL_SCHEMA)
 +            
          else:
             raise MissingTrustedRoots(self.config.get_trustedroots_dir())
         
@@@ -91,7 -91,6 +91,7 @@@
          # This check does not apply to trusted peers 
          trusted_peers = [gid.get_hrn() for gid in self.trusted_cert_list]
          if hrn and self.client_gid.get_hrn() not in trusted_peers:
 +            
              target_hrn = self.object_gid.get_hrn()
              if not hrn == target_hrn:
                  raise PermissionError("Target hrn: %s doesn't match specified hrn: %s " % \
          @param name human readable name to test  
          """
          object_hrn = self.object_gid.get_hrn()
 -        if object_hrn == name:
 -            return
 -        if name.startswith(object_hrn + "."):
 +      #strname = str(name).strip("['']")
 +      if object_hrn == name:
 +        #if object_hrn == strname:
 +            return 
 +        if name.startswith(object_hrn + ".") :
 +        #if strname.startswith((object_hrn + ".")) is True:
              return
          #if name.startswith(get_authority(name)):
              #return
 -    
 +
          raise PermissionError(name)
  
-     def determine_user_rights(self, caller_hrn, record):
+     def determine_user_rights(self, caller_hrn, reg_record):
          """
          Given a user credential and a record, determine what set of rights the
          user should have to that record.
          
-         This is intended to replace determine_rights() and
+         This is intended to replace determine_user_rights() and
          verify_cancreate_credential()
          """
  
          rl = Rights()
-         type = record['type']
-         if type=="slice":
-             researchers = record.get("researcher", [])
-             pis = record.get("PI", [])
-             if (caller_hrn in researchers + pis):
-                 rl.add("refresh")
-                 rl.add("embed")
-                 rl.add("bind")
-                 rl.add("control")
-                 rl.add("info")
-         elif type == "authority":
-             pis = record.get("PI", [])
-             operators = record.get("operator", [])
+         type = reg_record.type
+         logger.debug("entering determine_user_rights with record %s and caller_hrn %s"%(reg_record, caller_hrn))
+         if type == 'slice':
+             # researchers in the slice are in the DB as-is
+             researcher_hrns = [ user.hrn for user in reg_record.reg_researchers ]
+             # locating PIs attached to that slice
+             slice_pis=reg_record.get_pis()
+             pi_hrns = [ user.hrn for user in slice_pis ]
+             if (caller_hrn in researcher_hrns + pi_hrns):
+                 rl.add('refresh')
+                 rl.add('embed')
+                 rl.add('bind')
+                 rl.add('control')
+                 rl.add('info')
+         elif type == 'authority':
+             pi_hrns = [ user.hrn for user in reg_record.reg_pis ]
              if (caller_hrn == self.config.SFA_INTERFACE_HRN):
-                 rl.add("authority")
-                 rl.add("sa")
-                 rl.add("ma")
-             if (caller_hrn in pis):
-                 rl.add("authority")
-                 rl.add("sa")
-             if (caller_hrn in operators):
-                 rl.add("authority")
-                 rl.add("ma")
-         elif type == "user":
-             rl.add("refresh")
-             rl.add("resolve")
-             rl.add("info")
-         elif type == "node":
-             rl.add("operator")
+                 rl.add('authority')
+                 rl.add('sa')
+                 rl.add('ma')
+             if (caller_hrn in pi_hrns):
+                 rl.add('authority')
+                 rl.add('sa')
+             # NOTE: for the PL implementation, this 'operators' list 
+             # amounted to users with 'tech' role in that site 
+             # it seems like this is not needed any longer, so for now I just drop that
+             # operator_hrns = reg_record.get('operator',[])
+             # if (caller_hrn in operator_hrns):
+             #    rl.add('authority')
+             #    rl.add('ma')
+         elif type == 'user':
+             rl.add('refresh')
+             rl.add('resolve')
+             rl.add('info')
+         elif type == 'node':
+             rl.add('operator')
  
          return rl
  
-     def verify_cancreate_credential(self, src_cred, record):
-         """
-         Verify that a user can retrive a particular type of credential.
-         For slices, the user must be on the researcher list. For SA and
-         MA the user must be on the pi and operator lists respectively
-         """
-         type = record.get_type()
-         cred_object_hrn = src_cred.get_gid_object().get_hrn()
-         if cred_object_hrn in [self.config.SFA_REGISTRY_ROOT_AUTH]:
-             return
-         if type=="slice":
-             researchers = record.get("researcher", [])
-             if not (cred_object_hrn in researchers):
-                 raise PermissionError(cred_object_hrn + " is not in researcher list for " + record.get_name())
-         elif type == "sa":
-             pis = record.get("pi", [])
-             if not (cred_object_hrn in pis):
-                 raise PermissionError(cred_object_hrn + " is not in pi list for " + record.get_name())
-         elif type == "ma":
-             operators = record.get("operator", [])
-             if not (cred_object_hrn in operators):
-                 raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name())
      def get_authority(self, hrn):
          return get_authority(hrn)
  
diff --combined tests/testXrn.py
@@@ -1,11 -1,11 +1,12 @@@
  #!/usr/bin/python
 +# just checking write access on repo
  import sys
  import unittest
  
  from sfa.util.faults import *
  from sfa.util.xrn import Xrn
- from sfa.util.plxrn import PlXrn
+ from sfa.planetlab.plxrn import PlXrn
  
  verbose=False