fix bugs, typos
[sfa.git] / sfa / server / interface.py
1 #
2 ### $Id: interface.py 17583 2010-04-06 15:01:08Z tmack $
3 ### $URL: https://svn.planet-lab.org/svn/sfa/trunk/sfa/server/interface.py $
4 #
5
6
7 from sfa.util.faults import *
8 from sfa.util.storage import *
9 from sfa.util.namespace import *
10 from sfa.trust.gid import GID
11 from sfa.util.table import SfaTable
12 from sfa.util.record import SfaRecord
13 import sfa.util.xmlrpcprotocol as xmlrpcprotocol
14 import sfa.util.soapprotocol as soapprotocol
15
16  
17 # GeniLight client support is optional
18 try:
19     from egeni.geniLight_client import *
20 except ImportError:
21     GeniClientLight = None            
22
23
24 ##
25 # In is a dictionary of registry connections keyed on the registry
26 # hrn
27
28 class Interfaces(dict):
29     """
30     Interfaces is a base class for managing information on the
31     peers we are federated with. It is responsible for the following:
32
33     1) Makes sure a record exist in the local registry for the each 
34        fedeated peer   
35     2) Attepts to fetch and install trusted gids   
36     3) Provides connections (xmlrpc or soap) to federated peers
37     """
38
39     # fields that must be specified in the config file
40     default_fields = {
41         'hrn': '',
42         'addr': '', 
43         'port': '', 
44     }
45
46     # defined by the class 
47     default_dict = {}
48
49     # allowed types
50     types = ['sa', 'ma']
51
52     def __init__(self, api, conf_file, type):
53         if type not in self.types:
54             raise SfaInfaildArgument('Invalid type %s: must be in %s' % (type, self.types))    
55         dict.__init__(self, {})
56         self.api = api
57         
58         # load config file
59         self.interface_info = XmlStorage(conf_file, self.default_dict)
60         self.interface_info.load()
61         self.interfaces = self.interface_info.values()[0].values()[0]
62         if not isinstance(self.interfaces, list):
63             self.interfaces = [self.interfaces]
64         
65         # Attempt to get any missing peer gids
66         # There should be a gid file in /etc/sfa/trusted_roots for every
67         # peer registry found in in the registries.xml config file. If there
68         # are any missing gids, request a new one from the peer registry.
69         gids_current = self.api.auth.trusted_cert_list
70         hrns_current = [gid.get_hrn() for gid in gids_current] 
71         hrns_expected = [interface['hrn'] for interface in self.interfaces] 
72         new_hrns = set(hrns_expected).difference(hrns_current)
73         self.get_peer_gids(new_hrns)
74
75         # update the local db records for these registries
76         self.update_db_records(type)
77         
78         # create connections to the registries
79         self.update(self.get_connections(self.interfaces))
80
81     def get_peer_gids(self, new_hrns):
82         """
83         Install trusted gids from the specified interfaces.  
84         """
85         if not new_hrns:
86             return
87         trusted_certs_dir = self.api.config.get_trustedroots_dir()
88         for new_hrn in new_hrns:
89             # the gid for this interface should already be installed  
90             if new_hrn == self.api.config.SFA_INTERFACE_HRN:
91                 continue
92             try:
93                 # get gid from the registry
94                 interface = self.get_connections(self.interfaces[new_hrn])[new_hrn]
95                 trusted_gids = interface.get_trusted_certs()
96                 # default message
97                 message = "interface: %s\tunable to install trusted gid for %s" % \
98                            (self.api.interface, new_hrn) 
99                 if trusted_gids:
100                     # the gid we want shoudl be the first one in the list, 
101                     # but lets make sure
102                     for trusted_gid in trusted_gids:
103                         gid = GID(string=trusted_gids[0])
104                         if gid.get_hrn() == new_hrn:
105                             gid_filename = os.path.join(trusted_certs_dir, '%s.gid' % new_hrn)
106                             gid.save_to_file(gid_filename, save_parents=True)
107                             message = "interface: %s\tinstalled trusted gid for %s" % \
108                                 (self.api.interface, new_hrn)
109                 # log the message
110                 self.api.logger.info(message)
111             except:
112                 message = "interface: %s\tunable to install trusted gid for %s" % \
113                             (self.api.interface, new_hrn) 
114                 self.api.logger.info(message)
115         
116         # reload the trusted certs list
117         self.api.auth.load_trusted_certs()
118
119     def update_db_records(self, type):
120         """
121         Make sure there is a record in the local db for allowed registries
122         defined in the config file (registries.xml). Removes old records from
123         the db.         
124         """
125         # get hrns we expect to find
126         hrns_expected = [interface['hrn'] for interface in self.interfaces]
127
128         # get hrns that actually exist in the db
129         table = SfaTable()
130         records = table.find({'type': type})
131         hrns_found = [record['hrn'] for record in records]
132        
133         # remove old records
134         for record in records:
135             if record['hrn'] not in hrns_expected:
136                 table.remove(record)
137
138         # add new records
139         for hrn in hrns_expected:
140             if hrn not in hrns_found:
141                 record = {
142                     'hrn': hrn,
143                     'type': type,
144                     'pointer': -1, 
145                     'authority': get_authority(hrn),
146                 }
147                 record = SfaRecord(dict=record)
148                 table.insert(record)
149                         
150  
151     def get_connections(self, interfaces):
152         """
153         read connection details for the trusted peer registries from file return 
154         a dictionary of connections keyed on interface hrn. 
155         """
156         connections = {}
157         required_fields = self.default_fields.keys()
158         if not isinstance(interfaces, list):
159             interfaces = [interfaces]
160         for interface in interfaces:
161             # make sure the required fields are present and not null
162             for key in required_fields:
163                 if not interface.get(key):
164                     continue 
165             hrn, address, port = interface['hrn'], interface['addr'], interface['port']
166             url = 'http://%(address)s:%(port)s' % locals()
167             # check which client we should use
168             # sfa.util.xmlrpcprotocol is default
169             client_type = 'xmlrpcprotocol'
170             if interface.has_key('client') and \
171                interface['client'] in ['geniclientlight'] and \
172                GeniClientLight:
173                 client_type = 'geniclientlight'
174                 connections[hrn] = GeniClientLight(url, self.api.key_file, self.api.cert_file) 
175             else:
176                 connections[hrn] = xmlrpcprotocol.get_server(url, self.api.key_file, self.api.cert_file)
177
178         return connections