remove debugging output
[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 from sfa.util.faults import *
7 from sfa.util.storage import *
8 from sfa.util.namespace import *
9 from sfa.trust.gid import GID
10 from sfa.util.table import SfaTable
11 from sfa.util.record import SfaRecord
12 import traceback
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         self.type = type  
58         # load config file
59         self.interface_info = XmlStorage(conf_file, self.default_dict)
60         self.interface_info.load()
61         interfaces = self.interface_info.values()[0].values()[0]
62         if not isinstance(interfaces, list):
63             interfaces = [self.interfaces]
64         self.interfaces = {}
65         for interface in interfaces:
66             self.interfaces[interface['hrn']] = interface
67
68         # get connections
69         self.update(self.get_connections(self.interfaces))
70
71     def sync_interfaces(self):
72         """
73         Install missing trusted gids and db records for our federated
74         interfaces
75         """     
76         # Attempt to get any missing peer gids
77         # There should be a gid file in /etc/sfa/trusted_roots for every
78         # peer registry found in in the registries.xml config file. If there
79         # are any missing gids, request a new one from the peer registry.
80         gids_current = self.api.auth.trusted_cert_list
81         hrns_current = [gid.get_hrn() for gid in gids_current] 
82         hrns_expected = self.interfaces.keys() 
83         new_hrns = set(hrns_expected).difference(hrns_current)
84         gids = self.get_peer_gids(new_hrns)
85         # update the local db records for these registries
86         self.update_db_records(self.type, gids)
87         
88     def get_peer_gids(self, new_hrns):
89         """
90         Install trusted gids from the specified interfaces.  
91         """
92         peer_gids = []
93         if not new_hrns:
94             return peer_gids
95         trusted_certs_dir = self.api.config.get_trustedroots_dir()
96         for new_hrn in new_hrns:
97             # the gid for this interface should already be installed  
98             if new_hrn == self.api.config.SFA_INTERFACE_HRN:
99                 continue
100             try:
101                 # get gid from the registry
102                 interface_info =  self.interfaces[new_hrn]
103                 interface = self.get_connections(self.interfaces[new_hrn])[new_hrn]
104                 trusted_gids = interface.get_trusted_certs()
105                 # default message
106                 message = "interface: %s\tunable to install trusted gid for %s" % \
107                            (self.api.interface, new_hrn) 
108                 if trusted_gids:
109                     # the gid we want shoudl be the first one in the list, 
110                     # but lets make sure
111                     for trusted_gid in trusted_gids:
112                         gid = GID(string=trusted_gids[0])
113                         peer_gids.append(gid) 
114                         if gid.get_hrn() == new_hrn:
115                             gid_filename = os.path.join(trusted_certs_dir, '%s.gid' % new_hrn)
116                             gid.save_to_file(gid_filename, save_parents=True)
117                             message = "interface: %s\tinstalled trusted gid for %s" % \
118                                 (self.api.interface, new_hrn)
119                 # log the message
120                 self.api.logger.info(message)
121             except:
122                 message = "interface: %s\tunable to install trusted gid for %s" % \
123                             (self.api.interface, new_hrn) 
124                 self.api.logger.info(message)
125                 traceback.print_exc()
126         
127         # reload the trusted certs list
128         self.api.auth.load_trusted_certs()
129         return peer_gids
130
131     def update_db_records(self, type, gids):
132         """
133         Make sure there is a record in the local db for allowed registries
134         defined in the config file (registries.xml). Removes old records from
135         the db.         
136         """
137         if not gids: 
138             return
139         # get hrns we expect to find
140         # ignore records for local interfaces
141         ignore_interfaces = [self.api.config.SFA_INTERFACE_HRN]
142         hrns_expected = [gid.get_hrn() for gid in gids \
143                          if gid.get_hrn() not in ignore_interfaces]
144
145         # get hrns that actually exist in the db
146         table = SfaTable()
147         records = table.find({'type': type})
148         hrns_found = [record['hrn'] for record in records]
149        
150         # remove old records
151         for record in records:
152             if record['hrn'] not in hrns_expected:
153                 table.remove(record)
154
155         # add new records
156         for gid in gids:
157             hrn = gid.get_hrn()
158             if hrn not in hrns_found:
159                 record = {
160                     'hrn': hrn,
161                     'type': type,
162                     'pointer': -1, 
163                     'authority': get_authority(hrn),
164                     'gid': gid.save_to_string(save_parents=True),
165                 }
166                 record = SfaRecord(dict=record)
167                 table.insert(record)
168                         
169     def get_connections(self, interfaces):
170         """
171         read connection details for the trusted peer registries from file return 
172         a dictionary of connections keyed on interface hrn. 
173         """
174         connections = {}
175         required_fields = self.default_fields.keys()
176         if not isinstance(interfaces, list):
177             interfaces = [interfaces]
178         for interface in interfaces:
179             # make sure the required fields are present and not null
180             if not all([interface.get(key) for key in required_fields]):
181                 continue
182  
183             hrn, address, port = interface['hrn'], interface['addr'], interface['port']
184             url = 'http://%(address)s:%(port)s' % locals()
185             # check which client we should use
186             # sfa.util.xmlrpcprotocol is default
187             client_type = 'xmlrpcprotocol'
188             if interface.has_key('client') and \
189                interface['client'] in ['geniclientlight'] and \
190                GeniClientLight:
191                 client_type = 'geniclientlight'
192                 connections[hrn] = GeniClientLight(url, self.api.key_file, self.api.cert_file) 
193             else:
194                 connections[hrn] = xmlrpcprotocol.get_server(url, self.api.key_file, self.api.cert_file)
195
196         return connections