Tony fix to the sfa- start bug when aggregates.xml holds peer information .
[sfa.git] / sfa / server / sfa-start.py
1 #!/usr/bin/python
2 #
3 # PlanetLab SFA implementation
4 #
5 # This implements the SFA Registry and Slice Interfaces on PLC.
6 # Depending on command line options, it starts some combination of a
7 # Registry, an Aggregate Manager, and a Slice Manager.
8 #
9 # There are several items that need to be done before starting the servers.
10 #
11 # NOTE:  Many configuration settings, including the PLC maintenance account
12 # credentials, URI of the PLCAPI, and PLC DB URI and admin credentials are initialized
13 # from your MyPLC configuration (/etc/planetlab/plc_config*).  Please make sure this information
14 # is up to date and accurate.
15 #
16 # 1) Import the existing planetlab database, creating the
17 #    appropriate SFA records. This is done by running the "sfa-import-plc.py" tool.
18 #
19 # 2) Create a "trusted_roots" directory and place the certificate of the root
20 #    authority in that directory. Given the defaults in sfa-import-plc.py, this
21 #    certificate would be named "planetlab.gid". For example,
22 #
23 #    mkdir trusted_roots; cp authorities/planetlab.gid trusted_roots/
24 #
25 # TODO: Can all three servers use the same "registry" certificate?
26 ##
27
28 ### xxx todo not in the config yet
29 component_port=12346
30 import os, os.path
31 import traceback
32 import sys
33 from optparse import OptionParser
34
35 from sfa.util.sfalogging import logger
36 from sfa.util.xrn import get_authority, hrn_to_urn
37 from sfa.util.config import Config
38 from sfa.trust.gid import GID
39 from sfa.trust.trustedroots import TrustedRoots
40 from sfa.trust.certificate import Keypair, Certificate
41 from sfa.trust.hierarchy import Hierarchy
42 from sfa.trust.gid import GID
43
44 from sfa.server.sfaapi import SfaApi
45 from sfa.server.registry import Registries
46 from sfa.server.aggregate import Aggregates
47 from sfa.client.return_value import ReturnValue
48
49 # after http://www.erlenstar.demon.co.uk/unix/faq_2.html
50 def daemon():
51     """Daemonize the current process."""
52     if os.fork() != 0: os._exit(0)
53     os.setsid()
54     if os.fork() != 0: os._exit(0)
55     os.umask(0)
56     devnull = os.open(os.devnull, os.O_RDWR)
57     os.dup2(devnull, 0)
58     # xxx fixme - this is just to make sure that nothing gets stupidly lost - should use devnull
59     logdir='/var/log/httpd'
60     # when installed in standalone we might not have httpd installed
61     if not os.path.isdir(logdir): os.mkdir('/var/log/httpd')
62     crashlog = os.open('%s/sfa_access_log'%logdir, os.O_RDWR | os.O_APPEND | os.O_CREAT, 0644)
63     os.dup2(crashlog, 1)
64     os.dup2(crashlog, 2)
65
66
67 def install_peer_certs(server_key_file, server_cert_file):
68     """
69     Attempt to install missing trusted gids and db records for 
70     our federated interfaces
71     """
72     # Attempt to get any missing peer gids
73     # There should be a gid file in /etc/sfa/trusted_roots for every
74     # peer registry found in in the registries.xml config file. If there
75     # are any missing gids, request a new one from the peer registry.
76     print>>sys.stderr, " \r\n \r\n \t=============================================== install_peer_certs server_key_file  %s  server_cert_file %s"%(server_key_file,server_cert_file)
77     api = SfaApi(key_file = server_key_file, cert_file = server_cert_file)
78     registries = Registries()
79     aggregates = Aggregates()
80     interfaces = dict(registries.items() + aggregates.items())
81     gids_current = api.auth.trusted_cert_list
82     hrns_current = [gid.get_hrn() for gid in gids_current]
83     hrns_expected = set([hrn for hrn in interfaces])
84     new_hrns = set(hrns_expected).difference(hrns_current)
85     #gids = self.get_peer_gids(new_hrns) + gids_current
86     peer_gids = []
87     if not new_hrns:
88         return 
89     print>>sys.stderr," \r\n \r\n \t=============================================== install_peer_certs interfaces %s  api.config.SFA_INTERFACE_HRN %s  new_hrns %s" %( interfaces,api.config.SFA_INTERFACE_HRN,new_hrns)
90     trusted_certs_dir = api.config.get_trustedroots_dir()
91     for new_hrn in new_hrns: 
92         if not new_hrn: continue
93         # the gid for this interface should already be installed
94         if new_hrn == api.config.SFA_INTERFACE_HRN: continue
95         try:
96             # get gid from the registry
97             url = interfaces[new_hrn].get_url()
98             interface = interfaces[new_hrn].server_proxy(server_key_file, server_cert_file, timeout=30)
99             # skip non sfa aggregates
100             print>>sys.stderr, " \r\n \r\n \t=============================================== install_peer_certs IIIinterface  %s url %s" %(interface,url)
101             server_version = api.get_cached_server_version(interface)
102             print>>sys.stderr, " \r\n \r\n \t=============================================== install_peer_certs server_version  %s \r\n \r\rn \t\t =============================================== server_version['sfa'] %s, " %(server_version, server_version['sfa'])
103             if 'sfa' not in server_version:
104                 logger.info("get_trusted_certs: skipping non sfa aggregate: %s" % new_hrn)
105                 continue
106             trusted_gids = ReturnValue.get_value(interface.get_trusted_certs())
107             #trusted_gids = interface.get_trusted_certs()
108             print>>sys.stderr, " \r\n \r\n \t=============================================== install_peer_certs  TRUSTED_GIDS %s   " %(trusted_gids)
109             if trusted_gids:
110                  #and not isinstance(trusted_gids,list):
111                 # the gid we want should be the first one in the list,
112                 # but lets make sure
113                 #trusted_gids = [trusted_gids]
114                 print>>sys.stderr, " \r\n \r\n \t=============================================== install_peer_certs  TRUSTED_GIDS %s   " %(trusted_gids)
115                 for trusted_gid in trusted_gids: 
116                     print>>sys.stderr, " \r\n \r\n \t=============================================== install_peer_certs  trusted_gids%s   " %(trusted_gid)
117                     # default message
118                     message = "interface: %s\t" % (api.interface)
119                     message += "unable to install trusted gid for %s" % \
120                                (new_hrn) 
121                     print>>sys.stderr, " \r\n \r\n \t=============================================== install_peer_certs   message %s   " %(message)
122                     #gid = GID(string=trusted_gids[0])
123                     gid = GID(string=trusted_gid)
124                     print>>sys.stderr, " \r\n \r\n \t=============================================== install_peer_certs   gid %s   " %(gid)
125                     peer_gids.append(gid)
126                     if gid.get_hrn() == new_hrn:
127                         gid_filename = os.path.join(trusted_certs_dir, '%s.gid' % new_hrn)
128                         gid.save_to_file(gid_filename, save_parents=True)
129                         message = "installed trusted cert for %s" % new_hrn
130                     # log the message
131                     api.logger.info(message)
132         except:
133             message = "interface: %s\tunable to install trusted gid for %s" % \
134                         (api.interface, new_hrn)
135             api.logger.log_exc(message)
136     # doesnt matter witch one
137     update_cert_records(peer_gids)
138
139 def update_cert_records(gids):
140     """
141     Make sure there is a record in the registry for the specified gids. 
142     Removes old records from the db.
143     """
144     # import SfaTable here so this module can be loaded by PlcComponentApi
145     from sfa.storage.table import SfaTable
146     from sfa.storage.record import SfaRecord
147     if not gids:
148         return
149     table = SfaTable()
150     # get records that actually exist in the db
151     gid_urns = [gid.get_urn() for gid in gids]
152     hrns_expected = [gid.get_hrn() for gid in gids]
153     records_found = table.find({'hrn': hrns_expected, 'pointer': -1}) 
154
155     # remove old records
156     for record in records_found:
157         if record['hrn'] not in hrns_expected and \
158             record['hrn'] != self.api.config.SFA_INTERFACE_HRN:
159             table.remove(record)
160
161     # TODO: store urn in the db so we do this in 1 query 
162     for gid in gids:
163         hrn, type = gid.get_hrn(), gid.get_type()
164         print>>sys.stderr, " \r\n \r\n  update_cert_records  hrn,%s type %s"%(hrn, type)       
165         record = table.find({'hrn': hrn, 'type': type, 'pointer': -1})
166         if not record:
167             record = {
168                 'hrn': hrn, 'type': type, 'pointer': -1,
169                 'authority': get_authority(hrn),
170                 'gid': gid.save_to_string(save_parents=True),
171             }
172             record = SfaRecord(dict=record)
173             print>>sys.stderr, " \r\n \r\rn record %s "%(record)
174             table.insert(record)
175         
176 def main():
177     # Generate command line parser
178     parser = OptionParser(usage="sfa-start.py [options]")
179     parser.add_option("-r", "--registry", dest="registry", action="store_true",
180          help="run registry server", default=False)
181     parser.add_option("-s", "--slicemgr", dest="sm", action="store_true",
182          help="run slice manager", default=False)
183     parser.add_option("-a", "--aggregate", dest="am", action="store_true",
184          help="run aggregate manager", default=False)
185     parser.add_option("-c", "--component", dest="cm", action="store_true",
186          help="run component server", default=False)
187     parser.add_option("-t", "--trusted-certs", dest="trusted_certs", action="store_true",
188          help="refresh trusted certs", default=False)
189     parser.add_option("-d", "--daemon", dest="daemon", action="store_true",
190          help="Run as daemon.", default=False)
191     (options, args) = parser.parse_args()
192     
193     config = Config()
194     logger.setLevelFromOptVerbose(config.SFA_API_LOGLEVEL)
195     
196
197     # ge the server's key and cert
198     hierarchy = Hierarchy()
199     auth_info = hierarchy.get_interface_auth_info()
200     server_key_file = auth_info.get_privkey_filename()
201     server_cert_file = auth_info.get_gid_filename() 
202     print>>sys.stderr, " \r\n \t\t\t\t\t SFA-START MAIN auth_info %s server_key_file %s server_cert_file %s "%(auth_info, server_key_file,server_cert_file)
203     # ensure interface cert is present in trusted roots dir
204     trusted_roots = TrustedRoots(config.get_trustedroots_dir())
205     trusted_roots.add_gid(GID(filename=server_cert_file))
206     if (options.daemon):  daemon()
207     
208     if options.trusted_certs:
209         install_peer_certs(server_key_file, server_cert_file)   
210     
211     # start registry server
212     if (options.registry):
213         from sfa.server.registry import Registry
214         r = Registry("", config.SFA_REGISTRY_PORT, server_key_file, server_cert_file)
215         r.start()
216
217     if (options.am):
218         from sfa.server.aggregate import Aggregate
219         a = Aggregate("", config.SFA_AGGREGATE_PORT, server_key_file, server_cert_file)
220         a.start()
221
222     # start slice manager
223     if (options.sm):
224         from sfa.server.slicemgr import SliceMgr
225         s = SliceMgr("", config.SFA_SM_PORT, server_key_file, server_cert_file)
226         s.start()
227
228     if (options.cm):
229         from sfa.server.component import Component
230         c = Component("", config.component_port, server_key_file, server_cert_file)
231 #        c = Component("", config.SFA_COMPONENT_PORT, server_key_file, server_cert_file)
232         c.start()
233
234 if __name__ == "__main__":
235     try:
236         main()
237     except:
238         logger.log_exc_critical("SFA server is exiting")