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.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 ### xxx todo not in the config yet
33 from optparse import OptionParser
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 from sfa.server.sfaapi import SfaApi
44 from sfa.server.registry import Registries
45 from sfa.server.aggregate import Aggregates
46 from sfa.client.return_value import ReturnValue
48 # after http://www.erlenstar.demon.co.uk/unix/faq_2.html
50 """Daemonize the current process."""
51 if os.fork() != 0: os._exit(0)
53 if os.fork() != 0: os._exit(0)
55 devnull = os.open(os.devnull, os.O_RDWR)
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)
66 def install_peer_certs(server_key_file, server_cert_file):
68 Attempt to install missing trusted gids and db records for
69 our federated interfaces
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 api = SfaApi(key_file = server_key_file, cert_file = server_cert_file)
76 registries = Registries()
77 aggregates = Aggregates()
78 interfaces = dict(registries.items() + aggregates.items())
79 gids_current = api.auth.trusted_cert_list
80 hrns_current = [gid.get_hrn() for gid in gids_current]
81 hrns_expected = set([hrn for hrn in interfaces])
82 new_hrns = set(hrns_expected).difference(hrns_current)
83 #gids = self.get_peer_gids(new_hrns) + gids_current
87 trusted_certs_dir = api.config.get_trustedroots_dir()
88 for new_hrn in new_hrns:
89 if not new_hrn: continue
90 # the gid for this interface should already be installed
91 if new_hrn == api.config.SFA_INTERFACE_HRN: continue
93 # get gid from the registry
94 url = interfaces[new_hrn].get_url()
95 interface = interfaces[new_hrn].server_proxy(server_key_file, server_cert_file, timeout=30)
96 # skip non sfa aggregates
97 server_version = api.get_cached_server_version(interface)
98 if 'sfa' not in server_version:
99 logger.info("get_trusted_certs: skipping non sfa aggregate: %s" % new_hrn)
101 trusted_gids = ReturnValue.get_value(interface.get_trusted_certs())
103 # the gid we want should be the first one in the list,
105 for trusted_gid in trusted_gids:
107 message = "interface: %s\t" % (api.interface)
108 message += "unable to install trusted gid for %s" % \
110 gid = GID(string=trusted_gid)
111 peer_gids.append(gid)
112 if gid.get_hrn() == new_hrn:
113 gid_filename = os.path.join(trusted_certs_dir, '%s.gid' % new_hrn)
114 gid.save_to_file(gid_filename, save_parents=True)
115 message = "installed trusted cert for %s" % new_hrn
117 api.logger.info(message)
119 message = "interface: %s\tunable to install trusted gid for %s" % \
120 (api.interface, new_hrn)
121 api.logger.log_exc(message)
122 # doesnt matter witch one
123 update_cert_records(peer_gids)
125 def update_cert_records(gids):
127 Make sure there is a record in the registry for the specified gids.
128 Removes old records from the db.
130 # import db stuff here here so this module can be loaded by PlcComponentApi
131 from sfa.storage.alchemy import dbsession
132 from sfa.storage.model import RegRecord
135 # get records that actually exist in the db
136 gid_urns = [gid.get_urn() for gid in gids]
137 hrns_expected = [gid.get_hrn() for gid in gids]
138 records_found = dbsession.query(RegRecord).\
139 filter_by(pointer=-1).filter(RegRecord.hrn.in_(hrns_expected)).all()
142 for record in records_found:
143 if record.hrn not in hrns_expected and \
144 record.hrn != self.api.config.SFA_INTERFACE_HRN:
145 dbsession.delete(record)
147 # TODO: store urn in the db so we do this in 1 query
149 hrn, type = gid.get_hrn(), gid.get_type()
150 record = dbsession.query(RegRecord).filter_by(hrn=hrn, type=type,pointer=-1).first()
152 record = RegRecord (dict= {'type':type,
154 'authority': get_authority(hrn),
155 'gid': gid.save_to_string(save_parents=True),
157 dbsession.add(record)
161 # Generate command line parser
162 parser = OptionParser(usage="sfa-start.py [options]")
163 parser.add_option("-r", "--registry", dest="registry", action="store_true",
164 help="run registry server", default=False)
165 parser.add_option("-s", "--slicemgr", dest="sm", action="store_true",
166 help="run slice manager", default=False)
167 parser.add_option("-a", "--aggregate", dest="am", action="store_true",
168 help="run aggregate manager", default=False)
169 parser.add_option("-c", "--component", dest="cm", action="store_true",
170 help="run component server", default=False)
171 parser.add_option("-t", "--trusted-certs", dest="trusted_certs", action="store_true",
172 help="refresh trusted certs", default=False)
173 parser.add_option("-d", "--daemon", dest="daemon", action="store_true",
174 help="Run as daemon.", default=False)
175 (options, args) = parser.parse_args()
178 logger.setLevelFromOptVerbose(config.SFA_API_LOGLEVEL)
181 # ge the server's key and cert
182 hierarchy = Hierarchy()
183 auth_info = hierarchy.get_interface_auth_info()
184 server_key_file = auth_info.get_privkey_filename()
185 server_cert_file = auth_info.get_gid_filename()
186 # ensure interface cert is present in trusted roots dir
187 trusted_roots = TrustedRoots(config.get_trustedroots_dir())
188 trusted_roots.add_gid(GID(filename=server_cert_file))
189 if (options.daemon): daemon()
191 if options.trusted_certs:
192 install_peer_certs(server_key_file, server_cert_file)
194 # start registry server
195 if (options.registry):
196 from sfa.server.registry import Registry
197 r = Registry("", config.SFA_REGISTRY_PORT, server_key_file, server_cert_file)
201 from sfa.server.aggregate import Aggregate
202 a = Aggregate("", config.SFA_AGGREGATE_PORT, server_key_file, server_cert_file)
205 # start slice manager
207 from sfa.server.slicemgr import SliceMgr
208 s = SliceMgr("", config.SFA_SM_PORT, server_key_file, server_cert_file)
212 from sfa.server.component import Component
213 c = Component("", config.component_port, server_key_file, server_cert_file)
214 # c = Component("", config.SFA_COMPONENT_PORT, server_key_file, server_cert_file)
217 if __name__ == "__main__":
221 logger.log_exc_critical("SFA server is exiting")