source: fedd/federation/access.py @ 5bf359d

axis_examplecompt_changesinfo-opsversion-3.01version-3.02
Last change on this file since 5bf359d was 06cc65b, checked in by Ted Faber <faber@…>, 15 years ago

more refactoring - beaking code into smaller chunks for digestibility

  • Property mode set to 100644
File size: 23.2 KB
Line 
1#!/usr/local/bin/python
2
3import os,sys
4import stat # for chmod constants
5import re
6import random
7import string
8import copy
9import pickle
10import logging
11import subprocess
12
13from threading import *
14from M2Crypto.SSL import SSLError
15
16from util import *
17from allocate_project import allocate_project_local, allocate_project_remote
18from access_project import access_project
19from fedid import fedid, generate_fedid
20from authorizer import authorizer
21from service_error import service_error
22from remote_service import xmlrpc_handler, soap_handler, service_caller
23
24import httplib
25import tempfile
26from urlparse import urlparse
27
28import topdl
29import list_log
30import proxy_emulab_segment
31import local_emulab_segment
32
33
34# Make log messages disappear if noone configures a fedd logger
35class nullHandler(logging.Handler):
36    def emit(self, record): pass
37
38fl = logging.getLogger("fedd.access")
39fl.addHandler(nullHandler())
40
41class access_base:
42    """
43    The implementation of access control based on mapping users to projects.
44
45    Users can be mapped to existing projects or have projects created
46    dynamically.  This implements both direct requests and proxies.
47    """
48
49    class parse_error(RuntimeError): pass
50
51    def __init__(self, config=None, auth=None):
52        """
53        Initializer.  Pulls parameters out of the ConfigParser's access section.
54        """
55
56        # Make sure that the configuration is in place
57        if not config: 
58            raise RunTimeError("No config to fedd.access")
59
60        self.project_priority = config.getboolean("access", "project_priority")
61
62        self.certdir = config.get("access","certdir")
63        self.create_debug = config.getboolean("access", "create_debug")
64        self.cleanup = not config.getboolean("access", "leave_tmpfiles")
65        self.access_type = config.get("access", "type")
66        self.log = logging.getLogger("fedd.access")
67        set_log_level(config, "access", self.log)
68        self.state_lock = Lock()
69        self.state = { }
70        # XXX: Configurable
71        self.exports = set(('SMB', 'seer', 'tmcd', 'userconfig', 
72            'project_export', 'local_seer_control', 'seer_master', 
73            'hide_hosts'))
74        self.imports = set(('SMB', 'seer', 'userconfig', 'seer_master',
75            'hide_hosts'))
76
77        if auth: self.auth = auth
78        else:
79            self.log.error(\
80                    "[access]: No authorizer initialized, creating local one.")
81            auth = authorizer()
82
83        self.state_filename = config.get("access", "access_state")
84        self.read_state()
85
86        # Keep cert_file and cert_pwd coming from the same place
87        self.cert_file = config.get("access", "cert_file")
88        if self.cert_file:
89            self.sert_pwd = config.get("access", "cert_pw")
90        else:
91            self.cert_file = config.get("globals", "cert_file")
92            self.sert_pwd = config.get("globals", "cert_pw")
93
94        self.trusted_certs = config.get("access", "trusted_certs") or \
95                config.get("globals", "trusted_certs")
96
97
98    @staticmethod
99    def software_list(v):
100        """
101        From a string containing a sequence of space separated pairs, return a
102        list of tuples with pairs of location and file.
103        """
104        l = [ ]
105        if v:
106            ps = v.split(" ")
107            while len(ps):
108                loc, file = ps[0:2]
109                del ps[0:2]
110                l.append((loc, file))
111        return l
112
113    @staticmethod
114    def add_kit(e, kit):
115        """
116        Add a Software object created from the list of (install, location)
117        tuples passed as kit  to the software attribute of an object e.  We
118        do this enough to break out the code, but it's kind of a hack to
119        avoid changing the old tuple rep.
120        """
121
122        s = [ topdl.Software(install=i, location=l) for i, l in kit]
123
124        if isinstance(e.software, list): e.software.extend(s)
125        else: e.software = s
126
127
128    def read_access(self, config, access_obj=None):
129        """
130        Read an access DB with filename config  of the form:
131            (id, id, id) -> something
132        where the ids can be fedids, strings, or <any> or <none> and somthing
133        is any set of charcters.  The hash self.access is populated with
134        mappings from those triples to the results of access_obj being called
135        on the remainder of the line.  If access_obj is not given, the string
136        itself is entered in the hash.  Additionally, a triple with <any> and
137        <none> mapped to None is entered in self.auth with the attribute
138        "access".
139
140        Parsing errors result in a self.parse_error exception being raised.
141        access_obj should throw that as well.
142        """
143        lineno=0
144        name_expr = "["+string.ascii_letters + string.digits + "\.\-_]+"
145        fedid_expr = "fedid:[" + string.hexdigits + "]+"
146        key_name = "(<ANY>|<NONE>|"+fedid_expr + "|"+ name_expr + ")"
147        access_re = re.compile('\('+key_name+'\s*,\s*'+key_name+'\s*,\s*'+
148                key_name+'\s*\)\s*->\s*(.*)', re.IGNORECASE)
149
150        def parse_name(n):
151            if n.startswith('fedid:'): return fedid(hexstr=n[len('fedid:'):])
152            else: return n
153       
154        def auth_name(n):
155            if isinstance(n, basestring):
156                if n =='<any>' or n =='<none>': return None
157                else: return unicode(n)
158            else:
159                return n
160
161        if access_obj is None:
162            access_obj = lambda(x): "%s" % x
163
164        f = open(config, "r");
165        try:
166            for line in f:
167                lineno += 1
168                line = line.strip();
169                if len(line) == 0 or line.startswith('#'):
170                    continue
171
172                # Access line (t, p, u) -> anything
173                m = access_re.match(line)
174                if m != None:
175                    access_key = tuple([ parse_name(x) \
176                            for x in m.group(1,2,3)])
177                    auth_key = tuple([ auth_name(x) for x in access_key])
178                    access_val = access_obj(m.group(4))
179
180                    self.access[access_key] = access_val
181                    self.auth.set_attribute(auth_key, "access")
182                    continue
183
184                # Nothing matched to here: unknown line - raise exception
185                f.close()
186                raise self.parse_error(
187                        "Unknown statement at line %d of %s" % \
188                        (lineno, config))
189        finally:
190            if f: f.close()
191
192    def get_users(self, obj):
193        """
194        Return a list of the IDs of the users in dict
195        """
196        if obj.has_key('user'):
197            return [ unpack_id(u['userID']) \
198                    for u in obj['user'] if u.has_key('userID') ]
199        else:
200            return None
201
202    def write_state(self):
203        if self.state_filename:
204            try:
205                f = open(self.state_filename, 'w')
206                pickle.dump(self.state, f)
207                self.log.debug("Wrote state to %s" % self.state_filename)
208            except EnvironmentError, e:
209                self.log.error("Can't write file %s: %s" % \
210                        (self.state_filename, e))
211            except pickle.PicklingError, e:
212                self.log.error("Pickling problem: %s" % e)
213            except TypeError, e:
214                self.log.error("Pickling problem (TypeError): %s" % e)
215
216
217    def read_state(self):
218        """
219        Read a new copy of access state.  Old state is overwritten.
220
221        State format is a simple pickling of the state dictionary.
222        """
223        if self.state_filename:
224            try:
225                f = open(self.state_filename, "r")
226                self.state = pickle.load(f)
227                self.log.debug("[read_state]: Read state from %s" % \
228                        self.state_filename)
229            except EnvironmentError, e:
230                self.log.warning(("[read_state]: No saved state: " +\
231                        "Can't open %s: %s") % (self.state_filename, e))
232            except EOFError, e:
233                self.log.warning(("[read_state]: " +\
234                        "Empty or damaged state file: %s:") % \
235                        self.state_filename)
236            except pickle.UnpicklingError, e:
237                self.log.warning(("[read_state]: No saved state: " + \
238                        "Unpickling failed: %s") % e)
239
240
241
242    def permute_wildcards(self, a, p):
243        """Return a copy of a with various fields wildcarded.
244
245        The bits of p control the wildcards.  A set bit is a wildcard
246        replacement with the lowest bit being user then project then testbed.
247        """
248        if p & 1: user = ["<any>"]
249        else: user = a[2]
250        if p & 2: proj = "<any>"
251        else: proj = a[1]
252        if p & 4: tb = "<any>"
253        else: tb = a[0]
254
255        return (tb, proj, user)
256
257    def find_access(self, search):
258        """
259        Search the access DB for a match on this tuple.  Return the matching
260        access tuple and the user that matched.
261       
262        NB, if the initial tuple fails to match we start inserting wildcards in
263        an order determined by self.project_priority.  Try the list of users in
264        order (when wildcarded, there's only one user in the list).
265        """
266        if self.project_priority: perm = (0, 1, 2, 3, 4, 5, 6, 7)
267        else: perm = (0, 2, 1, 3, 4, 6, 5, 7)
268
269        for p in perm: 
270            s = self.permute_wildcards(search, p)
271            # s[2] is None on an anonymous, unwildcarded request
272            if s[2] != None:
273                for u in s[2]:
274                    if self.access.has_key((s[0], s[1], u)):
275                        return (self.access[(s[0], s[1], u)], u)
276            else:
277                if self.access.has_key(s):
278                    return (self.access[s], None)
279        return None, None
280
281    def lookup_access_base(self, req, fid):
282        """
283        Determine the allowed access for this request.  Return the access and
284        which fields are dynamic.
285
286        The fedid is needed to construct the request
287        """
288        user_re = re.compile("user:\s(.*)")
289        project_re = re.compile("project:\s(.*)")
290
291        # Search keys
292        tb = fid
293        user = [ user_re.findall(x)[0] for x in req.get('credential', []) \
294                if user_re.match(x)]
295        project = [ project_re.findall(x)[0] \
296                for x in req.get('credential', []) \
297                    if project_re.match(x)]
298
299        if len(project) == 1: project = project[0]
300        elif len(project) == 0: project = None
301        else: 
302            raise service_error(service_error.req, 
303                    "More than one project credential")
304
305        # Confirm authorization
306        for u in user:
307            self.log.debug("[lookup_access] Checking access for %s" % \
308                    ((tb, project, u),))
309            if self.auth.check_attribute((tb, project, u), 'access'):
310                self.log.debug("[lookup_access] Access granted")
311                break
312            else:
313                self.log.debug("[lookup_access] Access Denied")
314        else:
315            raise service_error(service_error.access, "Access denied")
316
317        # This maps a valid user to the Emulab projects and users to use
318        found, user_match = self.find_access((tb, project, user))
319
320        return (found, (tb, project, user_match))
321       
322
323    def get_handler(self, path, fid):
324        self.log.info("Get handler %s %s" % (path, fid))
325        if self.auth.check_attribute(fid, path) and self.userconfdir:
326            return ("%s/%s" % (self.userconfdir, path), "application/binary")
327        else:
328            return (None, None)
329
330    def export_userconf(self, project):
331        dev_null = None
332        confid, confcert = generate_fedid("test", dir=self.userconfdir, 
333                log=self.log)
334        conffilename = "%s/%s" % (self.userconfdir, str(confid))
335        cf = None
336        try:
337            cf = open(conffilename, "w")
338            os.chmod(conffilename, stat.S_IRUSR | stat.S_IWUSR)
339        except EnvironmentError, e:
340            raise service_error(service_error.internal, 
341                    "Cannot create user configuration data")
342
343        try:
344            dev_null = open("/dev/null", "a")
345        except EnvironmentError, e:
346            self.log.error("export_userconf: can't open /dev/null: %s" % e)
347
348        cmd = "%s %s" % (self.userconfcmd, project)
349        conf = subprocess.call(cmd.split(" "),
350                stdout=cf, stderr=dev_null, close_fds=True)
351
352        self.auth.set_attribute(confid, "/%s" % str(confid))
353
354        return confid, confcert
355
356    def export_SMB(self, id, state, project, user, attrs):
357        return { 
358                'id': id,
359                'name': 'SMB',
360                'visibility': 'export',
361                'server': 'http://fs:139',
362                'fedAttr': [
363                        { 'attribute': 'SMBSHARE', 'value': 'USERS' },
364                        { 'attribute': 'SMBUSER', 'value': user },
365                        { 'attribute': 'SMBPROJ', 'value': project },
366                    ]
367                }
368
369    def export_seer(self, id, state, project, user, attrs):
370        return { 
371                'id': id,
372                'name': 'seer',
373                'visibility': 'export',
374                'server': 'http://control:16606',
375                }
376
377    def export_local_seer(self, id, state, project, user, attrs):
378        return { 
379                'id': id,
380                'name': 'local_seer_control',
381                'visibility': 'export',
382                'server': 'http://control:16606',
383                }
384
385    def export_seer_master(self, id, state, project, user, attrs):
386        return { 
387                'id': id,
388                'name': 'seer_master',
389                'visibility': 'export',
390                'server': 'http://seer-master:17707',
391                }
392
393    def export_tmcd(self, id, state, project, user, attrs):
394        return { 
395                'id': id,
396                'name': 'seer',
397                'visibility': 'export',
398                'server': 'http://boss:7777',
399                }
400
401    def export_userconfig(self, id, state, project, user, attrs):
402        if self.userconfdir and self.userconfcmd \
403                and self.userconfurl:
404            cid, cert = self.export_userconf(project)
405            state['userconfig'] = unicode(cid)
406            return {
407                    'id': id,
408                    'name': 'userconfig',
409                    'visibility': 'export',
410                    'server': "%s/%s" % (self.userconfurl, str(cid)),
411                    'fedAttr': [
412                        { 'attribute': 'cert', 'value': cert },
413                    ]
414                    }
415        else:
416            return None
417
418    def export_hide_hosts(self, id, state, project, user, attrs):
419        return {
420                'id': id, 
421                'name': 'hide_hosts',
422                'visibility': 'export',
423                'fedAttr': [ x for x in attrs \
424                        if x.get('attribute', "") == 'hosts'],
425                }
426
427    def export_services(self, sreq, project, user):
428        exp = [ ]
429        state = { }
430        # XXX: Filthy shortcut here using http: so urlparse will give the right
431        # answers.
432        for s in sreq:
433            sname = s.get('name', '')
434            svis = s.get('visibility', '')
435            sattrs = s.get('fedAttr', [])
436            if svis == 'export':
437                if sname in self.exports:
438                    id = s.get('id', 'no_id')
439                    if sname == 'SMB':
440                        exp.append(self.export_SMB(id, state, project, user,
441                            sattrs))
442                    elif sname == 'seer':
443                        exp.append(self.export_seer(id, state, project, user,
444                            sattrs))
445                    elif sname == 'tmcd':
446                        exp.append(self.export_tmcd(id, state, project, user,
447                            sattrs))
448                    elif sname == 'userconfig':
449                        exp.append(self.export_userconfig(id, state,
450                            project, user, sattrs))
451                    elif sname == 'project_export':
452                        exp.append(self.export_SMB(id, state, project, user,
453                            sattrs))
454                        #exp.append(self.export_seer(id, state, project, user,
455                        #sattrs))
456                        exp.append(self.export_userconfig(id, state,
457                            project, user, sattrs))
458                    elif sname == 'local_seer_control':
459                        exp.append(self.export_local_seer(id, state, project,
460                            user, sattrs))
461                    elif sname == 'seer_master':
462                        exp.append(self.export_seer_master(id, state, project,
463                            user, sattrs))
464                    elif sname == 'hide_hosts':
465                        exp.append(self.export_hide_hosts(id, state, project,
466                            user, sattrs))
467        return (exp, state)
468
469    def build_access_response(self, alloc_id, ap, services):
470        """
471        Create the SOAP response.
472
473        Build the dictionary description of the response and use
474        fedd_utils.pack_soap to create the soap message.  ap is the allocate
475        project message returned from a remote project allocation (even if that
476        allocation was done locally).
477        """
478        # Because alloc_id is already a fedd_services_types.IDType_Holder,
479        # there's no need to repack it
480        msg = { 
481                'allocID': alloc_id,
482                'fedAttr': [
483                    { 'attribute': 'domain', 'value': self.domain } , 
484                    { 'attribute': 'project', 'value': 
485                        ap['project'].get('name', {}).get('localname', "???") },
486                ]
487            }
488
489        if self.dragon_endpoint:
490            msg['fedAttr'].append({'attribute': 'dragon',
491                'value': self.dragon_endpoint})
492        if self.deter_internal:
493            print 'adding internal'
494            msg['fedAttr'].append({'attribute': 'deter_internal',
495                'value': self.deter_internal})
496        else: print "internal: %s" % self.deter_internal
497        #XXX: ??
498        if self.dragon_vlans:
499            msg['fedAttr'].append({'attribute': 'vlans',
500                'value': self.dragon_vlans})
501
502        if services:
503            msg['service'] = services
504        return msg
505
506    def generate_portal_configs(self, topo, pubkey_base, secretkey_base, 
507            tmpdir, lproj, leid, connInfo, services):
508
509        def conninfo_to_dict(key, info):
510            """
511            Make a cpoy of the connection information about key, and flatten it
512            into a single dict by parsing out any feddAttrs.
513            """
514
515            rv = None
516            for i in info:
517                if key == i.get('portal', "") or \
518                        key in [e.get('element', "") \
519                        for e in i.get('member', [])]:
520                    rv = i.copy()
521                    break
522
523            else:
524                return rv
525
526            if 'fedAttr' in rv:
527                for a in rv['fedAttr']:
528                    attr = a.get('attribute', "")
529                    val = a.get('value', "")
530                    if attr and attr not in rv:
531                        rv[attr] = val
532                del rv['fedAttr']
533            return rv
534
535        # XXX: un hardcode this
536        def client_null(f, s):
537            print >>f, "Service: %s" % s['name']
538
539        def client_seer_master(f, s):
540            print >>f, 'PortalAlias: seer-master';
541
542        def client_smb(f, s):
543            print >>f, "Service: %s" % s['name']
544            smbshare = None
545            smbuser = None
546            smbproj = None
547            for a in s.get('fedAttr', []):
548                if a.get('attribute', '') == 'SMBSHARE':
549                    smbshare = a.get('value', None)
550                elif a.get('attribute', '') == 'SMBUSER':
551                    smbuser = a.get('value', None)
552                elif a.get('attribute', '') == 'SMBPROJ':
553                    smbproj = a.get('value', None)
554
555            if all((smbshare, smbuser, smbproj)):
556                print >>f, "SMBshare: %s" % smbshare
557                print >>f, "ProjectUser: %s" % smbuser
558                print >>f, "ProjectName: %s" % smbproj
559
560        def client_hide_hosts(f, s):
561            for a in s.get('fedAttr', [ ]):
562                if a.get('attribute', "") == 'hosts':
563                    print >>f, "Hide: %s" % a.get('value', "")
564
565        client_service_out = {
566                'SMB': client_smb,
567                'tmcd': client_null,
568                'seer': client_null,
569                'userconfig': client_null,
570                'project_export': client_null,
571                'seer_master': client_seer_master,
572                'hide_hosts': client_hide_hosts,
573            }
574
575        def client_seer_master_export(f, s):
576            print >>f, "AddedNode: seer-master"
577
578        def client_seer_local_export(f, s):
579            print >>f, "AddedNode: control"
580
581        client_export_service_out = {
582                'seer_master': client_seer_master_export,
583                'local_seer_control': client_seer_local_export,
584            }
585
586        def server_port(f, s):
587            p = urlparse(s.get('server', 'http://localhost'))
588            print >>f, 'port: remote:%s:%s:%s' % (p.port, p.hostname, p.port) 
589
590        def server_null(f,s): pass
591
592        def server_seer(f, s):
593            print >>f, 'seer: True'
594
595        server_service_out = {
596                'SMB': server_port,
597                'tmcd': server_port,
598                'userconfig': server_null,
599                'project_export': server_null,
600                'seer': server_seer,
601                'seer_master': server_port,
602                'hide_hosts': server_null,
603            }
604        # XXX: end un hardcode this
605
606
607        seer_out = False
608        client_out = False
609        mproj = None
610        mexp = None
611        control_gw = None
612        testbed = ""
613        # Create configuration files for the portals
614        for e in [ e for e in topo.elements \
615                if isinstance(e, topdl.Computer) and e.get_attribute('portal')]:
616            myname = e.name
617            type = e.get_attribute('portal_type')
618
619            info = conninfo_to_dict(myname, connInfo)
620
621            if not info:
622                raise service_error(service_error.req,
623                        "No connectivity info for %s" % myname)
624
625            peer = info.get('peer', "")
626            ldomain = self.domain;
627            ssh_port = info.get('ssh_port', 22)
628
629            # Collect this for the client.conf file
630            if 'masterexperiment' in info:
631                mproj, meid = info['masterexperiment'].split("/", 1)
632
633            if type in ('control', 'both'):
634                testbed = e.get_attribute('testbed')
635                control_gw = myname
636
637            active = info.get('active', 'False')
638
639            cfn = "%s/%s.gw.conf" % (tmpdir, myname.lower())
640            tunnelconfig = self.tunnel_config
641            try:
642                f = open(cfn, "w")
643                if active == 'True':
644                    print >>f, "active: True"
645                    print >>f, "ssh_port: %s" % ssh_port
646                    if type in ('control', 'both'):
647                        for s in [s for s in services \
648                                if s.get('name', "") in self.imports]:
649                            server_service_out[s['name']](f, s)
650
651                if tunnelconfig:
652                    print >>f, "tunnelip: %s" % tunnelconfig
653                print >>f, "peer: %s" % peer.lower()
654                print >>f, "ssh_pubkey: /proj/%s/exp/%s/tmp/%s" % \
655                        (lproj, leid, pubkey_base)
656                print >>f, "ssh_privkey: /proj/%s/exp/%s/tmp/%s" % \
657                        (lproj, leid, secretkey_base)
658                f.close()
659            except EnvironmentError, e:
660                raise service_error(service_error.internal,
661                        "Can't write protal config %s: %s" % (cfn, e))
662
663        # Done with portals, write the client config file.
664        try:
665            f = open("%s/client.conf" % tmpdir, "w")
666            if control_gw:
667                print >>f, "ControlGateway: %s.%s.%s%s" % \
668                    (myname.lower(), leid.lower(), lproj.lower(),
669                            ldomain.lower())
670            for s in services:
671                if s.get('name',"") in self.imports and \
672                        s.get('visibility','') == 'import':
673                    client_service_out[s['name']](f, s)
674                if s.get('name', '') in self.exports and \
675                        s.get('visibility', '') == 'export' and \
676                        s['name'] in client_export_service_out:
677                    client_export_service_out[s['name']](f, s)
678            # Seer uses this.
679            if mproj and meid:
680                print >>f, "ExperimentID: %s/%s" % (mproj, meid)
681            f.close()
682        except EnvironmentError, e:
683            raise service_error(service_error.internal,
684                    "Cannot write client.conf: %s" %s)
685
686    def export_store_info(self, cf, proj, ename, connInfo):
687        """
688        For the export requests in the connection info, install the peer names
689        at the experiment controller via SetValue calls.
690        """
691
692        for c in connInfo:
693            for p in [ p for p in c.get('parameter', []) \
694                    if p.get('type', '') == 'output']:
695
696                if p.get('name', '') == 'peer':
697                    k = p.get('key', None)
698                    surl = p.get('store', None)
699                    if surl and k and k.index('/') != -1:
700                        value = "%s.%s.%s%s" % \
701                                (k[k.index('/')+1:], ename, proj, self.domain)
702                        req = { 'name': k, 'value': value }
703                        self.log.debug("Setting %s to %s on %s" % \
704                                (k, value, surl))
705                        self.call_SetValue(surl, req, cf)
706                    else:
707                        self.log.error("Bad export request: %s" % p)
708                elif p.get('name', '') == 'ssh_port':
709                    k = p.get('key', None)
710                    surl = p.get('store', None)
711                    if surl and k:
712                        req = { 'name': k, 'value': self.ssh_port }
713                        self.log.debug("Setting %s to %s on %s" % \
714                                (k, self.ssh_port, surl))
715                        self.call_SetValue(surl, req, cf)
716                    else:
717                        self.log.error("Bad export request: %s" % p)
718                else:
719                    self.log.error("Unknown export parameter: %s" % \
720                            p.get('name'))
721                    continue
722
723    def import_store_info(self, cf, connInfo):
724        """
725        Pull any import parameters in connInfo in.  We translate them either
726        into known member names or fedAddrs.
727        """
728
729        for c in connInfo:
730            for p in [ p for p in c.get('parameter', []) \
731                    if p.get('type', '') == 'input']:
732                name = p.get('name', None)
733                key = p.get('key', None)
734                store = p.get('store', None)
735
736                if name and key and store :
737                    req = { 'name': key, 'wait': True }
738                    self.log.debug("Waiting for %s (%s) from %s" % \
739                            (name, key, store))
740                    r = self.call_GetValue(store, req, cf)
741                    r = r.get('GetValueResponseBody', None)
742                    if r :
743                        if r.get('name', '') == key:
744                            v = r.get('value', None)
745                            if v is not None:
746                                if name == 'peer':
747                                    self.log.debug("Got peer %s" % v)
748                                    c['peer'] = v
749                                else:
750                                    self.log.debug("Got %s %s" % (name, v))
751                                    if c.has_key('fedAttr'):
752                                        c['fedAttr'].append({
753                                            'attribute': name, 'value': v})
754                                    else:
755                                        c['fedAttr']= [{
756                                            'attribute': name, 'value': v}]
757                            else:
758                                raise service_error(service_error.internal, 
759                                        'None value exported for %s'  % key)
760                        else:
761                            raise service_error(service_error.internal, 
762                                    'Different name returned for %s: %s' \
763                                            % (key, r.get('name','')))
764                    else:
765                        raise service_error(service_error.internal, 
766                            'Badly formatted response: no GetValueResponseBody')
767                else:
768                    raise service_error(service_error.internal, 
769                        'Bad Services missing info for import %s' % c)
Note: See TracBrowser for help on using the repository browser.