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
43 from sfa.trust.gid import GID
44 from sfa.trust.trustedroots import TrustedRoots
45 from sfa.trust.certificate import Keypair, Certificate
46 from sfa.trust.hierarchy import Hierarchy
47 from sfa.trust.gid import GID
49 from sfa.server.sfaapi import SfaApi
51 from sfa.server.registry import Registries
52 from sfa.server.aggregate import Aggregates
54 # after http://www.erlenstar.demon.co.uk/unix/faq_2.html
56 """Daemonize the current process."""
57 if os.fork() != 0: os._exit(0)
59 if os.fork() != 0: os._exit(0)
61 devnull = os.open(os.devnull, os.O_RDWR)
63 # xxx fixme - this is just to make sure that nothing gets stupidly lost - should use devnull
64 logdir='/var/log/httpd'
65 # when installed in standalone we might not have httpd installed
66 if not os.path.isdir(logdir): os.mkdir('/var/log/httpd')
67 crashlog = os.open('%s/sfa_access_log'%logdir, os.O_RDWR | os.O_APPEND | os.O_CREAT, 0644)
72 def install_peer_certs(server_key_file, server_cert_file):
74 Attempt to install missing trusted gids and db records for
75 our federated interfaces
77 # Attempt to get any missing peer gids
78 # There should be a gid file in /etc/sfa/trusted_roots for every
79 # peer registry found in in the registries.xml config file. If there
80 # are any missing gids, request a new one from the peer registry.
81 api = SfaApi(key_file = server_key_file, cert_file = server_cert_file)
82 registries = Registries()
83 aggregates = Aggregates()
84 interfaces = dict(registries.items() + aggregates.items())
85 gids_current = api.auth.trusted_cert_list
86 hrns_current = [gid.get_hrn() for gid in gids_current]
87 hrns_expected = set([hrn for hrn in interfaces])
88 new_hrns = set(hrns_expected).difference(hrns_current)
89 #gids = self.get_peer_gids(new_hrns) + gids_current
94 trusted_certs_dir = api.config.get_trustedroots_dir()
95 for new_hrn in new_hrns:
96 if not new_hrn: continue
97 # the gid for this interface should already be installed
98 if new_hrn == api.config.SFA_INTERFACE_HRN: continue
100 # get gid from the registry
101 url = interfaces[new_hrn].get_url()
102 interface = interfaces[new_hrn].server_proxy(server_key_file, server_cert_file, timeout=30)
103 # skip non sfa aggregates
104 server_version = api.get_cached_server_version(interface)
105 if 'sfa' not in server_version:
106 logger.info("get_trusted_certs: skipping non sfa aggregate: %s" % new_hrn)
109 trusted_gids = interface.get_trusted_certs()
111 # the gid we want should be the first one in the list,
113 for trusted_gid in trusted_gids:
115 message = "interface: %s\t" % (api.interface)
116 message += "unable to install trusted gid for %s" % \
118 gid = GID(string=trusted_gids[0])
119 peer_gids.append(gid)
120 if gid.get_hrn() == new_hrn:
121 gid_filename = os.path.join(trusted_certs_dir, '%s.gid' % new_hrn)
122 gid.save_to_file(gid_filename, save_parents=True)
123 message = "installed trusted cert for %s" % new_hrn
125 api.logger.info(message)
127 message = "interface: %s\tunable to install trusted gid for %s" % \
128 (api.interface, new_hrn)
129 api.logger.log_exc(message)
130 # doesnt matter witch one
131 update_cert_records(peer_gids)
133 def update_cert_records(gids):
135 Make sure there is a record in the registry for the specified gids.
136 Removes old records from the db.
138 # import SfaTable here so this module can be loaded by PlcComponentApi
139 from sfa.util.table import SfaTable
140 from sfa.util.record import SfaRecord
144 # get records that actually exist in the db
145 gid_urns = [gid.get_urn() for gid in gids]
146 hrns_expected = [gid.get_hrn() for gid in gids]
147 records_found = table.find({'hrn': hrns_expected, 'pointer': -1})
150 for record in records_found:
151 if record['hrn'] not in hrns_expected and \
152 record['hrn'] != self.api.config.SFA_INTERFACE_HRN:
155 # TODO: store urn in the db so we do this in 1 query
157 hrn, type = gid.get_hrn(), gid.get_type()
158 record = table.find({'hrn': hrn, 'type': type, 'pointer': -1})
161 'hrn': hrn, 'type': type, 'pointer': -1,
162 'authority': get_authority(hrn),
163 'gid': gid.save_to_string(save_parents=True),
165 record = SfaRecord(dict=record)
169 # Generate command line parser
170 parser = OptionParser(usage="sfa-start.py [options]")
171 parser.add_option("-r", "--registry", dest="registry", action="store_true",
172 help="run registry server", default=False)
173 parser.add_option("-s", "--slicemgr", dest="sm", action="store_true",
174 help="run slice manager", default=False)
175 parser.add_option("-a", "--aggregate", dest="am", action="store_true",
176 help="run aggregate manager", default=False)
177 parser.add_option("-c", "--component", dest="cm", action="store_true",
178 help="run component server", default=False)
179 parser.add_option("-t", "--trusted-certs", dest="trusted_certs", action="store_true",
180 help="refresh trusted certs", default=False)
181 parser.add_option("-v", "--verbose", action="count", dest="verbose", default=0,
182 help="verbose mode - cumulative")
183 parser.add_option("-d", "--daemon", dest="daemon", action="store_true",
184 help="Run as daemon.", default=False)
185 (options, args) = parser.parse_args()
188 if config.SFA_API_DEBUG: pass
190 # ge the server's key and cert
191 hierarchy = Hierarchy()
192 auth_info = hierarchy.get_interface_auth_info()
193 server_key_file = auth_info.get_privkey_filename()
194 server_cert_file = auth_info.get_gid_filename()
196 # ensure interface cert is present in trusted roots dir
197 trusted_roots = TrustedRoots(config.get_trustedroots_dir())
198 trusted_roots.add_gid(GID(filename=server_cert_file))
199 if (options.daemon): daemon()
201 if options.trusted_certs:
202 install_peer_certs(server_key_file, server_cert_file)
204 # start registry server
205 if (options.registry):
206 from sfa.server.registry import Registry
207 r = Registry("", config.SFA_REGISTRY_PORT, server_key_file, server_cert_file)
211 from sfa.server.aggregate import Aggregate
212 a = Aggregate("", config.SFA_AGGREGATE_PORT, server_key_file, server_cert_file)
215 # start slice manager
217 from sfa.server.slicemgr import SliceMgr
218 s = SliceMgr("", config.SFA_SM_PORT, server_key_file, server_cert_file)
222 from sfa.server.component import Component
223 c = Component("", config.component_port, server_key_file, server_cert_file)
224 # c = Component("", config.SFA_COMPONENT_PORT, server_key_file, server_cert_file)
227 if __name__ == "__main__":
231 logger.log_exc_critical("SFA server is exiting")