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