Ignore:
Timestamp:
Nov 14, 2008 5:13:10 PM (15 years ago)
Author:
Ted Faber <faber@…>
Branches:
axis_example, compt_changes, info-ops, master, version-1.30, version-2.00, version-3.01, version-3.02
Children:
afa43a8
Parents:
2dafa0c
Message:

Proxy key additions working

File:
1 edited

Legend:

Unmodified
Added
Removed
  • fedd/fedd_allocate_project.py

    r2dafa0c r4ed10ae  
    3535fl.addHandler(nullHandler())
    3636
     37
    3738class fedd_allocate_project_local:
    3839    """
    3940    Allocate projects on this machine in response to an access request.
    4041    """
    41     def __init__(self, dp=False, url=None, certs=None):
     42    def __init__(self, config):
    4243        """
    4344        Initializer.  Parses a configuration if one is given.
    4445        """
    4546
    46         self.dynamic_projects = dp
    47         self.wap = '/usr/testbed/sbin/wap'
    48         self.newproj = '/usr/testbed/sbin/newproj'
    49         self.mkproj = '/usr/testbed/sbin/mkproj'
    50         self.grantnodetype = '/usr/testbed/sbin/grantnodetype'
     47        self.debug = config.get("access", "debug_project", False)
     48        self.wap = config.get('access', 'wap', '/usr/testbed/sbin/wap')
     49        self.newproj = config.get('access', 'newproj',
     50                '/usr/testbed/sbin/newproj')
     51        self.mkproj = config.get('access', 'mkproj', '/usr/testbed/sbin/mkproj')
     52        self.addpubkey = config.get('access', 'addpubkey',
     53                '/usr/testbed/sbin/taddpubkey')
     54        self.grantnodetype = config.get('access', 'grantnodetype',
     55                '/usr/testbed/sbin/grantnodetype')
    5156        self.log = logging.getLogger("fedd.allocate.local")
     57        set_log_level(config, "access", self.log)
    5258
    5359        # Internal services are SOAP only
     
    5662                AllocateProjectRequestMessage.typecode,\
    5763                self.dynamic_project, AllocateProjectResponseMessage,\
    58                 "AllocateProjectResponseBody")\
     64                "AllocateProjectResponseBody"),
     65                "StaticProject": make_soap_handler(\
     66                StaticProjectRequestMessage.typecode,\
     67                self.static_project, StaticProjectResponseMessage,\
     68                "StaticProjectResponseBody")\
    5969                }
    6070        self.xmlrpc_services = { }
     
    179189        for cmd in cmds:
    180190            self.log.debug("[dynamic_project]: %s" % ' '.join(cmd))
    181             if self.dynamic_projects:
     191            if not self.debug:
    182192                try:
    183193                    rc = subprocess.call(cmd)
    184194                except OSerror, e:
    185                     raise fedd_proj.service_error(\
    186                             fedd_proj.service_error.internal,
     195                    raise service_error(service_error.internal,
    187196                            "Dynamic project subprocess creation error "+ \
    188197                                    "[%s] (%s)" %  (cmd[1], e.strerror))
    189198
    190199            if rc != 0:
    191                 raise fedd_proj.service_error(\
    192                         fedd_proj.service_error.internal,
     200                raise service_error(service_error.internal,
    193201                        "Dynamic project subprocess error " +\
    194202                                "[%s] (%d)" % (cmd[1], rc))
     
    207215        return rv
    208216
    209 
    210 class fedd_allocate_project_remote:
    211     """
    212     Allocate projects on a remote machine using the internal SOAP interface
    213     """
    214     def __init__(self, dp=False, url=None, certs=None):
    215         """
    216         Initializer.  Parses a configuration if one is given.
    217         """
    218 
    219         self.dynamic_projects = dp
    220         self.url = url
    221 
    222         if certs != None and isinstance(certs, type(tuple())):
    223             self.cert_file, self.trusted_certs, self.cert_pwd = certs
    224         else:
    225             self.cert_file, self.trusted_certs, self.cert_pwd = \
    226                     (None, None, None)
    227         self.soap_services = { }
    228         self.xmlrpc_services = { }
     217    def static_project(self, req, fedid=None):
     218        """
     219        Be certain that the local project in the request has access to the
     220        proper resources and users have correct keys.  Add them if necessary.
     221        """
     222
     223        cmds =  []
     224
     225        # While we should be more careful about this, for the short term, add
     226        # the keys to the specified users.
     227
     228        try:
     229            users = req['StaticProjectRequestBody']['project']['user']
     230            pname = req['StaticProjectRequestBody']['project']\
     231                    ['name']['localname']
     232            resources = req['StaticProjectRequestBody'].get('resources', [])
     233        except KeyError:
     234            raise service_error(service_error.req, "Badly formed request")
     235
     236
     237        for u in users:
     238            try:
     239                name = u['userID']['localname']
     240            except KeyError:
     241                raise service_error(service_error.req, "Badly formed user")
     242            for sk in [ k['sshPubkey'] for k in u.get('access', []) \
     243                    if k.has_key('sshPubkey')]:
     244                cmds.append((self.addpubkey, '-w', '-u', name, '-k', sk))
    229245       
    230     def dynamic_project(self, req, fedid=None):
     246
     247        # Add commands to grant access to any resources in the request.  The
     248        # list comprehension pulls out the hardware types in the node entries
     249        # in the resources list.
     250        for nt in [ h for r in resources \
     251                if r.has_key('node') and r['node'].has_key('hardware')\
     252                    for h in r['node']['hardware'] ] :
     253            cmds.append((self.wap, self.grantnodetype, '-p', pname, nt))
     254
     255        # Run the commands
     256        rc = 0
     257        for cmd in cmds:
     258            self.log.debug("[static_project]: %s" % ' '.join(cmd))
     259            if not self.debug:
     260                try:
     261                    rc = subprocess.call(cmd)
     262                except OSError, e:
     263                    print "Static project subprocess creation error "+ \
     264                                    "[%s] (%s)" %  (cmd[0], e.strerror)
     265                    raise service_error(service_error.internal,
     266                            "Static project subprocess creation error "+ \
     267                                    "[%s] (%s)" %  (cmd[0], e.strerror))
     268
     269            if rc != 0:
     270                raise service_error(service_error.internal,
     271                        "Static project subprocess error " +\
     272                                "[%s] (%d)" % (cmd[0], rc))
     273
     274        return { 'project': req['StaticProjectRequestBody']['project']}
     275
     276def make_proxy(method, req_name, req_alloc, resp_name):
     277    """
     278    Construct the proxy calling function from the given parameters.
     279    """
     280
     281    # Define the proxy, NB, the parameters to make_proxy are visible to the
     282    # definition of proxy.
     283    def proxy(self, req, fedid=None):
    231284        """
    232285        Send req on to a remote project instantiator.
    233286
    234         Req is just the projectAllocType object.  This function re-wraps it.
     287        Req is just the message to be sent.  This function re-wraps it.
    235288        It also rethrows any faults.
    236289        """
     290
    237291        # No retry loop here.  Proxy servers must correctly authenticate
    238292        # themselves without help
     
    249303                transdict={ 'ssl_context' : ctx })
    250304
    251         if req.has_key('AllocateProjectRequestBody'):
    252             req = req['AllocateProjectRequestBody']
     305        if req.has_key(req_name):
     306            req = req[req_name]
    253307        else:
    254308            raise service_error(service_error.req, "Bad formated request");
    255309
    256310        # Reconstruct the full request message
    257         msg = AllocateProjectRequestMessage()
    258         msg.set_element_AllocateProjectRequestBody(
    259                 pack_soap(msg, "AllocateProjectRequestBody", req))
     311        msg = req_alloc()
     312        set_elem = getattr(msg, "set_element_%s" % req_name)
     313        set_elem(pack_soap(msg, req_name, req))
    260314        try:
    261             resp = port.AllocateProject(msg)
     315            mattr = getattr(port, method)
     316            resp = mattr(msg)
    262317        except ZSI.ParseException, e:
    263318            raise service_error(service_error.proxy,
    264319                    "Bad format message (XMLRPC??): %s" % str(e))
     320        except ZSI.FaultException, e:
     321            resp = e.fault.detail[0]
     322
    265323        r = unpack_soap(resp)
    266324
    267         if r.has_key('AllocateProjectResponseBody'):
    268             return r['AllocateProjectResponseBody']
     325        if r.has_key(resp_name):
     326            return r[resp_name]
    269327        else:
    270328            raise service_error(service_error.proxy, "Bad proxy response")
    271 
     329    # NB: end of proxy function definition     
     330    return proxy
     331
     332class fedd_allocate_project_remote:
     333    """
     334    Allocate projects on a remote machine using the internal SOAP interface
     335    """
     336    dynamic_project = make_proxy("AllocateProject",
     337            "AllocateProjectRequestBody", AllocateProjectRequestMessage,
     338            "AllocateProjectResponseBody")
     339    static_project = make_proxy("StaticProject",
     340            "StaticProjectRequestBody", StaticProjectRequestMessage,
     341            "StaticProjectResponseBody")
     342
     343    def __init__(self, config):
     344        """
     345        Initializer.  Parses a configuration if one is given.
     346        """
     347
     348        self.debug = config.get("access", "debug_project", False)
     349        self.url = config.get("access", "dynamic_projects_url", "")
     350
     351        self.cert_file = config.get("access", "cert_file", None)
     352        self.cert_pwd = config.get("access", "cert_pwd", None)
     353        self.trusted_certs = config.get("access", "trusted_certs", None)
     354
     355        # Certs are promoted from the generic to the specific, so without a if
     356        # no dynamic project certificates, then proxy certs are used, and if
     357        # none of those the main certs.
     358
     359        if config.has_option("globals", "proxy_cert_file"):
     360            if not self.cert_file:
     361                self.cert_file = config.get("globals", "proxy_cert_file")
     362                if config.has_option("globals", "porxy_cert_pwd"):
     363                    self.cert_pwd = config.get("globals", "proxy_cert_pwd")
     364
     365        if config.has_option("globals", "proxy_trusted_certs") and \
     366                not self.trusted_certs:
     367                self.trusted_certs = \
     368                        config.get("globals", "proxy_trusted_certs")
     369
     370        if config.has_option("globals", "cert_file"):
     371            has_pwd = config.has_option("globals", "cert_pwd")
     372            if not self.cert_file:
     373                self.cert_file = config.get("globals", "cert_file")
     374                if has_pwd:
     375                    self.cert_pwd = config.get("globals", "cert_pwd")
     376
     377        if config.get("globals", "trusted_certs") and not self.trusted_certs:
     378                self.trusted_certs = \
     379                        config.get("globals", "trusted_certs")
     380
     381        self.soap_services = { }
     382        self.xmlrpc_services = { }
     383        self.log = logging.getLogger("fedd.allocate.remote")
     384        set_log_level(config, "access", self.log)
     385        #self.dynamic_project = fedd_allocate_project_remote.dynamic_project
     386        #self.static_project = fedd_allocate_project_remote.static_project
Note: See TracChangeset for help on using the changeset viewer.