Debugging federation functions on senslab/senslab2.
[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
48 # after http://www.erlenstar.demon.co.uk/unix/faq_2.html
49 def daemon():
50     """Daemonize the current process."""
51     if os.fork() != 0: os._exit(0)
52     os.setsid()
53     if os.fork() != 0: os._exit(0)
54     os.umask(0)
55     devnull = os.open(os.devnull, os.O_RDWR)
56     os.dup2(devnull, 0)
57     # xxx fixme - this is just to make sure that nothing gets stupidly lost - should use devnull
58     logdir='/var/log/httpd'
59     # when installed in standalone we might not have httpd installed
60     if not os.path.isdir(logdir): os.mkdir('/var/log/httpd')
61     crashlog = os.open('%s/sfa_access_log'%logdir, os.O_RDWR | os.O_APPEND | os.O_CREAT, 0644)
62     os.dup2(crashlog, 1)
63     os.dup2(crashlog, 2)
64
65
66 def install_peer_certs(server_key_file, server_cert_file):
67     """
68     Attempt to install missing trusted gids and db records for 
69     our federated interfaces
70     """
71     # Attempt to get any missing peer gids
72     # There should be a gid file in /etc/sfa/trusted_roots for every
73     # peer registry found in in the registries.xml config file. If there
74     # are any missing gids, request a new one from the peer registry.
75     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)
76     api = SfaApi(key_file = server_key_file, cert_file = server_cert_file)
77     registries = Registries()
78     aggregates = Aggregates()
79     interfaces = dict(registries.items() + aggregates.items())
80     gids_current = api.auth.trusted_cert_list
81     hrns_current = [gid.get_hrn() for gid in gids_current]
82     hrns_expected = set([hrn for hrn in interfaces])
83     new_hrns = set(hrns_expected).difference(hrns_current)
84     #gids = self.get_peer_gids(new_hrns) + gids_current
85     peer_gids = []
86     if not new_hrns:
87         return 
88     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)
89     trusted_certs_dir = api.config.get_trustedroots_dir()
90     for new_hrn in new_hrns: 
91         if not new_hrn: continue
92         # the gid for this interface should already be installed
93         if new_hrn == api.config.SFA_INTERFACE_HRN: continue
94         try:
95             # get gid from the registry
96             url = interfaces[new_hrn].get_url()
97             interface = interfaces[new_hrn].server_proxy(server_key_file, server_cert_file, timeout=30)
98             # skip non sfa aggregates
99             print>>sys.stderr, " \r\n \r\n \t=============================================== install_peer_certs IIIinterface  %s url %s" %(interface,url)
100             server_version = api.get_cached_server_version(interface)
101             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'])
102             if 'sfa' not in server_version:
103                 logger.info("get_trusted_certs: skipping non sfa aggregate: %s" % new_hrn)
104                 continue
105       
106             trusted_gids = interface.get_trusted_certs()
107             print>>sys.stderr, " \r\n \r\n \t=============================================== install_peer_certs  TRUSTED_GIDS %s   " %(trusted_gids)
108             if trusted_gids and not isinstance(trusted_gids,list):
109                 # the gid we want should be the first one in the list,
110                 # but lets make sure
111                 trusted_gids = [trusted_gids]
112                 print>>sys.stderr, " \r\n \r\n \t=============================================== install_peer_certs  TRUSTED_GIDS %s   " %(trusted_gids)
113                 for trusted_gid in trusted_gids: 
114                     print>>sys.stderr, " \r\n \r\n \t=============================================== install_peer_certs  trusted_gids%s   " %(trusted_gid)
115                     # default message
116                     message = "interface: %s\t" % (api.interface)
117                     message += "unable to install trusted gid for %s" % \
118                                (new_hrn) 
119                     print>>sys.stderr, " \r\n \r\n \t=============================================== install_peer_certs   message %s   " %(message)
120                     gid = GID(string=trusted_gid['value'][0])
121                     print>>sys.stderr, " \r\n \r\n \t=============================================== install_peer_certs   gid %s   " %(gid)
122                     peer_gids.append(gid)
123                     if gid.get_hrn() == new_hrn:
124                         gid_filename = os.path.join(trusted_certs_dir, '%s.gid' % new_hrn)
125                         #gid.save_to_file(gid_filename, save_parents=True)
126                         message = "installed trusted cert for %s" % new_hrn
127                     # log the message
128                     api.logger.info(message)
129         except:
130             message = "interface: %s\tunable to install trusted gid for %s" % \
131                         (api.interface, new_hrn)
132             api.logger.log_exc(message)
133     # doesnt matter witch one
134     update_cert_records(peer_gids)
135
136 def update_cert_records(gids):
137     """
138     Make sure there is a record in the registry for the specified gids. 
139     Removes old records from the db.
140     """
141     # import SfaTable here so this module can be loaded by PlcComponentApi
142     from sfa.storage.table import SfaTable
143     from sfa.storage.record import SfaRecord
144     if not gids:
145         return
146     table = SfaTable()
147     # get records that actually exist in the db
148     gid_urns = [gid.get_urn() for gid in gids]
149     hrns_expected = [gid.get_hrn() for gid in gids]
150     records_found = table.find({'hrn': hrns_expected, 'pointer': -1}) 
151
152     # remove old records
153     for record in records_found:
154         if record['hrn'] not in hrns_expected and \
155             record['hrn'] != self.api.config.SFA_INTERFACE_HRN:
156             table.remove(record)
157
158     # TODO: store urn in the db so we do this in 1 query 
159     for gid in gids:
160         hrn, type = gid.get_hrn(), gid.get_type()
161         print>>sys.stderr, " \r\n \r\n  update_cert_records  hrn,%s type %s"%(hrn, type)       
162         record = table.find({'hrn': hrn, 'type': type, 'pointer': -1})
163         if not record:
164             record = {
165                 'hrn': hrn, 'type': type, 'pointer': -1,
166                 'authority': get_authority(hrn),
167                 'gid': gid.save_to_string(save_parents=True),
168             }
169             record = SfaRecord(dict=record)
170             print>>sys.stderr, " \r\n \r\rn record %s "%(record)
171             #table.insert(record)
172         
173 def main():
174     # Generate command line parser
175     parser = OptionParser(usage="sfa-start.py [options]")
176     parser.add_option("-r", "--registry", dest="registry", action="store_true",
177          help="run registry server", default=False)
178     parser.add_option("-s", "--slicemgr", dest="sm", action="store_true",
179          help="run slice manager", default=False)
180     parser.add_option("-a", "--aggregate", dest="am", action="store_true",
181          help="run aggregate manager", default=False)
182     parser.add_option("-c", "--component", dest="cm", action="store_true",
183          help="run component server", default=False)
184     parser.add_option("-t", "--trusted-certs", dest="trusted_certs", action="store_true",
185          help="refresh trusted certs", default=False)
186     parser.add_option("-d", "--daemon", dest="daemon", action="store_true",
187          help="Run as daemon.", default=False)
188     (options, args) = parser.parse_args()
189     
190     config = Config()
191     logger.setLevelFromOptVerbose(config.SFA_API_LOGLEVEL)
192     
193
194     # ge the server's key and cert
195     hierarchy = Hierarchy()
196     auth_info = hierarchy.get_interface_auth_info()
197     server_key_file = auth_info.get_privkey_filename()
198     server_cert_file = auth_info.get_gid_filename() 
199     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)
200     # ensure interface cert is present in trusted roots dir
201     trusted_roots = TrustedRoots(config.get_trustedroots_dir())
202     trusted_roots.add_gid(GID(filename=server_cert_file))
203     if (options.daemon):  daemon()
204     
205     if options.trusted_certs:
206         install_peer_certs(server_key_file, server_cert_file)   
207     
208     # start registry server
209     if (options.registry):
210         from sfa.server.registry import Registry
211         r = Registry("", config.SFA_REGISTRY_PORT, server_key_file, server_cert_file)
212         r.start()
213
214     if (options.am):
215         from sfa.server.aggregate import Aggregate
216         a = Aggregate("", config.SFA_AGGREGATE_PORT, server_key_file, server_cert_file)
217         a.start()
218
219     # start slice manager
220     if (options.sm):
221         from sfa.server.slicemgr import SliceMgr
222         s = SliceMgr("", config.SFA_SM_PORT, server_key_file, server_cert_file)
223         s.start()
224
225     if (options.cm):
226         from sfa.server.component import Component
227         c = Component("", config.component_port, server_key_file, server_cert_file)
228 #        c = Component("", config.SFA_COMPONENT_PORT, server_key_file, server_cert_file)
229         c.start()
230
231 if __name__ == "__main__":
232     try:
233         main()
234     except:
235         logger.log_exc_critical("SFA server is exiting")