3 # PlanetLab SFA implementation
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.
9 # There are several items that need to be done before starting the servers.
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.
16 # 1) Import the existing planetlab database, creating the
17 # appropriate SFA records. This is done by running the "sfa-import-plc.py" tool.
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,
23 # mkdir trusted_roots; cp authorities/planetlab.gid trusted_roots/
25 # TODO: Can all three servers use the same "registry" certificate?
28 # TCP ports for the three servers
32 ### xxx todo not in the config yet
37 from optparse import OptionParser
39 from sfa.util.sfalogging import logger
40 from sfa.util.xrn import get_authority, hrn_to_urn
41 from sfa.util.config import Config
42 import sfa.client.xmlrpcprotocol as xmlrpcprotocol
44 from sfa.trust.certificate import Keypair, Certificate
45 from sfa.trust.hierarchy import Hierarchy
46 from sfa.trust.gid import GID
48 from sfa.server.sfaapi import SfaApi
50 from sfa.server.registry import Registries
51 from sfa.server.aggregate import Aggregates
53 # after http://www.erlenstar.demon.co.uk/unix/faq_2.html
55 """Daemonize the current process."""
56 if os.fork() != 0: os._exit(0)
58 if os.fork() != 0: os._exit(0)
60 devnull = os.open(os.devnull, os.O_RDWR)
62 # xxx fixme - this is just to make sure that nothing gets stupidly lost - should use devnull
63 crashlog = os.open('/var/log/httpd/sfa_access_log', os.O_RDWR | os.O_APPEND | os.O_CREAT, 0644)
68 def install_peer_certs(server_key_file, server_cert_file):
70 Attempt to install missing trusted gids and db records for
71 our federated interfaces
73 # Attempt to get any missing peer gids
74 # There should be a gid file in /etc/sfa/trusted_roots for every
75 # peer registry found in in the registries.xml config file. If there
76 # are any missing gids, request a new one from the peer registry.
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
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
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 server_version = api.get_cached_server_version(interface)
101 if 'sfa' not in server_version:
102 logger.info("get_trusted_certs: skipping non sfa aggregate: %s" % new_hrn)
105 trusted_gids = interface.get_trusted_certs()
107 # the gid we want should be the first one in the list,
109 for trusted_gid in trusted_gids:
111 message = "interface: %s\t" % (api.interface)
112 message += "unable to install trusted gid for %s" % \
114 gid = GID(string=trusted_gids[0])
115 peer_gids.append(gid)
116 if gid.get_hrn() == new_hrn:
117 gid_filename = os.path.join(trusted_certs_dir, '%s.gid' % new_hrn)
118 gid.save_to_file(gid_filename, save_parents=True)
119 message = "installed trusted cert for %s" % new_hrn
121 api.logger.info(message)
123 message = "interface: %s\tunable to install trusted gid for %s" % \
124 (api.interface, new_hrn)
125 api.logger.log_exc(message)
126 # doesnt matter witch one
127 update_cert_records(peer_gids)
129 def update_cert_records(gids):
131 Make sure there is a record in the registry for the specified gids.
132 Removes old records from the db.
134 # import SfaTable here so this module can be loaded by PlcComponentApi
135 from sfa.util.table import SfaTable
136 from sfa.util.record import SfaRecord
140 # get records that actually exist in the db
141 gid_urns = [gid.get_urn() for gid in gids]
142 hrns_expected = [gid.get_hrn() for gid in gids]
143 records_found = table.find({'hrn': hrns_expected, 'pointer': -1})
146 for record in records_found:
147 if record['hrn'] not in hrns_expected and \
148 record['hrn'] != self.api.config.SFA_INTERFACE_HRN:
151 # TODO: store urn in the db so we do this in 1 query
153 hrn, type = gid.get_hrn(), gid.get_type()
154 record = table.find({'hrn': hrn, 'type': type, 'pointer': -1})
157 'hrn': hrn, 'type': type, 'pointer': -1,
158 'authority': get_authority(hrn),
159 'gid': gid.save_to_string(save_parents=True),
161 record = SfaRecord(dict=record)
165 # Generate command line parser
166 parser = OptionParser(usage="sfa-start.py [options]")
167 parser.add_option("-r", "--registry", dest="registry", action="store_true",
168 help="run registry server", default=False)
169 parser.add_option("-s", "--slicemgr", dest="sm", action="store_true",
170 help="run slice manager", default=False)
171 parser.add_option("-a", "--aggregate", dest="am", action="store_true",
172 help="run aggregate manager", default=False)
173 parser.add_option("-c", "--component", dest="cm", action="store_true",
174 help="run component server", default=False)
175 parser.add_option("-t", "--trusted-certs", dest="trusted_certs", action="store_true",
176 help="refresh trusted certs", default=False)
177 parser.add_option("-v", "--verbose", action="count", dest="verbose", default=0,
178 help="verbose mode - cumulative")
179 parser.add_option("-d", "--daemon", dest="daemon", action="store_true",
180 help="Run as daemon.", default=False)
181 (options, args) = parser.parse_args()
184 if config.SFA_API_DEBUG: pass
186 # ge the server's key and cert
187 hierarchy = Hierarchy()
188 auth_info = hierarchy.get_interface_auth_info()
189 server_key_file = auth_info.get_privkey_filename()
190 server_cert_file = auth_info.get_gid_filename()
192 if (options.daemon): daemon()
194 if options.trusted_certs:
195 install_peer_certs(server_key_file, server_cert_file)
197 # start registry server
198 if (options.registry):
199 from sfa.server.registry import Registry
200 r = Registry("", config.SFA_REGISTRY_PORT, server_key_file, server_cert_file)
204 from sfa.server.aggregate import Aggregate
205 a = Aggregate("", config.SFA_AGGREGATE_PORT, server_key_file, server_cert_file)
208 # start slice manager
210 from sfa.server.slicemgr import SliceMgr
211 s = SliceMgr("", config.SFA_SM_PORT, server_key_file, server_cert_file)
215 from sfa.server.component import Component
216 c = Component("", config.component_port, server_key_file, server_cert_file)
217 # c = Component("", config.SFA_COMPONENT_PORT, server_key_file, server_cert_file)
220 if __name__ == "__main__":
224 logger.log_exc_critical("SFA server is exiting")