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 from sfa.trust.gid import GID
43 from sfa.trust.trustedroots import TrustedRoots
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 logdir='/var/log/httpd'
64 # when installed in standalone we might not have httpd installed
65 if not os.path.isdir(logdir): os.mkdir('/var/log/httpd')
66 crashlog = os.open('%s/sfa_access_log'%logdir, os.O_RDWR | os.O_APPEND | os.O_CREAT, 0644)
71 def install_peer_certs(server_key_file, server_cert_file):
73 Attempt to install missing trusted gids and db records for
74 our federated interfaces
76 # Attempt to get any missing peer gids
77 # There should be a gid file in /etc/sfa/trusted_roots for every
78 # peer registry found in in the registries.xml config file. If there
79 # are any missing gids, request a new one from the peer registry.
80 api = SfaApi(key_file = server_key_file, cert_file = server_cert_file)
81 registries = Registries()
82 aggregates = Aggregates()
83 interfaces = dict(registries.items() + aggregates.items())
84 gids_current = api.auth.trusted_cert_list
85 hrns_current = [gid.get_hrn() for gid in gids_current]
86 hrns_expected = set([hrn for hrn in interfaces])
87 new_hrns = set(hrns_expected).difference(hrns_current)
88 #gids = self.get_peer_gids(new_hrns) + gids_current
93 trusted_certs_dir = api.config.get_trustedroots_dir()
94 for new_hrn in new_hrns:
95 if not new_hrn: continue
96 # the gid for this interface should already be installed
97 if new_hrn == api.config.SFA_INTERFACE_HRN: continue
99 # get gid from the registry
100 url = interfaces[new_hrn].get_url()
101 interface = interfaces[new_hrn].server_proxy(server_key_file, server_cert_file, timeout=30)
102 # skip non sfa aggregates
103 server_version = api.get_cached_server_version(interface)
104 if 'sfa' not in server_version:
105 logger.info("get_trusted_certs: skipping non sfa aggregate: %s" % new_hrn)
108 trusted_gids = interface.get_trusted_certs()
110 # the gid we want should be the first one in the list,
112 for trusted_gid in trusted_gids:
114 message = "interface: %s\t" % (api.interface)
115 message += "unable to install trusted gid for %s" % \
117 gid = GID(string=trusted_gids[0])
118 peer_gids.append(gid)
119 if gid.get_hrn() == new_hrn:
120 gid_filename = os.path.join(trusted_certs_dir, '%s.gid' % new_hrn)
121 gid.save_to_file(gid_filename, save_parents=True)
122 message = "installed trusted cert for %s" % new_hrn
124 api.logger.info(message)
126 message = "interface: %s\tunable to install trusted gid for %s" % \
127 (api.interface, new_hrn)
128 api.logger.log_exc(message)
129 # doesnt matter witch one
130 update_cert_records(peer_gids)
132 def update_cert_records(gids):
134 Make sure there is a record in the registry for the specified gids.
135 Removes old records from the db.
137 # import SfaTable here so this module can be loaded by PlcComponentApi
138 from sfa.storage.table import SfaTable
139 from sfa.storage.record import SfaRecord
143 # get records that actually exist in the db
144 gid_urns = [gid.get_urn() for gid in gids]
145 hrns_expected = [gid.get_hrn() for gid in gids]
146 records_found = table.find({'hrn': hrns_expected, 'pointer': -1})
149 for record in records_found:
150 if record['hrn'] not in hrns_expected and \
151 record['hrn'] != self.api.config.SFA_INTERFACE_HRN:
154 # TODO: store urn in the db so we do this in 1 query
156 hrn, type = gid.get_hrn(), gid.get_type()
157 record = table.find({'hrn': hrn, 'type': type, 'pointer': -1})
160 'hrn': hrn, 'type': type, 'pointer': -1,
161 'authority': get_authority(hrn),
162 'gid': gid.save_to_string(save_parents=True),
164 record = SfaRecord(dict=record)
168 # Generate command line parser
169 parser = OptionParser(usage="sfa-start.py [options]")
170 parser.add_option("-r", "--registry", dest="registry", action="store_true",
171 help="run registry server", default=False)
172 parser.add_option("-s", "--slicemgr", dest="sm", action="store_true",
173 help="run slice manager", default=False)
174 parser.add_option("-a", "--aggregate", dest="am", action="store_true",
175 help="run aggregate manager", default=False)
176 parser.add_option("-c", "--component", dest="cm", action="store_true",
177 help="run component server", default=False)
178 parser.add_option("-t", "--trusted-certs", dest="trusted_certs", action="store_true",
179 help="refresh trusted certs", default=False)
180 parser.add_option("-v", "--verbose", action="count", dest="verbose", default=0,
181 help="verbose mode - cumulative")
182 parser.add_option("-d", "--daemon", dest="daemon", action="store_true",
183 help="Run as daemon.", default=False)
184 (options, args) = parser.parse_args()
187 if config.SFA_API_DEBUG: pass
189 # ge the server's key and cert
190 hierarchy = Hierarchy()
191 auth_info = hierarchy.get_interface_auth_info()
192 server_key_file = auth_info.get_privkey_filename()
193 server_cert_file = auth_info.get_gid_filename()
195 # ensure interface cert is present in trusted roots dir
196 trusted_roots = TrustedRoots(config.get_trustedroots_dir())
197 trusted_roots.add_gid(GID(filename=server_cert_file))
198 if (options.daemon): daemon()
200 if options.trusted_certs:
201 install_peer_certs(server_key_file, server_cert_file)
203 # start registry server
204 if (options.registry):
205 from sfa.server.registry import Registry
206 r = Registry("", config.SFA_REGISTRY_PORT, server_key_file, server_cert_file)
210 from sfa.server.aggregate import Aggregate
211 a = Aggregate("", config.SFA_AGGREGATE_PORT, server_key_file, server_cert_file)
214 # start slice manager
216 from sfa.server.slicemgr import SliceMgr
217 s = SliceMgr("", config.SFA_SM_PORT, server_key_file, server_cert_file)
221 from sfa.server.component import Component
222 c = Component("", config.component_port, server_key_file, server_cert_file)
223 # c = Component("", config.SFA_COMPONENT_PORT, server_key_file, server_cert_file)
226 if __name__ == "__main__":
230 logger.log_exc_critical("SFA server is exiting")