source: fedd/federation/geniapi_proxy.py @ 5ae9d94

compt_changes
Last change on this file since 5ae9d94 was 6bedbdba, checked in by Ted Faber <faber@…>, 13 years ago

Split topdl and fedid out to different packages. Add differential
installs

  • Property mode set to 100644
File size: 4.1 KB
Line 
1#!/usr/local/bin/python
2
3import os,sys
4
5from M2Crypto.SSL import SSLError
6from M2Crypto.m2xmlrpclib import SSL_Transport
7from service_error import service_error
8from xmlrpclib import ServerProxy, Fault, Error
9
10
11from protogeni_proxy import protogeni_proxy
12
13from deter import topdl
14import list_log
15
16class geniapi_proxy(protogeni_proxy):
17    '''
18    This exports the same interface as the protogeni_proxy, but uses GENIAPI
19    calls when avaliable.  These calls are currently only available only for
20    the component manager/aggregate manager.  The keyword arguments of the
21    ProtoGENI interface are converted into XMLRPC positional parameters on
22    GENIAPI calls.  Tables to do that are established in the constructior.
23    '''
24    def __init__(self, log=None, keyfile=None, debug=False, 
25            ch_url=None, sa_url=None, cm_url=None):
26        protogeni_proxy.__init__(self, log, keyfile, debug, ch_url, sa_url,
27                cm_url)
28
29        def get_key(k, d):
30            '''
31            Return a function that takes a dict and returns the value bound to
32            key k or the default d
33            '''
34            return lambda x : x.get(k, d)
35
36        def user_filter(params):
37            '''
38            Take a dict assumed to hold a key 'users' that is a dict of a urn
39            (keyed by 'urn' and a list of dicts describing ssh keys (keyed by
40            'key'.  Construct a list of dicts with the same 'urn' and a 'keys'
41            value holding only the 'key' value of the subdict.  This converts
42            ProtoGENI users to GENIAPI users.
43            '''
44
45            # That conversion is a nested list comprehension.
46            return [ { 
47                'urn': u.get('urn', ''), 
48                'keys': [ k.get('key', '') for k in u.get('keys', []) ] 
49                } for u in params.get('users', [])]
50
51        self.ProtoGENIError = protogeni_proxy.ProtoGENIError
52        # These ProtoGENI requests are mapped to the given GENIAPI request.
53        self.method_map = { 
54                'DeleteSlice': 'DeleteSliver',
55                'RenewSlice': 'RenewSliver',
56                }
57        # Conversion tables for changing the dict of keyword arguments into a
58        # list of arguments for GENIAPI.  The list of positional params is
59        # created by calling the functions in the dict below (keyed by the
60        # requested function) in order on the params dict, placing the results
61        # into the arguments list.  The list so constructed is the positional
62        # parameters in order.  Mostly this is just putting the right key in
63        # the right place, but the users choice is actually reformatted some.
64        # This dict is indexed by ProtoGENI method.
65        self.arg_map = {
66                'CreateSliver': [
67                    get_key('slice_urn', ''), 
68                    get_key('credentials', []), 
69                    get_key('rspec', ''), 
70                    user_filter ],
71                'SliverStatus': [
72                    get_key('slice_urn', ''),
73                    get_key('credentials','') ],
74                'DeleteSlice': [
75                    get_key('slice_urn', ''),
76                    get_key('credentials','') ],
77                'RenewSlice': [
78                    get_key('slice_urn', ''),
79                    get_key('credentials','') ],
80                }
81
82    def geniapi_call(self, url, method, params, context):
83        '''
84        Make an SSL authenticated (and encrypted) GENIAPI call on the given url.
85        '''
86        try:
87            if self.log:
88                self.log.debug("Calling %s %s" % (url, method))
89            transport = SSL_Transport(context)
90            port = ServerProxy(url, transport=transport)
91            remote_method = getattr(port, method, None)
92            if remote_method is not None:
93                return remote_method(*params)
94            else:
95                raise service_error(service_error.internal, 
96                        "Bad method: %s" % method)
97        except Fault, f:
98            raise service_error(f.faultCode, f.faultString)
99        except Error, e:
100            raise service_error(service_error.protocol, 
101                    "Remote XMLRPC Fault: %s" % e)
102        except:
103            raise self.ProtoGENIError(op=method, code=-1, 
104                    output="%s" % sys.exc_info()[1])
105
106
107    def component_manager_call(self, method, params, context):
108        '''
109        Convert the ProtoGENI call into a GENIAPI call using the translation
110        tables above.
111        '''
112        if not self.debug:
113            gmethod = self.method_map.get(method, method)
114            gparams = [f(params) for f in self.arg_map.get(method, [])]
115
116            return self.geniapi_call(self.cm_url, gmethod, gparams, context)
117        else:
118            if method in self.debug_fail:
119                raise self.ProtoGENIError(op=method, code='unknown',
120                        output='No output')
121            elif self.debug_response.has_key(method):
122                return self.debug_response[method]
123            else:
124                return "%s XML blob" % method
125
126
Note: See TracBrowser for help on using the repository browser.